00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "nel/misc/debug.h"
00029 #include "3d/lod_character_builder.h"
00030 #include "3d/scene.h"
00031 #include "3d/skeleton_shape.h"
00032 #include "3d/mesh.h"
00033 #include "3d/skeleton_model.h"
00034
00035
00036 using namespace std;
00037 using namespace NLMISC;
00038
00039
00040 namespace NL3D
00041 {
00042
00043
00044
00045 CLodCharacterBuilder::CLodCharacterBuilder()
00046 {
00047 _SkeletonShape= NULL;
00048 _LodBuild= NULL;
00049 _TmpScene= NULL;
00050 }
00051
00052 CLodCharacterBuilder::~CLodCharacterBuilder()
00053 {
00054
00055 if(_TmpScene)
00056 {
00057 _TmpScene->release();
00058 delete _TmpScene;
00059 _TmpScene= NULL;
00060 }
00061 }
00062
00063
00064 void CLodCharacterBuilder::setShape(const std::string &name, CSkeletonShape *skeletonShape, CLodCharacterShapeBuild *lodBuild)
00065 {
00066 nlassert(skeletonShape);
00067 nlassert(lodBuild);
00068
00069
00070 _SkeletonShape= skeletonShape;
00071
00072 _LodBuild= lodBuild;
00073
00074
00075 _BoneRemap.resize(lodBuild->BonesNames.size());
00076 for(uint i=0; i<_BoneRemap.size(); i++)
00077 {
00078 const std::string &boneName= lodBuild->BonesNames[i];
00079 sint32 boneId= _SkeletonShape->getBoneIdByName(boneName);
00080
00081 if(boneId<0)
00082 {
00083 nlwarning("Not found a bone in the skeleton Shape: %s", boneName.c_str());
00084
00085 _BoneRemap[i]= 0;
00086 }
00087 else
00088
00089 _BoneRemap[i]= boneId;
00090 }
00091
00092
00093 _LodCharacterShape.buildMesh(name, *_LodBuild);
00094
00095
00096 if(!_TmpScene)
00097 {
00098 _TmpScene= new CScene;
00099
00100 CScene::registerBasics();
00101
00102 _TmpScene->initDefaultTravs();
00103
00104
00105 _TmpScene->initDefaultRoots();
00106
00107
00108 _TmpScene->initGlobalnstanceGroup();
00109
00110 _TmpScene->initCoarseMeshManager ();
00111
00112 _TmpScene->initQuadGridClipManager ();
00113 }
00114 }
00115
00116
00117
00118 void CLodCharacterBuilder::addAnim(const char *animName, CAnimation *animation, float frameRate)
00119 {
00120 nlassert(frameRate>0);
00121 nlassert(animation);
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 CAnimationSet *tmpAnimationSet= new CAnimationSet;
00135 tmpAnimationSet->addAnimation(animName, animation);
00136 tmpAnimationSet->build();
00137
00138 CChannelMixer *tmpChannelMixer= new CChannelMixer;
00139 tmpChannelMixer->setAnimationSet(tmpAnimationSet);
00140
00141
00142
00143
00144 CSkeletonModel *skeleton= (CSkeletonModel*)_SkeletonShape->createInstance(*_TmpScene);
00145
00146 skeleton->registerToChannelMixer(tmpChannelMixer, "");
00147
00148 uint animID = tmpAnimationSet->getAnimationIdByName(animName);
00149 nlassert(animID != CAnimationSet::NotFound);
00150 tmpChannelMixer->setSlotAnimation(0, animID);
00151
00152
00153
00154
00155 CLodCharacterShape::CAnimBuild dstAnim;
00156 dstAnim.Name= animName;
00157 dstAnim.AnimLength= animation->getEndTime();
00158 dstAnim.NumKeys= (uint)ceil(dstAnim.AnimLength * frameRate);
00159 dstAnim.NumKeys= max(1U, dstAnim.NumKeys);
00160
00161 dstAnim.Keys.resize(_LodCharacterShape.getNumVertices() * dstAnim.NumKeys);
00162
00163
00164
00165
00166 double time=0;
00167 double dt= 1.0/(double)frameRate;
00168 uint64 evalDetaiDate= 0;
00169 for(uint i=0; i<dstAnim.NumKeys; i++, time+= dt)
00170 {
00171
00172 time= min(time, (double)dstAnim.AnimLength);
00173
00174
00175 tmpChannelMixer->setSlotTime(0, (float)time);
00176
00177
00178 tmpChannelMixer->eval(false);
00179 tmpChannelMixer->eval(true, evalDetaiDate++);
00180
00181
00182 skeleton->computeAllBones(CMatrix::Identity);
00183
00184
00185 applySkin(skeleton, &dstAnim.Keys[i*_LodCharacterShape.getNumVertices()]);
00186 }
00187
00188
00189
00190
00191 _LodCharacterShape.addAnim(dstAnim);
00192
00193
00194
00195
00196
00197 _TmpScene->deleteModel(skeleton);
00198
00199 delete tmpChannelMixer;
00200
00201 delete tmpAnimationSet;
00202 }
00203
00204
00205
00206 void CLodCharacterBuilder::applySkin(CSkeletonModel *skeleton, CVector *dstVertices)
00207 {
00208 uint numVerts= _LodBuild->Vertices.size();
00209
00210
00211 for(uint i=0; i<numVerts; i++)
00212 {
00213 CMesh::CSkinWeight &skinWgt= _LodBuild->SkinWeights[i];
00214 CVector &srcVert= _LodBuild->Vertices[i];
00215 CVector &dstVert= dstVertices[i];
00216 dstVert= CVector::Null;
00217
00218 for(uint j=0; j<NL3D_MESH_SKINNING_MAX_MATRIX; j++)
00219 {
00220 float wgt= skinWgt.Weights[j];
00221
00222 if(wgt==0)
00223 {
00224
00225 if(j==0)
00226 dstVert= srcVert;
00227
00228 break;
00229 }
00230 else
00231 {
00232
00233 uint boneId= _BoneRemap[skinWgt.MatrixId[j]];
00234
00235 const CMatrix &boneMat= skeleton->Bones[boneId].getBoneSkinMatrix();
00236
00237 dstVert+= (boneMat * srcVert) * wgt;
00238 }
00239 }
00240 }
00241 }
00242
00243
00244 }