The movement of the skeleton and the vertex skin are different two processes, the movement of the skeleton is relatively simple, not detailed said.
First put the vertex calculation formula:
1 vertexpos = MJ0 * weight[index0].pos * weight[index0].weight+ ... + Mj-n * Weight[indexn].pos * weight[indexn].weight;
First explain the variable meaning:
MJ-0: The matrix of the bones to which the weights are associated
Weight[index0].pos Weight Offset
Weight[index0].weight weight ratio
A vertex can be associated to n weights, generally we are limited to 4 within the M5 model, and all weights are 1, and the weight offset is the relative position of the associated bone. Specific implementation code:
1Vgavertex Rendervertex = {0,0,0, static_cast<float> (uv[0]),static_cast<float> (uv[1]) };2 3 for(intj =0; J < pmd5vertex->weightcount; J + +)4 {5Shared_ptr<weight> Weight = Weights[pmd5vertex->weightindex +j];6 7 //shared_ptr<framejoint> joint = frame->jointvec[weight->jointindex];8 9shared_ptr<md5joint> Md5joint = jointvec[weight->Jointindex];Ten One //FbxVector4 WV = JOINT->M_WORLDMATRIX.MULTT (weight->weightpos); A -FbxVector4 WV = MD5JOINT->BINDMATRIX.MULTT (weight->weightpos); - the //WV + = Joint.m_pos; - -WV *= Weight->weight; - +rendervertex.x + = static_cast<float> (wv[0]);//Joint.m_pos[0] + wv[0] -Rendervertex.y + = static_cast<float> (wv[1]); +Rendervertex.z + = static_cast<float> (wv[2]); A}
This is the first algorithm that can be used to display different models by passing in Bindpose or the matrix in the animation.
The second algorithm uses vertices under Bindpose to calculate the current vertex. Assuming that the vertex association weights only one time, the final vertex = bone Matrix * Weight offset, so according to the formula, we need to find the weight offset, the weight offset = inverse Skeleton Matrix * Final vertex, substituting the above formula is:
Vertexpos = (MJ-0 * MJ-0 (Bindpose)-1) * Vertexposbindpose * weight[index0].weight+ ... + (Mj-n * mj-n (Bin Dpose)-1) * vertexposbindpose * weight[indexn].weight;
In this case, we do not need the weight offset, we need the final vertex and the bone inverse matrix under bindpose.
The first, if you want to display a static model, is calculated as an animation, and you do not need to save the final vertex. The second is to show the static model when the animation is not needed, but the computational amount will increase, because there is a skeleton inverse matrix, which is the calculation method in Away3d.
1 for(size_t i =0; i < Vertexcount; i++)2 {3Shared_ptr<md5vertex> Pmd5vertex =Vertices[i];4 5 FbxVector2 UV;6 //if (useindex)7 //UV = PMESH->GETELEMENTUV ()->getdirectarray (). GetAt (pmd5vertex->uvindex);8 //Else9UV = Pmd5vertex->UV;Ten OneVgavertex Bindposevertex =M_pvertices[i]; A -FbxVector4 bindposeVertexVec4 = FbxVector4 (bindposevertex.x, bindposevertex.y, bindposevertex.z);//Bindpose final Vertex - theVgavertex Rendervertex = {0,0,0, bindposevertex.u,bindposevertex.v}; - - - for(intj =0; J < pmd5vertex->weightcount; J + +) + { -Shared_ptr<weight> Weight = Weights[pmd5vertex->weightindex +j]; + Ashared_ptr<framejoint> Joint = frame->jointvec[weight->Jointindex]; at -shared_ptr<md5joint> Md5joint = jointvec[weight->Jointindex]; - -Fbxamatrix Invmatrix = md5joint->bindmatrix.inverse (); -FbxVector4 WV =INVMATRIX.MULTT (BINDPOSEVERTEXVEC4); - in //WV + = Joint.m_pos; - toWV = JOINT->M_WORLDMATRIX.MULTT (WV);//here WV = Weight->weightpos + - //WV = JOINT->M_WORLDMATRIX.MULTT (weight->weightpos); the *WV *= Weight->weight; $ Panax Notoginsengrendervertex.x + = static_cast<float> (wv[0]);//Joint.m_pos[0] + wv[0] -Rendervertex.y + = static_cast<float> (wv[1]); theRendervertex.z + = static_cast<float> (wv[2]); + } A the*pvertices =Rendervertex; +pvertices++; -}
You can multiply the current matrix of bones by the inverse matrix of the bindpose,
1 Fbxamatrix Invmatrix = md5joint->bindmatrix.inverse (); 2 FbxVector4 WV = (Joint->m_worldmatrix * invmatrix). MULTT (BINDPOSEVERTEXVEC4);
Vertex skin Process