Chinaunix首页 | 论坛 | 博客
  • 博客访问: 174372
  • 博文数量: 43
  • 博客积分: 827
  • 博客等级: 准尉
  • 技术积分: 487
  • 用 户 组: 普通用户
  • 注册时间: 2012-01-26 19:19
文章分类

全部博文(43)

文章存档

2015年(1)

2014年(1)

2013年(5)

2012年(36)

我的朋友

分类: WINDOWS

2012-05-06 17:31:27

CAnimatedMeshScenenNode

几个重要的接口:
1:OnAnimate
在前面说过该接口负责时间驱动,因此在这里的该接口中先根据过去的时间计算出现在的Frame,然后在根据Frame得到当前的Mesh。

buildFrameNr(timeMs-LastTimeMs);                // Compute current frame
...
scene::IMesh * mesh = getMeshForCurrentFrame();        // Get current frame mesh

对于getMeshForCurrentFrame中如果是SkinnedMesh的话
        // animate the mesh , update the local matrix(Local Motion)
        skinnedMesh->animateMesh(getFrameNr(), 1.0f);
        // Update the skinned mesh for the current joint transforms.
        // Update the global matrix according to the Local Matrices. And transform the mesh buffer.
        skinnedMesh->skinMesh();

2: render
渲染该SkinnedMesh.注意的是Irrlicht对于SkinnedMesh是在CPU中进行Skin的,所以这里对于MeshBuffer的变换只有该AnimationMeshSceneNode的矩阵,并且MeshBuffer的Transformation总是为Identity Matrix。

点击(此处)折叠或打开

  1. // only render transparent buffer if this is the transparent render pass
  2. // and solid only in solid pass
  3. if (transparent == isTransparentPass)
  4. {
  5.         scene::IMeshBuffer* mb = m->getMeshBuffer(i);
  6.         const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
  7.         if (RenderFromIdentity)
  8.                 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
  9.         else if (Mesh->getMeshType() == EAMT_SKINNED)
  10.         // ((SSkinMeshBuffer*)mb)->Transformation always be Identity matrix.
  11.         driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);

  12.         driver->setMaterial(material);
  13.         driver->drawMeshBuffer(mb);
  14.  }

对于SkinnedMesh的实现:
animateMesh:
        // Get the blended position, scale and rotation.
        // 这里主要是根据frame(注意frame不一定是整数值)来插值关键帧。从而得到该Joint(Bone)的Translation, Rotation, Scaling。
        getFrameData(frame, joint, position, joint->positionHint, scale, joint->scaleHint, rotation, joint->rotationHint);
用getFrameData得到这个Joint的三个参数过后,就可以根据这些信息来更新Local Matrix。
buildAll_LocalAnimatedMatrices();
该接口就是根据局每一个Joint的三个参数信息,更新LocalAnimatedMatrix。

skinMesh:
        // Construct all the global animated matrix
        // 这里主要是迭代每一个Joint,根据LocalAnimatedMatrix和Parent-Child关系来更新GlobalAnimatedMatrix。
        buildAll_GlobalAnimatedMatrices();

        // 注意这一段代码是为Software实现的,但是对于//rigid animation Part应该是在HardwareSkinning中使用。

点击(此处)折叠或打开

  1. if (!HardwareSkinning)
  2.         {
  3.                 //Software skin....
  4.                 u32 i;

  5.                 // Note
  6.                 //rigid animation
  7.                 for (i=0; i<AllJoints.size(); ++i)
  8.                 {
  9.                         for (u32 j=0; j<AllJoints[i]->AttachedMeshes.size(); ++j)
  10.                         {
  11.                                 SSkinMeshBuffer* Buffer=(*SkinningBuffers)[ AllJoints[i]->AttachedMeshes[j] ];
  12.                                 Buffer->Transformation=AllJoints[i]->GlobalAnimatedMatrix; // Never called.
  13.                         }
  14.                 }

  15.                 //clear skinning helper array
  16.                 for (i=0; i<Vertices_Moved.size(); ++i)
  17.                         for (u32 j=0; j<Vertices_Moved[i].size(); ++j)
  18.                                 Vertices_Moved[i][j]=false;

  19.                 //skin starting with the root joints
  20.                 // Skin the model
  21.                 // 这里根据已有的GlobalAnimatedMatrix来Transform所有的顶点。这里面实现了Vertex Blend 技术
  22.                 for (i=0; i<RootJoints.size(); ++i)
  23.                         SkinJoint(RootJoints[i], 0);

  24.                 for (i=0; i<SkinningBuffers->size(); ++i)
  25.                         (*SkinningBuffers)[i]->setDirty(EBT_VERTEX);
  26.         }
经过skinMesh过后,这个SkinnedMesh就完成了Skinning过程。


对于CSkinnedMesh中的几个说明:
//! Unnecessary for loaders, will be overwritten on finalize
core::matrix4 GlobalMatrix;            //!< The Combined matrix.
core::matrix4 GlobalAnimatedMatrix;    //!< The current blended global matrix, LocalAnimatedMatrix*Parent::GlobalAnimatedMatrix, Combined Matrix
core::matrix4 LocalAnimatedMatrix;     //!< The current blended local matrix, generated by below three factors, Local Matrix
core::vector3df Animatedposition;      //!< The current blended position
core::vector3df Animatedscale;         //!< The current blended scaling
core::quaternion Animatedrotation;     //!< The current blended rotation
注意这个矩阵:
core::matrix4 GlobalInversedMatrix; //the x format pre-calculates this, In x format, it's offset matrix. Transform the bone to Local bone space. Offet Matrix
这个矩阵在X File中实际上是Offset Matrix.
但是:
在CalculateGlobalMatrices中(在finalize()中被调用,而finalize在该模型被加载好过后才调用)。
if (joint->GlobalInversedMatrix.isIdentity())//might be pre calculated
{
        joint->GlobalInversedMatrix = joint->GlobalMatrix;
        joint->GlobalInversedMatrix.makeInverse(); // slow
}
在X File的Skinned Mesh是没有用处的,而且是错的。他在这里添加这个代码仅仅是为了支持某一种Skinned Animation的模型格式。
GlobalInversedMatrix在skinJoint中被使用,作为Offset Matrix。

阅读(1756) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~