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() ); }
// --[ 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(); }
/** 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 ); }*/ }
// --[ 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; }