zoukankan      html  css  js  c++  java
  • 顶点蒙皮过程

    骨骼的运动和顶点蒙皮是不同的两个过程,骨骼的运动比较简单,就不详细说了。

    先贴一下顶点计算公式:

     1 VertexPos = MJ-0 * weight[index0].pos * weight[index0].weight+ ... + MJ-N * weight[indexN].pos * weight[indexN].weight; 

    先解释一下变量意思:

    MJ-0:权重关联到的骨骼的矩阵

    weight[index0].pos 权重偏移量

    weight[index0].weight 权重比率

    一个顶点可以关联到N个权重,一般我们在m5模型中会限制在4个以内,所有权重值的和为1,权重偏移量就是相对的关联骨骼的位置。具体实现代码:

     1 VGAVertex renderVertex = { 0,0,0, static_cast<float>(uv[0]),static_cast<float>(uv[1]) };
     2 
     3 for (int j = 0; j < pMd5Vertex->weightCount; j++)
     4 {
     5     shared_ptr<Weight> weight = weights[pMd5Vertex->weightIndex + j];
     6 
     7 //    shared_ptr<FrameJoint> joint = frame->jointVec[weight->jointIndex];
     8 
     9     shared_ptr<Md5Joint> md5Joint = jointVec[weight->jointIndex];
    10 
    11     //FbxVector4 wv = joint->m_worldMatrix.MultT(weight->weightPos);
    12 
    13     FbxVector4 wv = md5Joint->bindMatrix.MultT(weight->weightPos);
    14 
    15     //wv += joint.m_Pos;
    16 
    17     wv *= weight->weight;
    18 
    19     renderVertex.x += static_cast<float>(wv[0]);//joint.m_Pos[0] + wv[0]
    20     renderVertex.y += static_cast<float>(wv[1]);
    21     renderVertex.z += static_cast<float>(wv[2]);
    22 }

    这里传入bindpose下或动画中的矩阵就能分别显示不同的模型,这是第一种算法。

    第二种算法使用bindpose下的顶点来计算当前顶点。假定顶点关联的权重只有一个的时候,最终顶点 = 骨骼矩阵*权重偏移量,所以根据公式,我们需要先求出权重偏移量,权重偏移量 = 反转骨骼矩阵 * 最终顶点,代入上面的公式就是:

     VertexPos = (MJ-0 * MJ-0(bindpose)-1)* VertexPosbindpose * weight[index0].weight+ ... + (MJ-N * MJ-N(bindpose)-1)* VertexPosbindpose * weight[indexN].weight ; 

    这种情况下,我们就不需要权重偏移量,需要最终顶点和bindpose下的骨骼反向矩阵。

    第一种如果要显示静态模型,也得当按动画一样来计算,而且不需要保存最终顶点。而第二种在不需要动画的时候能显示静态模型,但是计算量会增加,因为多了一个骨骼逆矩阵,away3d中就是这样的计算方法。

     1 for (size_t i = 0; i < vertexCount; i++)
     2 {
     3     shared_ptr<Md5Vertex> pMd5Vertex = vertices[i];
     4 
     5     FbxVector2 uv;
     6     //if (useIndex)
     7     //    uv = pMesh->GetElementUV()->GetDirectArray().GetAt(pMd5Vertex->uvIndex);
     8     //else
     9     uv = pMd5Vertex->uv;
    10 
    11     VGAVertex bindposeVertex = m_pVertices[i];
    12 
    13     FbxVector4 bindposeVertexVec4 = FbxVector4(bindposeVertex.x, bindposeVertex.y, bindposeVertex.z);//bindpose最终顶点
    14 
    15     VGAVertex renderVertex = { 0,0,0, bindposeVertex.u,bindposeVertex.v };
    16 
    17 
    18     for (int j = 0; j < pMd5Vertex->weightCount; j++)
    19     {
    20         shared_ptr<Weight> weight = weights[pMd5Vertex->weightIndex + j];
    21 
    22         shared_ptr<FrameJoint> joint = frame->jointVec[weight->jointIndex];
    23 
    24         shared_ptr<Md5Joint> md5Joint = jointVec[weight->jointIndex];
    25 
    26         FbxAMatrix invMatrix = md5Joint->bindMatrix.Inverse();
    27         FbxVector4 wv = invMatrix.MultT(bindposeVertexVec4); 
    28 
    29         //wv += joint.m_Pos;
    30 
    31         wv = joint->m_worldMatrix.MultT(wv); //此处wv = weight->weightPos
    32 
    33         //wv = joint->m_worldMatrix.MultT(weight->weightPos);
    34 
    35         wv *= weight->weight;
    36 
    37         renderVertex.x += static_cast<float>(wv[0]);//joint.m_Pos[0] + wv[0]
    38         renderVertex.y += static_cast<float>(wv[1]);
    39         renderVertex.z += static_cast<float>(wv[2]);
    40     }
    41 
    42     *pVertices = renderVertex;
    43     pVertices++;
    44 }

    可以将骨骼当前矩阵先乘上bindpose的逆矩阵,

    1 FbxAMatrix invMatrix = md5Joint->bindMatrix.Inverse();
    2 FbxVector4 wv = (joint->m_worldMatrix * invMatrix).MultT(bindposeVertexVec4);
  • 相关阅读:
    css 渐变动画
    div 画园
    sql server中使用xp_cmdshell
    (0.2.3)Mysql安装——二进制安装
    (0.2.2)如何下载mysql数据库(二进制、RPM、源码、YUM源)
    (0.2.1)mysql数据库环境-操作系统配置
    (0.2)linux下Mysql的安装配置与管理入门(目录篇)
    行列转换之——多行转多列,多列转多行实践版
    sql server数据库状态监控
    【bat】bat批处理异备文件、压缩文件(net use)
  • 原文地址:https://www.cnblogs.com/riaol/p/5691599.html
Copyright © 2011-2022 走看看