zoukankan      html  css  js  c++  java
  • directx加载ms3d动画模型

    最近刚完成了ms3d模型的加载及动画显示,为了让更多的人容易学会和使用该模型,本人就自己所掌握的内容稍微谈谈。

    说起骨骼动画,大家一定不会陌生,这里本人假定大家都了解骨骼动画的基本原理。如果不熟悉的话可参考《Advanced Animation with DirectX》和《Focus.On.3D.Models》。其中《Advanced Animation with DirectX》讲了基本的骨骼原理和.x文件动画的显示,《Focus.On.3D.Models》讲了骨骼原理、ms3d格式(还有几种)及动画的显示。

    在DirectX下实现ms3d模型与在opengl下有着微妙的不同。本人就是搜索了很多英文网站也只找到了两份有用的源代码,一份是nehe的opengl代码,一份是milkshape写的directx代码。前一份代码阅读性很强,很容易看懂,本人的代码也是参考自它。后一份代码功能强大,但就我来说它不适于开始学习,太复杂了点,而且尽管是用direcxt,里面的坐标也全是基于右手的。

    下面开始实现:由于模型空间为右手系,dx为左手系,因此代码中还得对坐标进行转换
    #pragma pack(push) //保存对齐状态

    #pragma pack(1)//设定为4字节对齐

    //-----------------------ms3d数据-------------------------------
    typedef struct MS3DHeader_TYP
    {
            char m_ID[10];                                // Must be 'MS3D000000'
            int  m_version;                                // File format version (3 or 4)
    } MS3DHeader;

    // Vertex information
    typedef struct MS3DVertex_TYP
    {
            unsigned char m_flags;                        // Editor flags
            float m_vertex[3];                                // World coordinates                
            char m_boneID;                                // -1 = no bone
            unsigned char m_refCount;                // Reference count
    } MS3DVertex;

    // Triangle information
    typedef struct MS3DTriangle_TYP
    {
            unsigned short m_flags;                                // Editor flags
            unsigned short m_vertexIndices[3];        // Vertex indices
            float m_vertexNormals[3][3];                        // Normals (each vertex, x/y/z)
            float m_u[3];                                                // Texture u coordinate
            float m_v[3];                                                // Texture v coordinate
            unsigned char m_smoothingGroup;        // Smoothing group
            unsigned char m_groupIndex;                // Material group
    } MS3DTriangle;

    ///Mesh information
    typedef struct MS3DMesh_TYP
    {
            unsigned char m_flags;                                // Editor flags
            char m_name[32];                                        // Name of group
            unsigned short  m_numTriangles;                // # faces in group
            unsigned short *m_TriangleIndices;        // Face indices
            char m_MaterialIndex;                                // -1 = no material
    } MS3DMesh;

    // Material information
    typedef struct MS3DMaterial_TYP
    {
                char m_name[32];                                        // Material name
                float m_ambient[4];                                        // Ambient colors
                float m_diffuse[4];                                        // Diffuse colors
                float m_specular[4];                                        // Specular colors
                float m_emissive[4];                                        // Emmisive colors
                float m_shininess;                                        // Shininess strength
                float m_transparency;                                // Transparency amount
                char m_mode;                                                // Mode 0-3 0, 1, 2 is unused now
                char m_texture[128];                                        // Texture map .bmp filename
                char m_alphamap[128];                                // Alpha map .bmp filename
    } MS3DMaterial;

    //-------------------------骨骼部分----------------------------
    //        Joint information
    struct MS3DJoint
    {
            char m_flags;
            char m_name[32];
            char m_parentName[32];
            float m_rotation[3];
            float m_translation[3];
            unsigned short m_numRotationKeyframes;
            unsigned short m_numTranslationKeyframes;
    };

    // Keyframe data
    struct MS3DKeyframe
    {
            float m_time;
            float m_parameter[3];
    };

    #pragma pack(pop)

    以上是对整个ms3d文件内部组成的说明,我们使用c++的文件输入来读取其中内容,当然也可以使用其它io方法,只要效果一样即可。
    bool CMs3dMesh:oad(IDirect3DDevice9 *pDevice, const char *filename, float scale, char *TexturePath)
    {
            if ((m_pDevice = pDevice) == NULL)
                    return false;
            
            std::ifstream file(filename, std::ios::in | std::ios::binary);
            //Open the .ms3d model file
            if (file == NULL)
                    return false;

            file.seekg(0, std::ios::end);
            long fileSize = file.tellg();
            file.seekg(0, std::ios::beg);

            char *pBuffer = new char[fileSize];
            file.read(pBuffer, fileSize);
            file.close();

            const unsigned char *pPtr = (const unsigned char *)pBuffer;
                    
            MS3DHeader *pHeader = (MS3DHeader *)pPtr;
            pPtr += sizeof(MS3DHeader);
            if (::strncmp(pHeader->m_ID, "MS3D000000", 10) != 0)
            { 
                    MessageBox(NULL,"id error","ERROR",MB_OK|MB_ICONEXCLAMATION);
                    return false;
            }
            if (pHeader->m_version < 3)// ||Header.m_version > 4)//支持1.5
            {
                    MessageBox(NULL,"version error","ERROR",MB_OK|MB_ICONEXCLAMATION);
                    return false; // "Unhandled file version. Only Milkshape3D Version 1.3 and 1.4 or above is supported." );
            }

            m_numVertices = *(unsigned short *)pPtr;
            pPtr += sizeof(unsigned short);

            m_pVertices = new Vertex[m_numVertices];
            for (unsigned short i = 0; i < m_numVertices; i++)
            {
                    MS3DVertex *pVertex = (MS3DVertex *)pPtr;

                    /////////////data copy
                    m_pVertices.m_location[0] = pVertex->m_vertex[0];
                    m_pVertices.m_location[1] = pVertex->m_vertex[1];
                    //右手到左手
                    m_pVertices.m_location[2] = -pVertex->m_vertex[2];
                    ///////////////zoom
                    m_pVertices.m_location[0] *= scale;
                    m_pVertices.m_location[1] *= scale;
                    m_pVertices.m_location[2] *= scale;

                    //骨骼
                    m_pVertices.m_boneID = pVertex->m_boneID;
                    pPtr += sizeof(MS3DVertex);
            }
            
                ///////////read Triangles///////////////////////////
            m_numTriangles = *(unsigned short *)pPtr;
            pPtr += sizeof(unsigned short);
            m_pTriangles = new Triangle[m_numTriangles];

            for (i = 0; i < m_numTriangles; i++)
            {
                    MS3DTriangle *pTriangle = (MS3DTriangle *)pPtr;

                    //////////////////////////////////////////////////////////////////////
                    ::memcpy(m_pTriangles.m_normal, pTriangle->m_vertexNormals, sizeof(float)*9);
                    //右手到左手
                    m_pTriangles.m_normal[0][2] = -m_pTriangles.m_normal[0][2];
                    m_pTriangles.m_normal[1][2] = -m_pTriangles.m_normal[1][2];
                    m_pTriangles.m_normal[2][2] = -m_pTriangles.m_normal[2][2];

                    ::memcpy(m_pTriangles.m_u, pTriangle->m_u, sizeof( float )*3);
                    ::memcpy(m_pTriangles.m_v, pTriangle->m_v, sizeof( float )*3);
                    ::memcpy(m_pTriangles.m_vertexIndices, pTriangle->m_vertexIndices, sizeof(unsigned short )*3);

                    m_pTriangles.m_groupID = pTriangle->m_groupIndex;
                    pPtr += sizeof(MS3DTriangle);
            }

            //////////////read Meshes/////////////
               m_numMeshes = *(unsigned short *)pPtr;
            pPtr += sizeof(unsigned short);
            m_pMeshes = new Mesh[m_numMeshes];

            for (i = 0; i < m_numMeshes; i++)
            {
                    pPtr += sizeof(unsigned char);        // flags
                    pPtr += 32;                                // name

                    unsigned short nTriangles = *(unsigned short *)pPtr;
                    pPtr += sizeof(unsigned short);
                    unsigned short *pTriangleIndices = new unsigned short[nTriangles];
                    for (int j = 0; j < nTriangles; j++)
                    {
                            pTriangleIndices[j] = *(unsigned short *)pPtr;
                            pPtr += sizeof(unsigned short);
                    }

                    char materialIndex = *(char *)pPtr;
                    pPtr += sizeof(char);
            
                    m_pMeshes.m_textureIndex = materialIndex;
                    m_pMeshes.m_numTriangles = nTriangles;
                    m_pMeshes.m_pTriangleIndices = pTriangleIndices;
            }

                ////////////////read texture/////////////
                // Read materials, creating a default one if none in file
            m_numMaterials = *(unsigned short *)pPtr;
            pPtr += sizeof(short);
            if (!m_numMaterials)
            {
                    // Create a single material and color it white
                    m_numMaterials = 1;
                    m_pMaterial = new MATERIAL[1];
                    ZeroMemory(&m_pMaterial[0], sizeof(MATERIAL));
                    m_pMaterial[0].MatD3D.Diffuse.a = 
                    m_pMaterial[0].MatD3D.Diffuse.r = 
                    m_pMaterial[0].MatD3D.Diffuse.g = 
                    m_pMaterial[0].MatD3D.Diffuse.b = 1.0f;

                    // Set all groups to use material #0
                    // If there are no materials, set all groups to 
                    // use material #0
                    if (m_numMeshes) 
                    {
                            for (i=0; i<m_numMeshes; i++)
                                    m_pMeshes.m_textureIndex = 0;
                    }
            }
            else
            {
                    m_pMaterial = new MATERIAL[m_numMaterials];
                    ZeroMemory(m_pMaterial, sizeof(MATERIAL)*m_numMaterials);
                    
                    // Read in all materials from file
                    for (i=0; i<m_numMaterials; i++)
                    {
                            MS3DMaterial *pMaterial = (MS3DMaterial *)pPtr;
                            
                            /////////////////拷贝
                            m_pMaterial.MatD3D.Diffuse.a = pMaterial->m_diffuse[3];
                            m_pMaterial.MatD3D.Diffuse.r = pMaterial->m_diffuse[2];
                            m_pMaterial.MatD3D.Diffuse.g = pMaterial->m_diffuse[1];
                            m_pMaterial.MatD3D.Diffuse.b = pMaterial->m_diffuse[0];
                            m_pMaterial.MatD3D.Ambient.a = pMaterial->m_ambient[3];
                            m_pMaterial.MatD3D.Ambient.r = pMaterial->m_ambient[2];
                            m_pMaterial.MatD3D.Ambient.g = pMaterial->m_ambient[1];
                            m_pMaterial.MatD3D.Ambient.b = pMaterial->m_ambient[0];
                            m_pMaterial.MatD3D.Specular.a = pMaterial->m_specular[3];
                            m_pMaterial.MatD3D.Specular.r = pMaterial->m_specular[2];
                            m_pMaterial.MatD3D.Specular.g = pMaterial->m_specular[1];
                            m_pMaterial.MatD3D.Specular.b = pMaterial->m_specular[0];
                            m_pMaterial.MatD3D.Emissive.a = pMaterial->m_emissive[3];
                            m_pMaterial.MatD3D.Emissive.r = pMaterial->m_emissive[2];
                            m_pMaterial.MatD3D.Emissive.g = pMaterial->m_emissive[1];
                            m_pMaterial.MatD3D.Emissive.b = pMaterial->m_emissive[0];
                            m_pMaterial.MatD3D.Power = pMaterial->m_shininess;

                            if (pMaterial->m_texture)
                            {
                                    char TextureFile[250] = {0};
                                    // MS3D 1.5.x 相对路径
                                    if (::strncmp(pMaterial->m_texture, ".\", 2 ) == 0 ) 
                                            ParseTextureFileName(pMaterial->m_texture);
                                    
                                    sprintf(TextureFile, "%s%s", TexturePath, pMaterial->m_texture);
                                    
                                    if (FAILED(D3DXCreateTextureFromFile(m_pDevice, TextureFile, &m_pMaterial.pTexture)))
                                    {
                                            D3DXCreateTextureFromFile(m_pDevice, pMaterial->m_texture, &m_pMaterial.pTexture);
                                    }
                            }

                            pPtr += sizeof(MS3DMaterial);
                    }
            }

            //骨骼动画部分
            m_fFps = *(float *)pPtr;
            pPtr += sizeof(float);

            // skip currentTime
            pPtr += sizeof(float);

            int totalFrames = *(int *)pPtr;
            pPtr += sizeof(int);

            m_totalTime = totalFrames*1000.0/m_fFps;

            m_numJoints = *(unsigned short *)pPtr;
            pPtr += sizeof(unsigned short);
            //有骨骼信息
            if (m_numJoints > 0)
            {
                    m_pJoints = new Joint[m_numJoints];
                    
                    const unsigned char *pTempPtr = pPtr;

                    JointNameListRec *pNameList = new JointNameListRec[m_numJoints];
                    unsigned short i = 0;
                    for (i = 0; i < m_numJoints; i++)
                    {
                            MS3DJoint *pJoint = (MS3DJoint *)pTempPtr;
                            pTempPtr += sizeof(MS3DJoint);
                            pTempPtr += sizeof(MS3DKeyframe)*(pJoint->m_numRotationKeyframes+pJoint->m_numTranslationKeyframes);

                            pNameList.m_jointIndex = i;
                            pNameList.m_pName = pJoint->m_name;
                    }

                    for (i = 0; i < m_numJoints; i++)
                    {
                            MS3DJoint *pJoint = (MS3DJoint *)pPtr;
                            pPtr += sizeof(MS3DJoint);

                            int j, parentIndex = -1;
                            if (::strlen(pJoint->m_parentName) > 0)
                            {
                                    for (j = 0; j < m_numJoints; j++)
                                    {
                                            if (::stricmp(pNameList[j].m_pName, pJoint->m_parentName) == 0)
                                            {
                                                    parentIndex = pNameList[j].m_jointIndex;
                                                    break;
                                            }
                                    }
                                    if (parentIndex == -1) 
                                    {
                                            MessageBox(NULL, "55", 0, 0);
                                            return false;
                                    }
                            }

                            ::memcpy(m_pJoints.m_localRotation, pJoint->m_rotation, sizeof(float)*3);
                            ::memcpy(m_pJoints.m_localTranslation, pJoint->m_translation, sizeof(float)*3);

                            //右手到左手
                            m_pJoints.m_localRotation[0] = -m_pJoints.m_localRotation[0];
                            m_pJoints.m_localRotation[1] = -m_pJoints.m_localRotation[1];
                            m_pJoints.m_localTranslation[2] = -m_pJoints.m_localTranslation[2];

                            m_pJoints.m_localTranslation[0] *= scale;
                            m_pJoints.m_localTranslation[1] *= scale;
                            m_pJoints.m_localTranslation[2] *= scale;
                            
                            m_pJoints.m_parent = parentIndex;
                            m_pJoints.m_numRotationKeyframes = pJoint->m_numRotationKeyframes;
                            m_pJoints.m_pRotationKeyframes = new Keyframe[pJoint->m_numRotationKeyframes];
                            m_pJoints.m_numTranslationKeyframes = pJoint->m_numTranslationKeyframes;
                            m_pJoints.m_pTranslationKeyframes = new Keyframe[pJoint->m_numTranslationKeyframes];

                            for (j = 0; j < pJoint->m_numRotationKeyframes; j++)
                            {
                                    MS3DKeyframe *pKeyframe = (MS3DKeyframe *)pPtr;
                                    pPtr += sizeof(MS3DKeyframe);

                                    SetJointKeyframe(i, j, pKeyframe->m_time*1000.0f, pKeyframe->m_parameter, true);
                            }

                            for (j = 0; j < pJoint->m_numTranslationKeyframes; j++)
                            {
                                    MS3DKeyframe *pKeyframe = (MS3DKeyframe *)pPtr;
                                    pPtr += sizeof(MS3DKeyframe);

                                    SetJointKeyframe(i, j, pKeyframe->m_time*1000.0f, pKeyframe->m_parameter, false, scale);
                            }
                    }
                    delete[] pNameList;
            }

            delete []pBuffer;

            GenerateVB();

            ComputBoxAndSphere();

            if (m_numJoints > 0)
            {
                    SetupJoints();
                    Restart();
            }
        
            return true;
    }

    大家主意到上面代码里本人使用反转z坐标来实现右手到左手的转换,同时由于右手空间中旋转方向为逆时针方向,而dx空间为顺时针方向,旋转时也得反转。读者可以自己在草稿上笔画,一边是左手坐标变换,一边是右手坐标变换,左手中该怎么变换才能同右手效果一样。我讲的方法只是其中一种,只要是最终显示效果跟右手空间中显示效果一样,此方法即可。

    void CMs3dMesh::SetJointKeyframe(int jointIndex, int keyframeIndex, float time, float *parameter, bool isRotation, float scale)
    {
            Keyframe& keyframe = isRotation ? m_pJoints[jointIndex].m_pRotationKeyframes[keyframeIndex] :
                    m_pJoints[jointIndex].m_pTranslationKeyframes[keyframeIndex];

            keyframe.m_jointIndex = jointIndex;
            keyframe.m_time = time;
            ::memcpy(keyframe.m_parameter, parameter, sizeof(float)*3);

            //右手到左手
            if (isRotation)
            {
                    keyframe.m_parameter[0] = -keyframe.m_parameter[0];
                    keyframe.m_parameter[1] = -keyframe.m_parameter[1];
    //
            }
            else
            {
                    keyframe.m_parameter[2] = -keyframe.m_parameter[2];
                    keyframe.m_parameter[0] *= scale;
                    keyframe.m_parameter[1] *= scale;
                    keyframe.m_parameter[2] *= scale;
            }
    }
    这里旋转的z值不要反转了,大家画图就可知道。^_^
    缩放系数是我代码里的功能,读者都把其看作1即可。

    void CMs3dMesh::SetupJoints()
    {
            unsigned short i;
            for (i = 0; i < m_numJoints; i++)
            {
                    Joint &joint = m_pJoints;

                    D3DXVECTOR3 vecRol(joint.m_localRotation[0], joint.m_localRotation[1], joint.m_localRotation[2]);
                    D3DXVECTOR3 vecPos(joint.m_localTranslation[0], joint.m_localTranslation[1], joint.m_localTranslation[2]);

                    D3DXMatrixFromRotXYZPos(&joint.m_relative, vecRol, vecPos);
                    
                    if (joint.m_parent != -1)
                    {
                            joint.m_absolute = joint.m_relative*m_pJoints[joint.m_parent].m_absolute;
                    }
                    else
                            joint.m_absolute = joint.m_relative;

                    D3DXMatrixInverse(&m_pJoints.m_offset, NULL, &m_pJoints.m_absolute);
            }

            for (i = 0; i < m_numVertices; i++)
            {
                    Vertex &vertex = m_pVertices;

                    if (vertex.m_boneID != -1)
                    {
                            const D3DXMATRIX &matrix = m_pJoints[vertex.m_boneID].m_offset;

                            D3DXVECTOR3 vec(m_pVertices.m_location[0], m_pVertices.m_location[1], m_pVertices.m_location[2]);
                            D3DXVec3TransformCoord(&vec, &vec, &matrix);
                            m_pVertices.m_location[0] = vec.x;
                            m_pVertices.m_location[1] = vec.y;
                            m_pVertices.m_location[2] = vec.z;
                    }
            }

            for (i = 0; i < m_numTriangles; i++) 
            {
                    Triangle &triangle = m_pTriangles;
                    for (int j = 0; j < 3; j++)
                    {
                            const Vertex &vertex = m_pVertices[triangle.m_vertexIndices[j]];
                            if (vertex.m_boneID != -1) 
                            {
                                    const D3DXMATRIX &matrix = m_pJoints[vertex.m_boneID].m_offset;

                                    D3DXVECTOR3 vec(triangle.m_normal[j][0], triangle.m_normal[j][1], triangle.m_normal[j][2]);
                                    D3DXVec3TransformNormal(&vec, &vec, &matrix);
                                    D3DXVec3Normalize(&vec, &vec);
                                    triangle.m_normal[j][0] = vec.x;
                                    triangle.m_normal[j][1] = vec.y;
                                    triangle.m_normal[j][2] = vec.z;
                            }
                    }
            }
    }

    看到没,所有代码基本上都是参考自nehe的代码。^_^,感谢网络!
    以下得坐标原点为整个模型得坐标原点。
    这里右手坐标为数学坐标,dx与其相反。在数学坐标下矩阵相乘由右到左,dx下由左到右。
    代码中的relative(相对)矩阵是每个joint自己的空间矩阵,你把每个joint看成是个模型。而absolute(绝对)矩阵则是每个joint到坐标原点的变换矩阵。对此矩阵进行求逆,得offset矩阵,对每个joint实行offset矩阵变换,每个节点就会回到坐标原点。这里上面方法调用完每个顶点都可以进行动画矩阵变换了。

    void CMs3dMesh::UpdateAnimation(DWORD time, bool bLoop)
    {
            if (time > m_totalTime)
            {
                    if (bLoop)
                    {
                            time %= m_totalTime;

                            if (time <= m_dwSpeed)
                                    Restart();
                    }
                    else
                            time = m_totalTime;
            } 

            for (int i = 0; i < m_numJoints; i++)
            {
                    float transVec[3] = {0.0f, 0.0f, 0.0f};
                    D3DXMATRIX transform;
                    int frame;
                    Joint *pJoint = &m_pJoints;

                    if (pJoint->m_numRotationKeyframes == 0 && pJoint->m_numTranslationKeyframes == 0)
                    {
                            pJoint->m_final = pJoint->m_absolute;
                            continue;
                    }

                    frame = pJoint->m_currentTranslationKeyframe;
                    while (frame < pJoint->m_numTranslationKeyframes && pJoint->m_pTranslationKeyframes[frame].m_time < time)
                    {
                            frame++;
                    }
                    pJoint->m_currentTranslationKeyframe = frame;

                    if (frame == 0)
                            ::memcpy(transVec, pJoint->m_pTranslationKeyframes[0].m_parameter, sizeof(float)*3);
                    else if (frame == pJoint->m_numTranslationKeyframes)
                            ::memcpy(transVec, pJoint->m_pTranslationKeyframes[frame-1].m_parameter, sizeof(float)*3);
                    else
                    {
                            const Keyframe &curFrame = pJoint->m_pTranslationKeyframes[frame];
                            const Keyframe &prevFrame = pJoint->m_pTranslationKeyframes[frame-1];

                            float timeDelta = curFrame.m_time-prevFrame.m_time;
                            float interpValue = (float)((time-prevFrame.m_time)/timeDelta);

                            transVec[0] = prevFrame.m_parameter[0]+(curFrame.m_parameter[0]-prevFrame.m_parameter[0])*interpValue;
                            transVec[1] = prevFrame.m_parameter[1]+(curFrame.m_parameter[1]-prevFrame.m_parameter[1])*interpValue;
                            transVec[2] = prevFrame.m_parameter[2]+(curFrame.m_parameter[2]-prevFrame.m_parameter[2])*interpValue; 
                    }

                    frame = pJoint->m_currentRotationKeyframe;
                    while (frame < pJoint->m_numRotationKeyframes && pJoint->m_pRotationKeyframes[frame].m_time < time)
                    {
                            frame++;
                    }
                    pJoint->m_currentRotationKeyframe = frame;

                    float rotVec[3] = {0.0f, 0.0f, 0.0f};

                    if (frame == 0)
                            ::memcpy(rotVec, pJoint->m_pRotationKeyframes[0].m_parameter, sizeof(float)*3);
                    else if (frame == pJoint->m_numRotationKeyframes)
                            ::memcpy(rotVec, pJoint->m_pRotationKeyframes[frame-1].m_parameter, sizeof(float)*3);
                    else
                    {
                            const Keyframe& curFrame = pJoint->m_pRotationKeyframes[frame];
                            const Keyframe& prevFrame = pJoint->m_pRotationKeyframes[frame-1];
                            
                            float timeDelta = curFrame.m_time-prevFrame.m_time;
                            float interpValue = (float)((time-prevFrame.m_time)/timeDelta);

                            rotVec[0] = prevFrame.m_parameter[0]+(curFrame.m_parameter[0]-prevFrame.m_parameter[0])*interpValue;
                            rotVec[1] = prevFrame.m_parameter[1]+(curFrame.m_parameter[1]-prevFrame.m_parameter[1])*interpValue;
                            rotVec[2] = prevFrame.m_parameter[2]+(curFrame.m_parameter[2]-prevFrame.m_parameter[2])*interpValue;
                    }

                    D3DXVECTOR3 vecRol(rotVec[0], rotVec[1], rotVec[2]);
                    D3DXVECTOR3 vecPos(transVec[0], transVec[1], transVec[2]);
                    D3DXMatrixFromRotXYZPos(&transform, vecRol, vecPos);

                    D3DXMATRIX relativeFinal = transform*pJoint->m_relative;

                    if (pJoint->m_parent == -1)
                            pJoint->m_final = relativeFinal;
                    else
                    {
                            pJoint->m_final = relativeFinal*m_pJoints[pJoint->m_parent].m_final;
                    }
            }
    }

    每个节点变换完自己得动画后才再实现父节点得变换,pJoint->m_final = relativeFinal*m_pJoints[pJoint->m_parent].m_final。而自己得动画变化是在自己节点得空间矩阵下进行的,所以:relativeFinal = transform*pJoint->m_relative;

    VOID D3DXMatrixFromRotXYZPos(
                                                                            D3DXMATRIX *pOut,
                                                                            D3DXVECTOR3 rot,
                                                                            D3DXVECTOR3 pos)
    {
            D3DXMATRIX matRotX, matRotY, matRotZ;

            D3DXMatrixRotationX(&matRotX, rot.x);
            D3DXMatrixRotationY(&matRotY, rot.y);
            D3DXMatrixRotationZ(&matRotZ, rot.z);

            *pOut = matRotX;
            *pOut *= matRotY;
            *pOut *= matRotZ;
            pOut->_41 = pos.x;
            pOut->_42 = pos.y;
            pOut->_43 = pos.z;
    }

    最后是更新:
    void CMs3dMesh::Update(DWORD time, bool bLoop)
    {
            if (m_numJoints == 0)
                    return;
            
            UpdateAnimation(time, bLoop);
            UpdateVB();//更新vertex buffer
    }

    代码还存在许多可以优化得地方,如可用shader等,这方面网上有相关资料。矩阵旋转我也没用四元数,这个我也不怎么熟也不想用的复杂,简单得东西就行!

    所有得代码本人还没整理好,但已经能很好得显示ms3d动画了。这点请大家放心!
    由于时间仓促,有说错或改进得地方请大家多多指教,再次声明:这只是本人兴致所致,随便谈谈,只要对大家有点帮助得话本人就足矣!

    以下图片为显示ms3d模型动画得效果

  • 相关阅读:
    XHProf的安装和使用(PHP性能测试神器)
    Visual自动添加CSS兼容前缀
    webpack9--删除冗余的CSS
    Vue 获取自定义属性的值
    webpack8--删除dist目录,压缩分离后的CSS
    webpack7--css压缩成单独的css文件
    APICloud 真机连接失败
    js 实现遮罩某一部分
    js实现选集功能
    微信小程序——wxParse使用方法
  • 原文地址:https://www.cnblogs.com/chunlinge/p/3783451.html
Copyright © 2011-2022 走看看