//************************************************************************** //* Max2NmoCS312.cpp - Virtools File Exporter //* //* Romain Sididris - Copyright (c) Virtools 2001 //* //* - This file contains some the same code than MAx2Nmo312.cpp //* but use the 3.00 version of character studio header files //* //* In the case of Max 4.2 (Character Studio 3.2) , Only this file is used... //*************************************************************************** #include "Precomp.h" #include "Max2Nmo.h" #ifdef MAX42 #include "PhyExp.h" #else #include "PhyExpCS300.h" #endif int AddBoneToArray(XVoidArray* bones,void* bone); // Try to find if a skin modifier is in the modifier stack of a node Modifier* Max2Nmo::FindSkinModifierCS300 (INode* node) { // Get object from node. Abort if no object. Object* pObj = node->GetObjectRef(); if (!pObj) return NULL; // Is derived object ? SClass_ID sid = pObj->SuperClassID(); while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { // Yes -> Cast. IDerivedObject* pDerObj = static_cast(pObj); // Iterate over all entries of the modifier stack. int ModStackIndex = 0; while (ModStackIndex < pDerObj->NumModifiers()) { // Get current modifier. Modifier* mod = pDerObj->GetModifier(ModStackIndex); // Is this Skin ? if (mod->ClassID() == SKIN_CLASSID ) { return mod; } // Next modifier stack entry. ModStackIndex++; } pObj = pDerObj->GetObjRef(); } return NULL; } // Try to find if a physique modifier is in the modifier stack of a node Modifier* Max2Nmo::FindPhysiqueModifierCS300 (INode* node) { // Get object from node. Abort if no object. Object* pObj = node->GetObjectRef(); if (!pObj) return NULL; // Is derived object ? SClass_ID sid = pObj->SuperClassID(); while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { // Yes -> Cast. IDerivedObject* pDerObj = static_cast(pObj); // Iterate over all entries of the modifier stack. int ModStackIndex = 0; while (ModStackIndex < pDerObj->NumModifiers()) { // Get current modifier. Modifier* mod = pDerObj->GetModifier(ModStackIndex); // Is this Physique ? if (mod->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B) ) { return mod; } // Next modifier stack entry. ModStackIndex++; } pObj = pDerObj->GetObjRef(); } // Not found. return NULL; } /******************************************************************** ********************************************************************/ BOOL Max2Nmo::ExportPhysiqueMeshCS300(INode* node,CK3dEntity* ent) { Modifier *PhysiqueModifier = FindPhysiqueModifier(node); if (!PhysiqueModifier) return FALSE; IPhysiqueExport *phyInterface = (IPhysiqueExport *)( PhysiqueModifier->GetInterface(I_PHYINTERFACE) ); if (!phyInterface) return FALSE; IPhyContextExport* context=phyInterface->GetContextInterface(node); if (!context) return FALSE; VirtoolsTransitionMesh* tmp_mesh= VirtoolsExporter->GetTransitionMesh(node); context->AllowBlending(TRUE); context->ConvertToRigid(TRUE); CKMesh* mesh=ent->GetCurrentMesh(); if (!mesh) return FALSE; Report(REPORT_HLEVEL,"%s : Converting Physique modifier to Skinning\r\n",node->GetName()); Matrix3 InitTM; VxMatrix Mat; CKSkin* skin = ent->CreateSkin(); int NbPhyVertices = context->GetNumberVertices(); int VertexCount = mesh->GetModifierVertexCount(); XVoidArray bones; CKDWORD Stride=0; BYTE* pts=mesh->GetModifierVertices(&Stride); CKDWORD NStride=0; BYTE* norms=(BYTE*)mesh->GetNormalsPtr(&NStride); BOOL DoNormal = (mesh->GetClassID() != CKCID_PATCHMESH); skin->SetVertexCount(VertexCount); if (DoNormal) { skin->SetNormalCount(VertexCount); } //----- Convert vertices info to skin data for(int j = 0 ; j < VertexCount ; j++,pts+=Stride,norms+=NStride) { int MaxVertexIndex = tmp_mesh ? tmp_mesh->m_VirtoolsVertices[j].OriginalPosIndex : j; IPhyVertexExport* vert=context->GetVertexInterface(MaxVertexIndex); CKSkinVertexData* vertexdata = skin->GetVertexData(j); if (vert) if (vert->GetVertexType()==RIGID_NON_BLENDED_TYPE) { IPhyRigidVertex* rvert=(IPhyRigidVertex*)vert; vertexdata->SetBoneCount(1); vertexdata->SetBone(0,AddBoneToArray(&bones,rvert->GetNode())); vertexdata->SetWeight(0,1.0f); vertexdata->SetInitialPos(*(VxVector *)pts); if (DoNormal) { skin->SetNormal(j,*(VxVector *)norms); } } else if (vert->GetVertexType()==RIGID_BLENDED_TYPE) { // RIGID_BLENDED_TYPE IPhyBlendedRigidVertex* bvert=(IPhyBlendedRigidVertex*)vert; int nbbones = bvert->GetNumberNodes(); vertexdata->SetBoneCount(nbbones); vertexdata->SetInitialPos(*(VxVector *)pts); if (DoNormal) { skin->SetNormal(j,*(VxVector *)norms); } float sum = 0; for (int k=0;kGetWeight(k); } sum = 1.0f/sum; for (int k=0;kSetBone(k,AddBoneToArray(&bones,bvert->GetNode(k))); vertexdata->SetWeight(k,sum * bvert->GetWeight(k)); } } else { Report(REPORT_HLEVEL,"%s : Invalid skin vertex type (Not Rigid)\r\n",node->GetName()); } context->ReleaseVertexInterface(vert); } //----- Create Bones int NbBones=bones.Size(); skin->SetBoneCount(NbBones); for(int j = 0 ; j < NbBones; j++) { INode* bone=(INode *)bones[j]; CK3dEntity* ent = VirtoolsExporter->GetEntityByKey(bone); CKSkinBoneData* bonedata = skin->GetBoneData(j); bonedata->SetBone(ent); if (ent) { bonedata->SetBoneInitialInverseMatrix(ent->GetInverseWorldMatrix()); } } InitTM=node->GetNodeTM(0); ConvertMaxMatrix2Virtools(InitTM, Mat); skin->SetObjectInitMatrix(Mat); phyInterface->ReleaseContextInterface(context); PhysiqueModifier->ReleaseInterface(I_PHYINTERFACE,phyInterface); return TRUE; }