00001 #include "CCal3dSceneNode.h"
00002
00003 #define DUMP_OFFLINE_ANIMATION false
00004
00005 #include <fstream>
00006 #include <vector>
00007
00013 CCal3DSceneNode::CCal3DSceneNode(const char* cf,
00014 irr::scene::ISceneNode* parent,
00015 irr::scene::ISceneManager* mgr, irr::s32 id)
00016 :irr::scene::ISceneNode(parent,mgr,id), configFile(cf)
00017 {
00018 m_scale = 1.0f;
00019 m_blendTime = 0.05f;
00020 m_lodLevel = 1.0f;
00021 lastTick=0;
00022 m_bPaused=false;
00023 bInitialized=false;
00024
00025 mediaPath=configFile.substr(0,configFile.find_last_of("/"));
00026
00027 material.Wireframe=false;
00028 material.Lighting = true;
00029
00030 material.MaterialType=irr::video::EMT_SOLID;
00031 material.ZWriteEnable=true;
00032 material.BackfaceCulling=false;
00033
00034 setDebugDataVisible(false);
00035 }
00036
00037
00038
00040 CCal3DSceneNode::~CCal3DSceneNode()
00041 {
00042 delete m_calModel;
00043 delete m_calCoreModel;
00044 }
00045
00046
00047
00049
00051
00052 void CCal3DSceneNode::OnPreRender()
00053 {
00054 if (bInitialized && IsVisible)
00055 {
00056 SceneManager->registerNodeForRendering(this);
00057 }
00058
00059 irr::scene::ISceneNode::OnPreRender();
00060 }
00061
00062
00063
00064 void CCal3DSceneNode::render()
00065 {
00066
00067 if(bInitialized)
00068 {
00069 irr::video::IVideoDriver* driver=SceneManager->getVideoDriver();
00070
00071
00072 driver->setTransform(irr::video::ETS_WORLD, AbsoluteTransformation);
00073
00074
00075 irr::video::S3DVertex tmp;
00076 irr::scene::SMeshBuffer mb;
00077
00078 unsigned char meshColor[4];
00079
00080
00081
00082 CalRenderer *pCalRenderer;
00083 pCalRenderer = m_calModel->getRenderer();
00084 pCalRenderer->setNormalization(true);
00085
00086 if(this->DebugDataVisible)
00087 {
00088 irr::video::SMaterial mat;
00089 mat.Wireframe=false;
00090 mat.Lighting=false;
00091 driver->setMaterial(mat);
00092 driver->draw3DBox(Box);
00093
00094 CalSkeleton* pCalSkeleton = m_calModel->getSkeleton();
00095 pCalSkeleton->calculateBoundingBoxes();
00096 std::vector<CalBone*> &vectorCoreBone = pCalSkeleton->getVectorBone();
00097 irr::core::aabbox3df b;
00098 CalVector p[8];
00099 Vector3 v[8];
00100
00101
00102 for(size_t boneId=0;boneId<vectorCoreBone.size();++boneId)
00103 {
00104 CalBone* bone=vectorCoreBone[boneId];
00105 CalBoundingBox & calBoundingBox = bone->getBoundingBox();
00106 calBoundingBox.computePoints(p);
00107
00108 for(int i=0;i<8;++i) v[i].set(p[i].x,p[i].y,p[i].z);
00109
00110 driver->setMaterial(mat);
00111
00112 driver->draw3DLine(v[0],v[1],irr::video::SColor(255,0,0,255));
00113 driver->draw3DLine(v[0],v[2],irr::video::SColor(255,0,0,255));
00114 driver->draw3DLine(v[1],v[3],irr::video::SColor(255,0,0,255));
00115 driver->draw3DLine(v[2],v[3],irr::video::SColor(255,0,0,255));
00116 driver->draw3DLine(v[4],v[5],irr::video::SColor(255,0,0,255));
00117 driver->draw3DLine(v[4],v[6],irr::video::SColor(255,0,0,255));
00118 driver->draw3DLine(v[5],v[7],irr::video::SColor(255,0,0,255));
00119 driver->draw3DLine(v[6],v[7],irr::video::SColor(255,0,0,255));
00120 driver->draw3DLine(v[0],v[4],irr::video::SColor(255,0,0,255));
00121 driver->draw3DLine(v[1],v[5],irr::video::SColor(255,0,0,255));
00122 driver->draw3DLine(v[2],v[6],irr::video::SColor(255,0,0,255));
00123 driver->draw3DLine(v[3],v[7],irr::video::SColor(255,0,0,255));
00124 }
00125 }
00126
00127
00128 if(pCalRenderer->beginRendering())
00129 {
00130
00131 int meshCount;
00132 meshCount = pCalRenderer->getMeshCount();
00133
00134
00135 int meshId;
00136 for(meshId = 0; meshId < meshCount; meshId++)
00137 {
00138
00139 int submeshCount;
00140 submeshCount = pCalRenderer->getSubmeshCount(meshId);
00141
00142
00143 int submeshId;
00144 for(submeshId = 0; submeshId < submeshCount; submeshId++)
00145 {
00146
00147 if(pCalRenderer->selectMeshSubmesh(meshId, submeshId))
00148 {
00149
00150
00151 pCalRenderer->getAmbientColor(&meshColor[0]);
00152 material.AmbientColor.set(meshColor[3],meshColor[0],meshColor[1],meshColor[2]);
00153
00154
00155 pCalRenderer->getDiffuseColor(&meshColor[0]);
00156 material.DiffuseColor.set(meshColor[3],meshColor[0],meshColor[1],meshColor[2]);
00157
00158
00159 pCalRenderer->getSpecularColor(&meshColor[0]);
00160 material.SpecularColor.set(meshColor[3],meshColor[0],meshColor[1],meshColor[2]);
00161
00162
00163 material.Shininess = pCalRenderer->getShininess();
00164
00165
00166 static float meshVertices[30000][3];
00167 int vertexCount;
00168 vertexCount = pCalRenderer->getVertices(&meshVertices[0][0]);
00169
00170
00171 static float meshNormals[30000][3];
00172 int normalsCount=pCalRenderer->getNormals(&meshNormals[0][0]);
00173
00174
00175 static float meshTextureCoordinates[30000][2];
00176 int textureCoordinateCount;
00177 textureCoordinateCount = pCalRenderer->getTextureCoordinates(0, &meshTextureCoordinates[0][0]);
00178
00179
00180 static CalIndex meshFaces[50000][3];
00181 int faceCount =pCalRenderer->getFaces(&meshFaces[0][0]);
00182
00183 if((pCalRenderer->getMapCount() > 0) && (textureCoordinateCount > 0))
00184 {
00185 irr::video::ITexture* t=static_cast<irr::video::ITexture*>(pCalRenderer->getMapUserData(0));
00186 material.Texture1=t;
00187 }
00188
00189 mb.Vertices.clear();
00190 for(int i=0;i<vertexCount;i++)
00191 {
00192 tmp.Pos.set(meshVertices[i][0],meshVertices[i][1],meshVertices[i][2]);
00193 tmp.Normal.set(meshNormals[i][0],meshNormals[i][1],meshNormals[i][2]);
00194 tmp.TCoords.set(meshTextureCoordinates[i][0],meshTextureCoordinates[i][1]);
00195 tmp.Color=irr::video::SColor(255,255,255,255);
00196 mb.Vertices.push_back(tmp);
00197 }
00198
00199 mb.Indices.clear();
00200 for(int i=0; i<faceCount; ++i){
00201 mb.Indices.push_back(meshFaces[i][0]);
00202 mb.Indices.push_back(meshFaces[i][1]);
00203 mb.Indices.push_back(meshFaces[i][2]);
00204 }
00205
00206
00207 driver->setMaterial(material);
00208
00209 driver->drawIndexedTriangleList(mb.Vertices.const_pointer(),
00210 mb.Vertices.size(),mb.Indices.const_pointer(),faceCount);
00211
00212
00213
00214 }
00215 }
00216 }
00217
00218
00219 pCalRenderer->endRendering();
00220
00221 }
00222 }
00223 }
00224
00225
00226
00227 void CCal3DSceneNode::OnPostRender(irr::u32 timeMs)
00228 {
00229
00230 float elapsedSeconds;
00231 elapsedSeconds = (float)(timeMs - lastTick) / 1000.0f;
00232
00233
00234 if(!m_bPaused && lastTick!=0)
00235 {
00236
00237 if(m_calCoreModel->getCoreAnimationCount() > 1)
00238 {
00239 m_leftAnimationTime -= elapsedSeconds;
00240 if(m_leftAnimationTime <= m_blendTime)
00241 {
00242
00243 m_currentAnimationId = (m_currentAnimationId + 1) % m_calCoreModel->getCoreAnimationCount();
00244
00245
00246 m_calModel->getMixer()->executeAction(m_currentAnimationId, m_leftAnimationTime, m_blendTime);
00247
00248
00249 m_leftAnimationTime = m_calCoreModel->getCoreAnimation(m_currentAnimationId)->getDuration() - m_blendTime;
00250 }
00251 }
00252
00253 m_calModel->update(elapsedSeconds);
00254
00255 CalVector p[8];
00256 m_calModel->getBoundingBox(true).computePoints(p);
00257 Box.reset(p[0].x,p[0].y,p[0].z);
00258 for(int i=0;i<8;++i) Box.addInternalPoint(p[i].x,p[i].y,p[i].z);
00259 }
00260
00261
00262
00263
00264 lastTick = timeMs;
00265
00266 irr::scene::ISceneNode::OnPostRender(timeMs);
00267 }
00268
00269
00270
00271 const irr::core::aabbox3df& CCal3DSceneNode::getBoundingBox() const
00272 {
00273 return Box;
00274 }
00275
00276
00277
00279
00281
00285 bool CCal3DSceneNode::parseModelConfiguration(const std::string &cf)
00286 {
00287 std::string fn;
00288
00289 std::ifstream file;
00290 file.open(cf.c_str(), std::ios::in | std::ios::binary);
00291 if(!file)
00292 {
00293
00294 return false;
00295 }
00296
00297
00298 m_calCoreModel = new CalCoreModel("dummy");
00299 if(!m_calCoreModel)
00300 {
00301
00302 return false;
00303 }
00304
00305
00306 int line;
00307 for(line = 1; ; line++)
00308 {
00309
00310 std::string strBuffer;
00311 std::getline(file, strBuffer);
00312
00313
00314 if(file.eof()) break;
00315
00316
00317 if(!file)
00318 {
00319
00320 return false;
00321 }
00322
00323
00324 std::string::size_type pos;
00325 pos = strBuffer.find_first_not_of(" \t");
00326
00327
00328 if((pos == std::string::npos) || (strBuffer[pos] == '\n') || (strBuffer[pos] == '\r') || (strBuffer[pos] == 0)) continue;
00329
00330
00331 if(strBuffer[pos] == '#') continue;
00332
00333
00334 std::string strKey;
00335 strKey = strBuffer.substr(pos, strBuffer.find_first_of(" =\t\n\r", pos) - pos);
00336 pos += strKey.size();
00337
00338
00339 pos = strBuffer.find_first_not_of(" \t", pos);
00340 if((pos == std::string::npos) || (strBuffer[pos] != '='))
00341 {
00342
00343 return false;
00344 }
00345
00346
00347 pos = strBuffer.find_first_not_of(" \t", pos + 1);
00348
00349
00350 std::string strData;
00351 strData = strBuffer.substr(pos, strBuffer.find_first_of("\n\r", pos) - pos);
00352
00353
00354 if(strKey == "scale")
00355 {
00356
00357 m_scale = float(atof(strData.c_str()));
00358 }
00359 else if(strKey == "skeleton")
00360 {
00361
00362 fn.clear(); fn=mediaPath+"/"+strData;
00363
00364 if(!m_calCoreModel->loadCoreSkeleton(fn))
00365 {
00366
00367 return false;
00368 }
00369 }
00370 else if(strKey == "animation")
00371 {
00372 fn.clear(); fn=mediaPath+"/"+strData;
00373
00374
00375 if(m_calCoreModel->loadCoreAnimation(fn) == -1)
00376 {
00377
00378 return false;
00379 }
00380 }
00381 else if(strKey == "mesh")
00382 {
00383 fn.clear(); fn=mediaPath+"/"+strData;
00384
00385
00386 if(m_calCoreModel->loadCoreMesh(fn) == -1)
00387 {
00388
00389 return false;
00390 }
00391 }
00392 else if(strKey == "material")
00393 {
00394 fn.clear(); fn=mediaPath+"/"+strData;
00395
00396
00397 if(m_calCoreModel->loadCoreMaterial(fn) == -1)
00398 {
00399
00400 return false;
00401 }
00402 }
00403 else
00404 {
00405
00406
00407 }
00408 }
00409
00410
00411 file.close();
00412
00413 return true;
00414 }
00415
00416
00417
00418
00419 bool CCal3DSceneNode::init()
00420 {
00421 bool ok=true;
00422
00423 if(!parseModelConfiguration(configFile))
00424 {
00425 bInitialized=false;
00426 return false;
00427 }
00428
00429 m_calCoreModel->scale(m_scale);
00430
00431
00432
00433
00434
00435 for(int materialId = 0; materialId < m_calCoreModel->getCoreMaterialCount(); materialId++)
00436 {
00437
00438 m_calCoreModel->createCoreMaterialThread(materialId);
00439
00440
00441 m_calCoreModel->setCoreMaterialId(materialId, 0, materialId);
00442 }
00443
00444 m_calCoreModel->getCoreSkeleton()->calculateBoundingBoxes(m_calCoreModel);
00445
00446
00447 for(int materialId = 0; materialId < m_calCoreModel->getCoreMaterialCount(); materialId++)
00448 {
00449
00450 CalCoreMaterial *pCoreMaterial;
00451 pCoreMaterial = m_calCoreModel->getCoreMaterial(materialId);
00452
00453
00454 int mapId;
00455 for(mapId = 0; mapId < pCoreMaterial->getMapCount(); mapId++)
00456 {
00457
00458 std::string fn=mediaPath+"/"+pCoreMaterial->getMapFilename(mapId);
00459
00460
00461 irr::video::ITexture* texture=SceneManager->getVideoDriver()->getTexture(fn.c_str());
00462 if(texture)
00463 {
00464
00465 pCoreMaterial->setMapUserData(mapId, (Cal::UserData)texture);
00466 }
00467 else
00468 {
00469 ok=false;
00470
00471 }
00472
00473 }
00474 }
00475
00476
00477 m_calModel = new CalModel(m_calCoreModel);
00478 if(!m_calModel)
00479 {
00480
00481 return false;
00482 }
00483
00484
00485 int meshId;
00486 for(meshId = 0; meshId < m_calCoreModel->getCoreMeshCount(); meshId++)
00487 {
00488 m_calModel->attachMesh(meshId);
00489 }
00490
00491 m_calModel->setMaterialSet(0);
00492
00493
00494 if(m_calCoreModel->getCoreAnimationCount() > 0)
00495 {
00496 m_currentAnimationId = 0;
00497 m_leftAnimationTime = m_calCoreModel->getCoreAnimation(m_currentAnimationId)->getDuration() - m_blendTime;
00498 if(m_calCoreModel->getCoreAnimationCount() > 1)
00499 {
00500 m_calModel->getMixer()->executeAction(m_currentAnimationId, 0.0f, m_blendTime);
00501 }
00502 else
00503 {
00504 m_calModel->getMixer()->blendCycle(m_currentAnimationId, 1.0f, 0.0f);
00505 }
00506 }
00507 else
00508 {
00509 m_currentAnimationId = -1;
00510 m_leftAnimationTime = -1.0f;
00511 }
00512
00513 m_calModel->setLodLevel(m_lodLevel);
00514 m_calModel->update(0);
00515
00516
00517 CalVector p[8];
00518 m_calModel->getBoundingBox(true).computePoints(p);
00519 Box.reset(p[0].x,p[0].y,p[0].z);
00520 for(int i=0;i<8;++i) Box.addInternalPoint(p[i].x,p[i].y,p[i].z);
00521
00522
00523 bInitialized=ok;
00524
00525 return ok;
00526 }
00527
00529
00531
00532 void CCal3DSceneNode::moveBone(int boneID, CalQuaternion& direction)
00533 {
00534 if (! DUMP_OFFLINE_ANIMATION)
00535 {
00536 CalQuaternion oldPos;
00537 CalQuaternion newPos;
00538 oldPos = getCoreBoneRotation(boneID);
00539 newPos.w = oldPos.w + direction.w;
00540 newPos.x = oldPos.x + direction.x;
00541 newPos.y = oldPos.y + direction.y;
00542 newPos.z = oldPos.z + direction.z;
00543 setBoneRotation(boneID, newPos);
00544 }
00545 else
00546 {
00547 dumpBoneQaternion(boneID);
00548 }
00549 }
00550
00551 CalQuaternion CCal3DSceneNode::getCoreBoneRotation(int boneID)
00552 {
00553 CalQuaternion q(0,0,0,0);
00554 q = m_calCoreModel->getCoreSkeleton()->getCoreBone(boneID)->getRotation();
00555
00556 return q;
00557 }
00558
00559 CalQuaternion CCal3DSceneNode::getBoneRotation(int boneID)
00560 {
00561 CalQuaternion q(0,0,0,0);
00562 q = m_calModel->getSkeleton()->getBone(boneID)->getRotation();
00563
00564 return q;
00565 }
00566
00567 void CCal3DSceneNode::setBoneRotation(int boneID, CalQuaternion& newRotation)
00568 {
00569
00570 m_calModel->getSkeleton()->getBone(boneID)->setRotation(newRotation);
00571 m_calModel->getSkeleton()->calculateState();
00572 }
00573
00574 void CCal3DSceneNode::dumpBoneQaternion(int boneID)
00575 {
00576 CalQuaternion q(0,0,0,0);
00577
00578 q = m_calModel->getSkeleton()->getBone(boneID)->getRotation();
00579
00580
00581 std::cout << "getBoneRotation("<<boneID<<") q: x="<<q.x<<" y="<<q.y<<" z="<<q.z<<" w="<<q.w<<std::endl;
00582
00583 }
00584
00585 float CCal3DSceneNode::quaternionGetMagnitude(CalQuaternion qIn)
00586 {
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 return( sqrt(qIn.w*qIn.w + qIn.x*qIn.x + qIn.y*qIn.y + qIn.z*qIn.z) );
00598
00599 }
00600
00601 void CCal3DSceneNode::quaternionNormalize(CalQuaternion& qInOut)
00602 {
00603
00604
00605
00606
00607
00608
00609
00610 float magnitude = quaternionGetMagnitude(qInOut);
00611 qInOut.x = qInOut.x / magnitude;
00612 qInOut.y = qInOut.y / magnitude;
00613 qInOut.z = qInOut.z / magnitude;
00614 qInOut.w = qInOut.w / magnitude;
00615 }
00616
00617 void CCal3DSceneNode::quaternionToAxisAndAngle(CalQuaternion qIn, CalVector& vOut, float& aOut)
00618 {
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 float s = qIn.x*qIn.x + qIn.y*qIn.y + qIn.z*qIn.z;
00654 vOut.x = qIn.x / s;
00655 vOut.y = qIn.y / s;
00656 vOut.z = qIn.z / s;
00657 aOut = 2 * acos(qIn.w);
00658 }
00659
00660
00661 void CCal3DSceneNode::quaternionToAxisAndAngle(CalQuaternion qIn, CalQuaternion& qOut)
00662 {
00663 CalVector v;
00664 float angle;
00665
00666 quaternionToAxisAndAngle(qIn, v, angle);
00667
00668 qOut.x = v.x;
00669 qOut.y = v.y;
00670 qOut.z = v.z;
00671 qOut.x = angle;
00672
00673 }
00674
00675