/** Inserts all vertices affected by the node to the vertex map. */ void PhyExportUtil::addWeights( mb::VertexMap* vmap, INode* node, IPhyContextExport* mcExport ) { int vertices = mcExport->GetNumberVertices(); for ( int i = 0 ; i < vertices ; ++i ) { // rigid vertex / rigid blended vertex? IPhyVertexExport* vi = mcExport->GetVertexInterface( i /*,HIERARCHIAL_VERTEX*/ ); IPhyFloatingVertex* fv = static_cast<IPhyFloatingVertex*>( mcExport->GetFloatingVertexInterface(i) ); if ( vi && !fv ) { int type = vi->GetVertexType(); switch ( type ) { case RIGID_TYPE:{ IPhyRigidVertex* rv = static_cast<IPhyRigidVertex*>( vi ); INode* bone = rv->GetNode(); if ( bone == node ) addWeight( vmap, i, 1.f ); break;} case (RIGID_TYPE|BLENDED_TYPE):{ IPhyBlendedRigidVertex* rbv = static_cast<IPhyBlendedRigidVertex*>( vi ); for ( int x = 0 ; x < rbv->GetNumberNodes() ; ++x ) { INode* bone = rbv->GetNode( x ); if ( bone == node ) { float weight = rbv->GetWeight( x ); addWeight( vmap, i, weight ); } } break;} default:{ require( false ); break;} } } else if ( fv ) { Debug::println( "Floating vertex found!" ); for ( int x = 0; x < fv->GetNumberNodes() ; ++x ) { INode* bone = fv->GetNode( x ); if ( bone == node ) { float total; float weight = fv->GetWeight( x, total ); addWeight( vmap, i, weight ); } } } else { require( false ); } if ( fv ) mcExport->ReleaseVertexInterface( fv ); if ( vi ) mcExport->ReleaseVertexInterface( vi ); } // print list of mapped weights /*Debug::println( " Weight map {0}:", vmap->name() ); for ( int i = 0 ; i < vertices ; ++i ) { float w = 0.f; if ( vmap->getValue(i, &w, 1) ) Debug::println( " Vertex {0,#}: {1,#.###}", i, w ); }*/ }
void PhyExportUtil::listBones( IPhyContextExport* mcExport, Vector<INode*>& bones ) { int vertices = mcExport->GetNumberVertices(); for ( int i = 0 ; i < vertices ; ++i ) { // rigid vertex / rigid blended vertex? IPhyVertexExport* vi = mcExport->GetVertexInterface( i ); IPhyFloatingVertex* fv = static_cast<IPhyFloatingVertex*>( mcExport->GetFloatingVertexInterface(i) ); if ( vi && !fv ) { int type = vi->GetVertexType(); switch ( type ) { case RIGID_TYPE:{ IPhyRigidVertex* rv = static_cast<IPhyRigidVertex*>( vi ); INode* bone = rv->GetNode(); if ( -1 == bones.indexOf(bone) ) bones.add(bone); break;} case (RIGID_TYPE|BLENDED_TYPE):{ IPhyBlendedRigidVertex* rbv = static_cast<IPhyBlendedRigidVertex*>( vi ); for ( int x = 0 ; x < rbv->GetNumberNodes() ; ++x ) { INode* bone = rbv->GetNode( x ); if ( -1 == bones.indexOf(bone) ) bones.add(bone); } break;} default:{ require( false ); break;} } } else if ( fv ) // floating vertex { Debug::println( "Floating vertex found!" ); for ( int x = 0; x < fv->GetNumberNodes() ; ++x ) { INode* bone = fv->GetNode( x ); if ( -1 == bones.indexOf(bone) ) bones.add(bone); } } else { require( false ); } if ( fv ) mcExport->ReleaseVertexInterface( fv ); if ( vi ) mcExport->ReleaseVertexInterface( vi ); } // print list of used bones Debug::println( " Used bones ({0}):", bones.size() ); for ( int i = 0 ; i < bones.size() ; ++i ) Debug::println( " bone {0,#}: {1}", i, (String)bones[i]->GetName() ); }
CVertexCandidate *CMaxMesh::GetVertexCandidate(CSkeletonCandidate *pSkeletonCandidate, int faceId, int faceVertexId) { // check for valid mesh and physique modifier if((m_pIMesh == 0)) { theExporter.SetLastError("Invalid handle.", __FILE__, __LINE__); return 0; } // check if face id is valid if((faceId < 0) || (faceId >= m_pIMesh->getNumFaces())) { theExporter.SetLastError("Invalid face id found.", __FILE__, __LINE__); return 0; } // check if face vertex id is valid if((faceVertexId < 0) || (faceVertexId >= 3)) { theExporter.SetLastError("Invalid face vertex id found.", __FILE__, __LINE__); return 0; } // allocate a new vertex candidate CVertexCandidate *pVertexCandidate; pVertexCandidate = new CVertexCandidate(); if(pVertexCandidate == 0) { theExporter.SetLastError("Memory allocation failed.", __FILE__, __LINE__); return 0; } // create the new vertex candidate if(!pVertexCandidate->Create()) { delete pVertexCandidate; return 0; } // get vertex id int vertexId; vertexId = m_pIMesh->faces[faceId].v[faceVertexId]; // get the absolute vertex position Point3 vertex; vertex = m_pIMesh->getVert(vertexId) * m_tm; // set the vertex candidate position pVertexCandidate->SetPosition(vertex.x, vertex.y, vertex.z); pVertexCandidate->SetUniqueId(vertexId); // get the absolute vertex normal Point3 normal; normal = GetVertexNormal(faceId, vertexId); normal = normal * Inverse(Transpose(m_tm)); normal = normal.Normalize(); // set the vertex candidate normal pVertexCandidate->SetNormal(normal.x, normal.y, normal.z); if(m_pIMesh->numCVerts > 0) { VertColor vc; vc = m_pIMesh->vertCol[m_pIMesh->vcFace[faceId].t[faceVertexId]]; CalVector vcCal(vc.x, vc.y, vc.z); pVertexCandidate->SetVertColor(vcCal); } // get the vertex weight array float *pVertexWeights; pVertexWeights = m_pIMesh->getVertexWeights(); //if( pVertexWeights == NULL ) { // delete pVertexCandidate; // theExporter.SetLastError("Mesh has no vertex weights", __FILE__, __LINE__); // return 0; //} // get the vertex weight (if possible) float weight; if(pVertexWeights != 0) { weight = pVertexWeights[vertexId]; } else { weight = 0.0f; } // another 3ds max weird behaviour: // zero out epsilon weights if(weight < 0.0005f) weight = 0.0f; // set the vertex candidate weight pVertexCandidate->SetPhysicalProperty(weight); // get the material id of the face int materialId; materialId = GetFaceMaterialId(faceId); if((materialId < 0) || (materialId >= (int)m_vectorStdMat.size())) { delete pVertexCandidate; theExporter.SetLastError("Invalid material id found.", __FILE__, __LINE__); return 0; } // get the material of the face StdMat *pStdMat; pStdMat = m_vectorStdMat[materialId]; // loop through all the mapping channels and extract texture coordinates int mapId; for(mapId = 0; mapId < pStdMat->NumSubTexmaps(); mapId++) { // get texture map Texmap *pTexMap; pTexMap = pStdMat->GetSubTexmap(mapId); // check if map is valid if((pTexMap != 0) && (pStdMat->MapEnabled(mapId))) { // get the mapping channel int channel; channel = pTexMap->GetMapChannel(); bool bValidUV; bValidUV = false; // extract the texture coordinate UVVert uvVert; if(m_pIMesh->mapSupport(channel)) { TVFace *pTVFace; pTVFace = m_pIMesh->mapFaces(channel); UVVert *pUVVert; pUVVert = m_pIMesh->mapVerts(channel); uvVert = pUVVert[pTVFace[faceId].t[faceVertexId]]; bValidUV = true; } else if(m_pIMesh->numTVerts > 0) { uvVert = m_pIMesh->tVerts[m_pIMesh->tvFace[faceId].t[faceVertexId]]; bValidUV = true; } // if we found valid texture coordinates, add them to the vertex candidate if(bValidUV) { // apply a possible uv generator StdUVGen *pStdUVGen; pStdUVGen = (StdUVGen *)pTexMap->GetTheUVGen(); if(pStdUVGen != 0) { Matrix3 tmUV; pStdUVGen->GetUVTransform(tmUV); uvVert = uvVert * tmUV; } // add texture coordinate to the vertex candidate, inverting the y coordinate pVertexCandidate->AddTextureCoordinate(uvVert.x, 1.0f - uvVert.y); } } } // check for physique modifier if(m_modifierType == MODIFIER_PHYSIQUE) { // create a physique export interface IPhysiqueExport *pPhysiqueExport; pPhysiqueExport = (IPhysiqueExport *)m_pModifier->GetInterface(I_PHYINTERFACE); if(pPhysiqueExport == 0) { delete pVertexCandidate; theExporter.SetLastError("Physique modifier interface not found.", __FILE__, __LINE__); return 0; } // create a context export interface IPhyContextExport *pContextExport; pContextExport = (IPhyContextExport *)pPhysiqueExport->GetContextInterface(m_pINode); if(pContextExport == 0) { m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport); delete pVertexCandidate; theExporter.SetLastError("Context export interface not found.", __FILE__, __LINE__); return 0; } // set the flags in the context export interface pContextExport->ConvertToRigid(TRUE); pContextExport->AllowBlending(TRUE); // get the vertex export interface IPhyVertexExport *pVertexExport; pVertexExport = (IPhyVertexExport *)pContextExport->GetVertexInterface(vertexId); if(pVertexExport == 0) { pPhysiqueExport->ReleaseContextInterface(pContextExport); m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport); delete pVertexCandidate; theExporter.SetLastError("Vertex export interface not found.", __FILE__, __LINE__); return 0; } // get the vertex type int vertexType; vertexType = pVertexExport->GetVertexType(); // handle the specific vertex type if(vertexType == RIGID_TYPE) { // typecast to rigid vertex IPhyRigidVertex *pTypeVertex; pTypeVertex = (IPhyRigidVertex *)pVertexExport; // add the influence to the vertex candidate // get the influencing bone if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pTypeVertex->GetNode(), 1.0f)) { pPhysiqueExport->ReleaseContextInterface(pContextExport); m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport); delete pVertexCandidate; theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__); return 0; } } else if(vertexType == RIGID_BLENDED_TYPE) { // typecast to blended vertex IPhyBlendedRigidVertex *pTypeVertex; pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport; // loop through all influencing bones int nodeId; for(nodeId = 0; nodeId < pTypeVertex->GetNumberNodes(); nodeId++) { // add the influence to the vertex candidate if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pTypeVertex->GetNode(nodeId), pTypeVertex->GetWeight(nodeId))) { pPhysiqueExport->ReleaseContextInterface(pContextExport); m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport); delete pVertexCandidate; theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__); return 0; } } } // release all interfaces pPhysiqueExport->ReleaseContextInterface(pContextExport); m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport); } #if MAX_RELEASE >= 4000 // check for skin modifier else if(m_modifierType == MODIFIER_SKIN) { // create a skin interface ISkin *pSkin; pSkin = (ISkin*)m_pModifier->GetInterface(I_SKIN); if(pSkin == 0) { delete pVertexCandidate; theExporter.SetLastError("Skin modifier interface not found.", __FILE__, __LINE__); return 0; } // create a skin context data interface ISkinContextData *pSkinContextData; pSkinContextData = (ISkinContextData *)pSkin->GetContextInterface(m_pINode); if(pSkinContextData == 0) { m_pModifier->ReleaseInterface(I_SKIN, pSkin); delete pVertexCandidate; theExporter.SetLastError("Skin context data interface not found.", __FILE__, __LINE__); return 0; } // loop through all influencing bones int nodeId; for(nodeId = 0; nodeId < pSkinContextData->GetNumAssignedBones(vertexId); nodeId++) { // get the bone id int boneId; boneId = pSkinContextData->GetAssignedBone(vertexId, nodeId); if(boneId < 0) continue; // add the influence to the vertex candidate if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pSkin->GetBone(boneId), pSkinContextData->GetBoneWeight(vertexId, nodeId))) { m_pModifier->ReleaseInterface(I_SKIN, pSkin); delete pVertexCandidate; theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__); return 0; } } // release all interfaces m_pModifier->ReleaseInterface(I_SKIN, pSkin); } #endif else if( m_modifierType == MODIFIER_MORPHER || m_modifierType == MODIFIER_NONE ) { } else { theExporter.SetLastError("No physique/skin/morpher modifier found.", __FILE__, __LINE__); return 0; } return pVertexCandidate; }
// --[ Method ]--------------------------------------------------------------- // // - Class : CStravaganzaMaxTools // // - prototype : int BuildPhysiqueData(INode* pMaxNode, // CObject* pObject, // std::vector<std::string> &vecBoneNames, // std::vector<CBlendedVertex> &vecBlendedVertices) // // - Purpose : Builds the bone data for a given node. Returns the number // of bones processed (0 = failure). // // ----------------------------------------------------------------------------- int CStravaganzaMaxTools::BuildPhysiqueData(INode* pMaxNode, CObject* pObject, std::vector<std::string> &vecBoneNames, std::vector<CBlendedVertex> &vecBlendedVertices) { int nCount = 0; int nBoneCount = 0; Modifier *pPhyModifier = NULL; // Physique modifier IPhysiqueExport *pPhyExport = NULL; // Physique export interface IPhyContextExport *pPhyObjExport = NULL; // Physique object export interface vecBoneNames.clear(); vecBlendedVertices.clear(); // Build bone list std::vector<INode*> vecMaxBones; if(!AddNodeBones(vecMaxBones, pMaxNode)) { LOG.Write("\nWARNING - Error building node %s bone list", pMaxNode->GetName()); return 0; } // Build bones name list for(nBoneCount = 0; nBoneCount < vecMaxBones.size(); nBoneCount++) { vecBoneNames.push_back(vecMaxBones[nBoneCount]->GetName()); } // Get Physique modifier if(pPhyModifier = GetPhysiqueModifier(pMaxNode)) { pPhyExport = (IPhysiqueExport *)pPhyModifier->GetInterface(I_PHYINTERFACE); if(pPhyExport == NULL) { LOG.Write("\nWARNING - Couldn't get Physique export interface.\nFailed with node %s.", pMaxNode->GetName()); return 0; } } // Get physique object export interface pPhyObjExport = pPhyExport->GetContextInterface(pMaxNode); if(pPhyObjExport == NULL) { pPhyModifier->ReleaseInterface(I_PHYINTERFACE, pPhyExport); LOG.Write("\nWARNING - Unable to get physique context export.\nFailed with node %s.", pMaxNode->GetName()); return 0; } // Convert to rigid for time independent vertex assignment // Allow blending to export multi-link assignments pPhyObjExport->ConvertToRigid(true); pPhyObjExport->AllowBlending(true); // Build deformable vertex list bool bOK = true; int nBlendedCount = 0, nBlendedRigidCount = 0, nFloatingCount = 0; for(nCount = 0; nCount < pPhyObjExport->GetNumberVertices(); nCount++) { IPhyVertexExport *pPhyVertExport; IPhyBlendedRigidVertex *pPhyBRVertexExport; IPhyRigidVertex *pPhyRigidVertexExport; IPhyFloatingVertex *pPhyFloatingVertex; pPhyVertExport = pPhyObjExport->GetVertexInterface(nCount); CBlendedVertex blendedVertex; float fTotalWeight = 0.0f; bool bFloatingBones = false; // Floating Vertex pPhyFloatingVertex = pPhyObjExport->GetFloatingVertexInterface(nCount); if(pPhyFloatingVertex) { bFloatingBones = true; CVector3 v3OffsetVector; float fWeight; // More than one bone int nNumVtxBones = pPhyFloatingVertex->GetNumberNodes(); // LOG.Write("\n%u - Floating, with %u bones", nCount, nNumVtxBones); for(nBoneCount = 0; nBoneCount < nNumVtxBones; nBoneCount++) { int nIndex = GetBoneIndex(vecMaxBones, pPhyFloatingVertex->GetNode(nBoneCount)); if(nIndex == -1) { LOG.Write("\nWARNING - Unable to get bone index (%s)", pPhyFloatingVertex->GetNode(nBoneCount)->GetName()); bOK = false; break; } float fTotal; v3OffsetVector = Point3ToVector3(pPhyFloatingVertex->GetOffsetVector(nBoneCount)); fWeight = pPhyFloatingVertex->GetWeight(nBoneCount, fTotal); fTotalWeight += fWeight;//fTotal; //fWeight = fTotal; // LOG.Write("\n Weight = %f (%s)", fWeight, pPhyFloatingVertex->GetNode(nBoneCount)->GetName()); blendedVertex.AddLink(v3OffsetVector, nIndex, fWeight); } // LOG.Write("\n Total = %f", fTotalWeight); if(!ARE_EQUAL(fTotalWeight, 1.0f)) { LOG.Write("\n WARNING - Vertex %u has total weights %f", nCount, fTotalWeight); } nFloatingCount++; pPhyObjExport->ReleaseVertexInterface(pPhyFloatingVertex); } if(pPhyVertExport) { if(pPhyVertExport->GetVertexType() & BLENDED_TYPE) { CVector3 v3OffsetVector; float fWeight; // More than one bone pPhyBRVertexExport = (IPhyBlendedRigidVertex *)pPhyVertExport; int nNumVtxBones = pPhyBRVertexExport->GetNumberNodes(); // LOG.Write("\n%u - Blended, with %u bones", nCount, nNumVtxBones); for(nBoneCount = 0; nBoneCount < nNumVtxBones; nBoneCount++) { int nIndex = GetBoneIndex(vecMaxBones, pPhyBRVertexExport->GetNode(nBoneCount)); if(nIndex == -1) { LOG.Write("\nWARNING - Unable to get bone index (%s)", pPhyBRVertexExport->GetNode(nBoneCount)->GetName()); bOK = false; break; } v3OffsetVector = Point3ToVector3(pPhyBRVertexExport->GetOffsetVector(nBoneCount)); fWeight = pPhyBRVertexExport->GetWeight(nBoneCount); fTotalWeight += fWeight; // LOG.Write("\n Weight = %f (%s)", fWeight, pPhyBRVertexExport->GetNode(nBoneCount)->GetName()); blendedVertex.AddLink(v3OffsetVector, nIndex, fWeight); } // LOG.Write("\n Total = %f", fTotalWeight); if(!ARE_EQUAL(fTotalWeight, 1.0f)) { LOG.Write("\n WARNING - Vertex %u has total weights %f", nCount, fTotalWeight); } nBlendedCount++; } else { CVector3 v3OffsetVector; float fWeight; // Single bone pPhyRigidVertexExport = (IPhyRigidVertex *)pPhyVertExport; int nIndex = GetBoneIndex(vecMaxBones, pPhyRigidVertexExport->GetNode()); if(nIndex == -1) { LOG.Write("\nWARNING - Unable to get bone index (%s)", pPhyRigidVertexExport->GetNode()->GetName()); bOK = false; break; } v3OffsetVector = Point3ToVector3(pPhyRigidVertexExport->GetOffsetVector()); fWeight = 1.0f; fTotalWeight = 1.0f; // LOG.Write("\n%u - Rigid (%s)", nCount, pPhyRigidVertexExport->GetNode()->GetName()); blendedVertex.AddLink(v3OffsetVector, nIndex, fWeight); nBlendedRigidCount++; } pPhyObjExport->ReleaseVertexInterface(pPhyVertExport); } for(int i = 0; i < blendedVertex.GetNumLinks(); i++) { // Normalize blendedVertex.SetWeight(i, blendedVertex.GetWeight(i) / fTotalWeight); } vecBlendedVertices.push_back(blendedVertex); } pPhyExport->ReleaseContextInterface(pPhyObjExport); pPhyModifier->ReleaseInterface(I_PHYINTERFACE, pPhyExport); if(!bOK) { vecMaxBones.clear(); vecBoneNames.clear(); vecBlendedVertices.clear(); } else { LOG.Write("\nPhysique: %u bones, %u vertices (%u rigid, %u rigidblended, %u floating)", vecBoneNames.size(), vecBlendedVertices.size(), nBlendedRigidCount, nBlendedCount, nFloatingCount); } return vecMaxBones.size(); }
// --[ Method ]--------------------------------------------------------------- // // - Class : CStravaganzaMaxTools // // - prototype : bool AddNodeBones(std::vector<INode*> &vecMaxBones, INode *pMaxNode) // // - Purpose : Adds all bones belonging to the node to the given list. // // ----------------------------------------------------------------------------- bool CStravaganzaMaxTools::AddNodeBones(std::vector<INode*> &vecMaxBones, INode *pMaxNode) { int nCount = 0; int nBoneCount = 0; bool bOK = true; Modifier *pPhyModifier = NULL; // Physique modifier IPhysiqueExport *pPhyExport = NULL; // Physique export interface IPhyContextExport *pPhyObjExport = NULL; // Physique object export interface // Get Physique modifier if(pPhyModifier = GetPhysiqueModifier(pMaxNode)) { pPhyExport = (IPhysiqueExport *)pPhyModifier->GetInterface(I_PHYINTERFACE); if(pPhyExport == NULL) { return false; } } else { return false; } // Get physique object export interface pPhyObjExport = pPhyExport->GetContextInterface(pMaxNode); if(pPhyObjExport == NULL) { pPhyModifier->ReleaseInterface(I_PHYINTERFACE, pPhyExport); return false; } pPhyObjExport->ConvertToRigid(true); pPhyObjExport->AllowBlending(true); INode *pMaxBone; // Build bone list LOG.Write("\nObject %s Bone List:", pMaxNode->GetName()); for(nCount = 0; nCount < pPhyObjExport->GetNumberVertices(); nCount++) { IPhyVertexExport *pPhyVertExport; IPhyBlendedRigidVertex *pPhyBRVertexExport; IPhyRigidVertex *pPhyRigidVertexExport; IPhyFloatingVertex *pPhyFloatingVertex; pPhyVertExport = pPhyObjExport->GetVertexInterface(nCount); if(pPhyVertExport) { if(pPhyVertExport->GetVertexType() & BLENDED_TYPE) { pPhyBRVertexExport = (IPhyBlendedRigidVertex *)pPhyVertExport; for(nBoneCount = 0; nBoneCount < pPhyBRVertexExport->GetNumberNodes(); nBoneCount++) { pMaxBone = pPhyBRVertexExport->GetNode(nBoneCount); if(IsBoneInList(vecMaxBones, pMaxBone) == false) { // LOG.Write("\n %s (blended)", pMaxBone->GetName()); vecMaxBones.push_back(pMaxBone); } } } else { pPhyRigidVertexExport = (IPhyRigidVertex *)pPhyVertExport; pMaxBone = pPhyRigidVertexExport->GetNode(); if(IsBoneInList(vecMaxBones, pMaxBone) == false) { // LOG.Write("\n %s (rigid)", pMaxBone->GetName()); vecMaxBones.push_back(pMaxBone); } } pPhyObjExport->ReleaseVertexInterface(pPhyVertExport); } pPhyFloatingVertex = pPhyObjExport->GetFloatingVertexInterface(nCount); if(pPhyFloatingVertex) { for(nBoneCount = 0; nBoneCount < pPhyFloatingVertex->GetNumberNodes(); nBoneCount++) { pMaxBone = pPhyFloatingVertex->GetNode(nBoneCount); if(IsBoneInList(vecMaxBones, pMaxBone) == false) { // LOG.Write("\n %s (floating)", pMaxBone->GetName()); vecMaxBones.push_back(pMaxBone); } } pPhyObjExport->ReleaseVertexInterface(pPhyFloatingVertex); } } pPhyExport->ReleaseContextInterface(pPhyObjExport); pPhyModifier->ReleaseInterface(I_PHYINTERFACE, pPhyExport); return bOK; }
void RBExport::GetPhysiqueBinding( ExpVertex& v ) { IPhyVertexExport* pExport = (IPhyVertexExport*)m_pPhysique->GetVertexInterface( v.index ); if (!pExport) { Warn( "Cannot export skinning with Physique modifier." ); return; } // check vertex type (rigid/rigid blended) DWORD vType; vType = pExport->GetVertexType(); m_pPhysique->ReleaseVertexInterface( pExport ); if (vType == RIGID_TYPE) { // skinned with single bone IPhyRigidVertex* pRigidVertex = (IPhyRigidVertex*)m_pPhysique->GetVertexInterface( v.index ); if (!pRigidVertex) { Warn( "Cannot export rigid type skinning with Physique modifier." ); return; } INode* pBoneNode = pRigidVertex->GetNode(); if (!pBoneNode) return; ExpNode* pExportedBone = GetExportedNode( pBoneNode ); if (!pExportedBone) return; v.boneIdx[0] = m_pCurExpNode->AddBoneIdx( pExportedBone->m_Index ); v.nBones = 1; v.boneWeight[0] = 1.0f; m_pPhysique->ReleaseVertexInterface( pRigidVertex ); } else if (vType == RIGID_BLENDED_TYPE) { IPhyBlendedRigidVertex* pBlendedVertex = (IPhyBlendedRigidVertex*) m_pPhysique->GetVertexInterface( v.index ); if (!pBlendedVertex) { Warn( "Cannot export blended type skinning with Physique modifier." ); return; } v.nBones = pBlendedVertex->GetNumberNodes(); for (int i = 0; i < v.nBones; i++) { INode* pBoneNode = pBlendedVertex->GetNode( i ); ExpNode* pExportedBone = GetExportedNode( pBoneNode ); v.boneIdx[i] = m_pCurExpNode->AddBoneIdx( pExportedBone->m_Index ); v.boneWeight[i] = pBlendedVertex->GetWeight( i ); /*if (!vert.AddWeight( bIdx, weight )) { Msg( "Too much weights per vertex. Skin:%s, Bone:%s", curNodeName, boneNode->GetName() ); vert.LeaveBiggerWeight( bIdx, weight ); continue; } */ } m_pPhysique->ReleaseVertexInterface( pBlendedVertex ); } else { // incorrect skinned vertex type Warn( "Cannot export skinning with Physique modifier: wrong vertex type." ); } } // RBExport::GetPhysiqueBinding
void SGP_MaxInterface::GetBoneGroup( Modifier *pModifier, int nModifierType, INode* pNode, Mesh* pMesh, int nVertexId, BoneGroup& boneGroup ) { if( !pMesh ) { assert( false ); return; } if( nVertexId >= pMesh->numVerts ) { assert( false ); return; } // static mesh if( nModifierType == MODIFIER_NONE ) { INode* pParent = pNode->GetParentNode(); if( pParent && ( IsBone( pParent ) || IsBipedBone( pParent ) ) ) { Influence infl; infl.fWeight = 1.0f; strcpy( infl.szBoneName, pParent->GetName() ); boneGroup.AddInfluence( infl ); } } // check for physique modifier else if( nModifierType == MODIFIER_PHYSIQUE ) { assert( pModifier && "get bone group error, modifier is null" ); // create a physique export interface IPhysiqueExport *pPhysiqueExport = (IPhysiqueExport *)pModifier->GetInterface(I_PHYINTERFACE); if(pPhysiqueExport == NULL) { return; } // create a context export interface IPhyContextExport *pContextExport = (IPhyContextExport *)pPhysiqueExport->GetContextInterface(pNode); if(pContextExport == NULL) { pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport); return; } // set the flags in the context export interface pContextExport->ConvertToRigid(TRUE); pContextExport->AllowBlending(TRUE); // get the vertex export interface IPhyVertexExport *pVertexExport = (IPhyVertexExport *)pContextExport->GetVertexInterface(nVertexId); if(pVertexExport == NULL) { pPhysiqueExport->ReleaseContextInterface(pContextExport); pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport); return; } // get the vertex type int vertexType = pVertexExport->GetVertexType(); // handle the specific vertex type if(vertexType == RIGID_TYPE) { // typecast to rigid vertex IPhyRigidVertex *pTypeVertex = (IPhyRigidVertex *)pVertexExport; Influence infl; if( pTypeVertex->GetNode() ) { strcpy( infl.szBoneName, pTypeVertex->GetNode()->GetName() ); infl.fWeight = 1.0f; boneGroup.AddInfluence( infl ); } else return; } else if(vertexType == RIGID_BLENDED_TYPE) { // typecast to blended vertex IPhyBlendedRigidVertex *pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport; // loop through all influencing bones Influence infl; for(int nodeId = 0; nodeId < pTypeVertex->GetNumberNodes(); nodeId++) { strcpy( infl.szBoneName, pTypeVertex->GetNode( nodeId )->GetName() ); infl.fWeight = pTypeVertex->GetWeight( nodeId ); boneGroup.AddInfluence( infl ); } } // release all interfaces pPhysiqueExport->ReleaseContextInterface(pContextExport); pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport); } else if( nModifierType == MODIFIER_SKIN) { assert( pModifier && "get bone group error, modifier is null" ); // create a skin interface ISkin *pSkin = (ISkin*)pModifier->GetInterface(I_SKIN); if(pSkin == 0) { return; } // create a skin context data interface ISkinContextData *pSkinContextData; pSkinContextData = (ISkinContextData *)pSkin->GetContextInterface(pNode); if(pSkinContextData == NULL) { pModifier->ReleaseInterface(I_SKIN, pSkin); return; } // loop through all influencing bones for(int nodeId = 0; nodeId < pSkinContextData->GetNumAssignedBones(nVertexId); nodeId++) { // get the bone id int boneId = pSkinContextData->GetAssignedBone(nVertexId, nodeId); if(boneId < 0) continue; INode* pBone = pSkin->GetBone( boneId ); Influence infl; strcpy( infl.szBoneName, pBone->GetName() ); infl.fWeight = pSkinContextData->GetBoneWeight(nVertexId, nodeId); boneGroup.AddInfluence( infl ); } // release all interfaces pModifier->ReleaseInterface(I_SKIN, pSkin); } }