ISkin* MaxExportPlugin::FindSkinModifier(INode* node) { Object* object = node->GetObjectRef(); if (!object) return 0; while (object->SuperClassID() == GEN_DERIVOB_CLASS_ID && object) { IDerivedObject* derivedObject = (IDerivedObject*)object; int modStackId = 0; while (modStackId < derivedObject->NumModifiers()) { Modifier* mod = derivedObject->GetModifier(modStackId); //file << "MODIFIER: " << std::to_wstring(mod->ClassID().PartA()) << " " << std::to_wstring(mod->ClassID().PartB()) << "\n"; if (mod->ClassID() == SKIN_CLASS_ID) { return (ISkin*)(mod->GetInterface(I_SKIN)); } modStackId++; } object = derivedObject->GetObjRef(); } return 0; }
//// FindSkinModifier /////////////////////////////////////////////////////// // Given an INode, gets the ISkin object of that node, or nil if there is // none. Taken from the Max4 SDK, ISkin.h ISkin* plMaxNodeBase::FindSkinModifier() { int modStackIndex; // Get object from node. Abort if no object. Object *pObj = GetObjectRef(); if( pObj == nil ) return nil; // Is derived object ? while( pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID ) { IDerivedObject *pDerObj = (IDerivedObject *)pObj; // Iterate over all entries of the modifier stack. for( modStackIndex = 0; modStackIndex < pDerObj->NumModifiers(); modStackIndex++ ) { // Get current modifier. Modifier *mod = pDerObj->GetModifier( modStackIndex ); // Is this Skin ? if( mod->ClassID() == SKIN_CLASSID ) { ISkin* skin = (ISkin*)mod->GetInterface(I_SKIN); if( skin->GetNumBones() > 0 ) return skin; } } pObj = pDerObj->GetObjRef(); } // Not found. return nil; }
Modifier *CMaxMesh::FindSkinModifier(INode *pINode) { #if MAX_RELEASE >= 4000 // get the object reference of the node Object *pObject; pObject = pINode->GetObjectRef(); if(pObject == 0) return 0; // loop through all derived objects while(pObject->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject *pDerivedObject; pDerivedObject = static_cast<IDerivedObject *>(pObject); // loop through all modifiers int stackId; for(stackId = 0; stackId < pDerivedObject->NumModifiers(); stackId++) { // get the modifier Modifier *pModifier; pModifier = pDerivedObject->GetModifier(stackId); // check if we found the skin modifier if(pModifier->ClassID() == SKIN_CLASSID) return pModifier; } // continue with next derived object pObject = pDerivedObject->GetObjRef(); } #endif return 0; }
//---------------------------------------------------------------------------- void SceneBuilder::CollectModifiers (INode *node, std::vector<Modifier*> &modifiers) { // 确定这个节点是否有修改器。如果有,存储起来。 // // node: // Max场景中节点指针。 // modifiers: // 存储所有修改器指针。 Object *obj = node->GetObjectRef(); if (!obj) return; while (obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject* derObj = static_cast<IDerivedObject*>(obj); int modStackIndex = 0; while (modStackIndex < derObj->NumModifiers()) { Modifier *mod = derObj->GetModifier(modStackIndex); if (mod) { modifiers.push_back(mod); } modStackIndex++; } obj = derObj->GetObjRef(); } }
Modifier* SGP_MaxInterface::FindModifier(INode *pINode, Class_ID id) { // get the object reference of the node Object *pObject; pObject = pINode->GetObjectRef(); if(pObject == NULL) return NULL; // loop through all derived objects while(pObject->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject *pDerivedObject; pDerivedObject = static_cast<IDerivedObject *>(pObject); // loop through all modifiers int stackId; for(stackId = 0; stackId < pDerivedObject->NumModifiers(); stackId++) { // get the modifier Modifier *pModifier; pModifier = pDerivedObject->GetModifier(stackId); // check if we found the modifier if(pModifier->ClassID() == id) return pModifier; } // continue with next derived object pObject = pDerivedObject->GetObjRef(); } return NULL; }
Modifier* PhyExportUtil::findPhysiqueModifier( INode* node ) { // Get object from node. Abort if no object. ::Object* obj = node->GetObjectRef(); if ( !obj ) return 0; // Is derived object ? while ( obj->SuperClassID() == GEN_DERIVOB_CLASS_ID && obj ) { // Yes -> Cast. IDerivedObject* derivedObj = static_cast<IDerivedObject*>( obj ); // Iterate over all entries of the modifier stack. for ( int modStackIndex = 0 ; modStackIndex < derivedObj->NumModifiers() ; ++modStackIndex ) { // Get current modifier. Modifier* modPtr = derivedObj->GetModifier( modStackIndex ); // Is this Physique ? if ( modPtr->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B) ) { // Yes -> Exit. return modPtr; } } obj = derivedObj->GetObjRef(); } // Not found. return 0; }
// ================================================== FindPhysiqueModifier() // Find if a given node contains a Physique Modifier // DerivedObjectPtr requires you include "modstack.h" from the MAX SDK Modifier* FindPhysiqueModifier (INode* nodePtr) { // Get object from node. Abort if no object. Object* ObjectPtr = nodePtr->GetObjectRef(); if ( NULL == ObjectPtr) return NULL; // Is derived object ? if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID){ // Yes -> Cast. IDerivedObject* DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr); // Iterate over all entries of the modifier stack. int ModStackIndex = 0; while (ModStackIndex < DerivedObjectPtr->NumModifiers()){ // Get current modifier. Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex); Class_ID clsid = ModifierPtr->ClassID(); // Is this Physique ? if (ModifierPtr->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B)) { // Yes -> Exit. return ModifierPtr; } // Next modifier stack entry. ModStackIndex++; } } // Not found. return NULL; }
Modifier *CMaxMesh::FindPhysiqueModifier(INode *pINode) { // get the object reference of the node Object *pObject; pObject = pINode->GetObjectRef(); if(pObject == 0) return 0; // loop through all derived objects while(pObject->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject *pDerivedObject; pDerivedObject = static_cast<IDerivedObject *>(pObject); // loop through all modifiers int stackId; for(stackId = 0; stackId < pDerivedObject->NumModifiers(); stackId++) { // get the modifier Modifier *pModifier; pModifier = pDerivedObject->GetModifier(stackId); // check if we found the physique modifier if(pModifier->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B)) return pModifier; } // continue with next derived object pObject = pDerivedObject->GetObjRef(); } return 0; }
ModContext* FindModContext(INode* pNode, Modifier* mod) { IDerivedObject *derivObj; if( pNode->GetObjectRef()->SuperClassID() == GEN_DERIVOB_CLASS_ID ) derivObj = (IDerivedObject*)pNode->GetObjectRef(); else return NULL; int i=0, count=derivObj->NumModifiers(); for( i=0; i<count; i++ ) if( (derivObj->GetModifier(i)) == mod ) break; if( i==count ) return NULL; //the search failed return derivObj->GetModContext(i); }
PaintDefromModData *PaintDeformTest::GetPMD(INode *pNode) { ModContext *mc = NULL; Object* pObj = pNode->GetObjectRef(); if (!pObj) return NULL; while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID && mc == NULL) { IDerivedObject* pDerObj = (IDerivedObject *)(pObj); int Idx = 0; while (Idx < pDerObj->NumModifiers()) { // Get the modifier. Modifier* mod = pDerObj->GetModifier(Idx); if (mod->ClassID() == PAINTDEFORMTEST_CLASS_ID) { // is this the correct Physique Modifier based on index? PaintDeformTest *pmod = (PaintDeformTest*)mod; if (pmod == this) { mc = pDerObj->GetModContext(Idx); break; } } Idx++; } pObj = pDerObj->GetObjRef(); } if(!mc) return NULL; if ( !mc->localData ) return NULL; PaintDefromModData *bmd = (PaintDefromModData *) mc->localData; return bmd; }
bool RBExport::MeshModStackIsValid( INode* node ) { Object* pObj = node->GetObjectRef(); if (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject* pDerivedObj = (IDerivedObject*)pObj; int nMod = pDerivedObj->NumModifiers(); if (nMod == 0) return true; if (nMod > 1) return false; Class_ID id = pDerivedObj->GetModifier( 0 )->ClassID(); return (id == SKIN_CLASSID || id == Class_ID( PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B )); } else { return true; } return false; } // RBExport::MeshModStackIsValid
ISkin* CExporter::getISkinPtr(Object* object) { assert(object != NULL); while (GEN_DERIVOB_CLASS_ID == object->SuperClassID()) { IDerivedObject* pDerObj = static_cast<IDerivedObject*>(object); for (int i = 0; i < pDerObj->NumModifiers(); ++i) { Modifier* mod = pDerObj->GetModifier(i); if (SKIN_CLASSID == mod->ClassID()) { return (ISkin*)(mod->GetInterface(I_SKIN)); } } object = pDerObj->GetObjRef(); } return NULL; }
void HavokImport::HandleRagdollOnNonAccum(INode* accumChild, INode* ragdollParent) { const int MaxChar = 512; char buffer[MaxChar]; //Fix for nonaccumNodes //TSTR name(A2THelper(buffer, parent->GetName().c_str(), _countof(buffer))); ragdollParent->SetName(FormatText(TEXT("Ragdoll_%s"), accumChild->GetName())); Object *Obj = ragdollParent->GetObjectRef(); if (Obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { while (Obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject *DerObj = static_cast<IDerivedObject *> (Obj); const int nMods = DerObj->NumModifiers(); for (int i = 0; i < nMods; i++) { Modifier *Mod = DerObj->GetModifier(i); if (Mod->ClassID() == HK_RIGIDBODY_MODIFIER_CLASS_ID) { ICustAttribContainer* cc = Mod->GetCustAttribContainer(); if (cc) { //reset Mod->DeleteCustAttribContainer(); } Mod->AllocCustAttribContainer(); cc = Mod->GetCustAttribContainer(); CustAttrib* c = (CustAttrib*)CreateInstance(CUST_ATTRIB_CLASS_ID, Class_ID(0x6e663460, 0x32682c72)); IParamBlock2* custModParameters = c->GetParamBlock(0); custModParameters->SetValue(0, 0, accumChild, 0); cc->InsertCustAttrib(0, c); } } Obj = DerObj->GetObjRef(); } } }
Modifier *FindSkinModifier (INode *node) { Object* ObjectPtr = node->GetObjectRef(); if (!ObjectPtr) return NULL; while (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID && ObjectPtr) { IDerivedObject *DerivedObjectPtr = (IDerivedObject *)(ObjectPtr); int ModStackIndex = 0; while (ModStackIndex < DerivedObjectPtr->NumModifiers()) { Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex); if (ModifierPtr->ClassID() == SKIN_CLASSID) return ModifierPtr; ModStackIndex++; } ObjectPtr = DerivedObjectPtr->GetObjRef(); } return NULL; }
//--------------------------------------------------------------- bool SkinController::isSkinned( Object* object ) { if ( !object ) return false; IDerivedObject* derivedObject; Object *currentObject = object; SClass_ID superClassId = object->SuperClassID(); if ( superClassId == GEN_DERIVOB_CLASS_ID || superClassId == DERIVOB_CLASS_ID || superClassId == WSM_DERIVOB_CLASS_ID) { derivedObject = (IDerivedObject*)object; if ( derivedObject->NumModifiers() < 1 ) return false; Modifier* modifier = derivedObject->GetModifier(0); return SkinController::isSkinController(modifier); } return false; }
Modifier *CMaxMesh::FindMorpherModifier(INode *pINode) { // get the object reference of the node Object *pObject; pObject = pINode->GetObjectRef(); if(pObject == 0) return 0; // loop through all derived objects while(pObject->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject *pDerivedObject; pDerivedObject = static_cast<IDerivedObject *>(pObject); // loop through all modifiers int stackId; for(stackId = 0; stackId < pDerivedObject->NumModifiers(); stackId++) { // get the modifier Modifier *pModifier; pModifier = pDerivedObject->GetModifier(stackId); Class_ID id = pModifier->ClassID(); char buf[512]; sprintf(buf, "node %s modifier %d class %d:%d/0x%x:0x%x\n", pINode->GetName(), stackId, id.PartA(), id.PartB(), id.PartA(), id.PartB()); ::OutputDebugStringA(buf); // check if we found the physique modifier if(pModifier->ClassID() == MR3_CLASS_ID) { ::OutputDebugStringA("that was it! the morpher I was looking for!\n"); return pModifier; } } // continue with next derived object pObject = pDerivedObject->GetObjRef(); } return 0; }
Modifier *FindBonesProModifier (INode *nodePtr) { // Get object from node. Abort if no object. Object *ObjectPtr = nodePtr->GetObjectRef(); if (!ObjectPtr) return NULL; // Is derived object ? if (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID) { // Yes -> Cast. IDerivedObject *DerivedObjectPtr = static_cast<IDerivedObject*>(ObjectPtr); // Iterate over all entries of the modifier stack. int ModStackIndex = 0; while (ModStackIndex < DerivedObjectPtr->NumModifiers()) { // Get current modifier. Modifier *ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex); // Is this Bones Pro OSM? if (ModifierPtr->ClassID() == BP_CLASS_ID_OSM ) { // Yes -> Exit. return ModifierPtr; } // Is this Bones Pro WSM? if (ModifierPtr->ClassID() == BP_CLASS_ID_WSM ) { // Yes -> Exit. return ModifierPtr; } // Next modifier stack entry. ModStackIndex++; } } // Not found. return NULL; }
// --[ Method ]--------------------------------------------------------------- // // - Class : CStravaganzaMaxTools // // - prototype : Modifier* GetPhysiqueModifier(INode* pMaxNode) // // - Purpose : Returns the Physique modifier of a given node if present. // // ----------------------------------------------------------------------------- Modifier* CStravaganzaMaxTools::GetPhysiqueModifier(INode* pMaxNode) { Object* pMaxObject = pMaxNode->GetObjectRef(); if(!pMaxObject) { return NULL; } while(pMaxObject->SuperClassID() == GEN_DERIVOB_CLASS_ID && pMaxObject) { // Yes -> Cast. IDerivedObject* pMaxDerivedObject = (IDerivedObject *)(pMaxObject); // Iterate over all entries of the modifier stack. int nModStackIndex = 0; while(nModStackIndex < pMaxDerivedObject->NumModifiers()) { // Get current modifier. Modifier* pMaxModifier = pMaxDerivedObject->GetModifier(nModStackIndex); // Is this Physique? if(pMaxModifier->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B)) { return pMaxModifier; } nModStackIndex++; } pMaxObject = pMaxDerivedObject->GetObjRef(); } // Not found. return NULL; }
//--------------------------------------------------------------- void ControllerList::resolveControllers( const ExportNode& exportNode ) { Object* object = exportNode.getINode()->GetObjectRef(); if ( !object ) return; if ( exportNode.getIsXRefObject() ) object = XRefFunctions::getXRefItemSource(object); if ( !object ) return; SClass_ID superClassId; IDerivedObject* derivedObject; Object *currentObject = object; //int modIdx = 0; superClassId = object->SuperClassID(); if (superClassId == GEN_DERIVOB_CLASS_ID || superClassId == DERIVOB_CLASS_ID || superClassId == WSM_DERIVOB_CLASS_ID) { derivedObject = (IDerivedObject*)object; while (superClassId == GEN_DERIVOB_CLASS_ID || superClassId == DERIVOB_CLASS_ID || superClassId == WSM_DERIVOB_CLASS_ID) { for (int modifierIndex = 0; modifierIndex < derivedObject->NumModifiers(); ++modifierIndex) { Modifier* modifier = derivedObject->GetModifier(modifierIndex); //no iskin support for xrefs // TODO needs further investigation... if ( SkinController::isSkinController(modifier) /*&& !exportNode.getIsXRefObject() */) { SkinController * skinController = new SkinController(derivedObject, modifierIndex, modifier->IsEnabled() != false); mControllers.push_back(skinController); } else if ( MorphController::isMorphController(modifier) ) { MorphController * morphController = new MorphController(derivedObject, modifierIndex, modifier->IsEnabled() != false); mControllers.push_back(morphController); } else return; } derivedObject = (IDerivedObject*) derivedObject->GetObjRef(); currentObject = (Object*) derivedObject; superClassId = derivedObject->SuperClassID(); } } /* int bct = currentObject->NumPipeBranches(FALSE); if (bct > 0) { for (int bi = 0; bi < bct; bi++) { Object* bobj = currentObject->GetPipeBranch(bi,FALSE); Resolve(bobj); return; } } */ }
void SkeletonExporter::export_particle_spray(INode *node) { char sval[50]; Interval range = ip->GetAnimRange(); ObjectState os = node->EvalWorldState(0); if (!os.obj) return; SimpleParticle *partsys; Object *p; IDerivedObject *q; Modifier *m; partsys=(SimpleParticle *)os.obj; Point3 row; Matrix3 mat; Mtl *materiale; INode *padre=node->GetParentNode(); int mod_names=0, k, mod_count=0; char modNames[25][50], refname[50]; int sf, sm, mf, n; if ((padre) && (strcmp(padre->GetName(), "Scene Root")!=0)) sf=strlen(padre->GetName())+1; else sf=0; materiale=node->GetMtl(); if (materiale) sm=strlen(materiale->GetName())+1; else sm=0; mf=0; // trovo i modificatori Wind e Gravity con il loro // nome p=node->GetObjOrWSMRef(); if ((p->SuperClassID()==GEN_DERIVOB_CLASS_ID) && (p->ClassID()==Class_ID(WSM_DERIVOB_CLASS_ID, 0))) { q=(IDerivedObject *)p; n=q->NumModifiers(); mod_names=mod_count=0; for (k=0; k<n; k++) { m=q->GetModifier(k); Class_ID cidd = m->ClassID(); if ((cidd==Class_ID(WINDMOD_CLASS_ID, 0)) || (cidd==Class_ID(GRAVITYMOD_CLASS_ID, 0)) || (cidd==Class_ID(BOMB_OBJECT_CLASS_ID, 0))) { SimpleWSMMod *wm=(SimpleWSMMod *)m; strcpy(refname, wm->nodeRef->GetName()); strcpy(modNames[mod_count], refname); mod_names+=(strlen(refname)+1); mod_count++; } } } write_chunk_header(fA3D, SPRAY_PARTICLE_SYSTEM_ID, node->GetName(), 4+sf+4+sm+ // padre, materiale 12+48+ //pivot, matrice world(t=0) 4+mf+ // nome mesh/oggetto 4+4+4+4+ // emitter: width, height, speed , variation 4+4+4+4+ // life, startTime, stopTime, max_particles 4+mod_names // num WSM, nomi WSM ); fprintf(fTXT, "Spray particle system found\n"); fprintf(fTXT, "Name : %s\n", node->GetName()); if (padre) fprintf(fTXT, "Parent name : %s\n", node->GetParentNode()->GetName()); if (materiale) fprintf(fTXT, "Material name : %s\n", materiale->GetName()); if (makeADP) fprintf(fADP, " particle %c%s%c\n {\n", '"', node->GetName(), '"'); // ----------- scrivo il padre (flag, nome) ------------------ fwrite(&sf, sizeof(int), 1, fA3D); if (sf>0) { write_string0(fA3D, padre->GetName()); if (makeADP) fprintf(fADP, " father=%c%s%c;\n", '"', padre->GetName(), '"'); } else if (makeADP) fprintf(fADP, " father=%cNONE%c;\n", '"', '"'); // --------- scrivo il materiale di base (flag, nome) ---------- fwrite(&sm, sizeof(int), 1, fA3D); if (sm>0) { write_string0(fA3D, materiale->GetName()); //if (makeADP) fprintf(fADP, " material=%c%s%c;\n", '"', materiale->GetName(), '"'); } else //if (makeADP) fprintf(fADP, " material=%cNONE%c;\n", '"', '"'); // --------------- scrittura del punto di pivot ---------------- GetPivotOffset(node, &row); fprintf(fTXT, "Pivot point : %f, %f, %f\n", row.x, row.y, row.z); write_point3(&row, fA3D); // ------------------- scrittura matrice ----------------------- mat = node->GetNodeTM(0); write_matrix(&mat, fA3D); // --------- scrittura dell'eventuale nome della mesh ---------- fwrite(&mf, sizeof(int), 1, fA3D); if (mf>0) { write_string0(fA3D, "TO_DO"); if (makeADP) fprintf(fADP, " lod=%cTO_DO, 0, 99999.99%c;\n", '"', '"'); } // ************* ESPORAZIONE DATI DEL PARTCLE SYSTEM ************* float initVel, var, width, height; int count, life, start_time, stop_time; partsys->pblock->GetValue(PB_EMITTERWIDTH, 0, width, FOREVER); partsys->pblock->GetValue(PB_EMITTERHEIGHT, 0, height, FOREVER); partsys->pblock->GetValue(PB_SPEED, 0, initVel, FOREVER); partsys->pblock->GetValue(PB_VARIATION, 0, var, FOREVER); partsys->pblock->GetValue(PB_LIFETIME, 0, life, FOREVER); life=life/ GetTicksPerFrame(); partsys->pblock->GetValue(PB_STARTTIME, 0, start_time, FOREVER); start_time=start_time / GetTicksPerFrame(); stop_time=range.End() / GetTicksPerFrame(); partsys->pblock->GetValue(PB_RNDPARTICLES, 0, count, FOREVER); fprintf(fTXT, "Emitter width: %f\n", width); fprintf(fTXT, "Emitter height: %f\n", height); fprintf(fTXT, "Emitter speed (init vel): %f\n", initVel); fprintf(fTXT, "Emitter variation: %f\n", var); fprintf(fTXT, "Life: %d\n", life); fprintf(fTXT, "Start time: %d\n", start_time); fprintf(fTXT, "Stop time: %d\n", stop_time); fprintf(fTXT, "Max particles: %d\n", count); // informazioni in formato binario (.A3D) fwrite(&width, sizeof(float), 1, fA3D); fwrite(&height, sizeof(float), 1, fA3D); fwrite(&initVel, sizeof(float), 1, fA3D); fwrite(&var, sizeof(float), 1, fA3D); fwrite(&life, sizeof(int), 1, fA3D); fwrite(&start_time, sizeof(int), 1, fA3D); fwrite(&stop_time, sizeof(int), 1, fA3D); fwrite(&count, sizeof(int), 1, fA3D); fwrite(&mod_count, sizeof(int), 1, fA3D); fprintf(fTXT, "Modificatori (wind, gravity, bomb) collegati: %d\n", mod_count); for (k=0; k<mod_count; k++) { fprintf(fTXT, "Modificatore %d: %s\n", k, modNames[k]); write_string0(fA3D, modNames[k]); //if (makeADP) //fprintf(fADP, " modifier=%c%s, ON%c;\n", '"', modNames[k], '"'); } //------------------------ // ESPORTAZIONE KEYFRAMER //------------------------ Control *c; int size_key; // NB: per gli oggetti mesh e quant'altre tipologie di // oggetti che possono essere linkati (ovvero dove e' // possibile implmenetare gerarchie), esporto SEMPRE una key // di posizione, una di rotazione ed una di scaling // POSITION CONTROLLER c=node->GetTMController()->GetPositionController(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=36; else if (IsBezierControl(c)) size_key=40; else size_key=16; fprintf(fTXT, "Particle position track present.\n"); write_chunk_header(fA3D, POSITION_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_point3_track(c, 1, fA3D); } else { fprintf(fTXT, "Particle position track present. (1 key case)\n"); if (!c) fprintf(fTXT, "c nullo !\n"); fflush(fTXT); size_key=36; write_chunk_header(fA3D, POSITION_TRACK_ID, node->GetName(), 1+2+4+1*size_key); export_1key_point3_track(c, 1, fA3D); } // ROTATION CONTROLLER c=node->GetTMController()->GetRotationController(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=40; else size_key=20; fprintf(fTXT, "Particle rotation track present.\n"); write_chunk_header(fA3D, ROTATION_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_rot_track(c, fA3D); } else { fprintf(fTXT, "Particle rotation track present. (1 key case)\n"); fflush(fTXT); size_key=40; write_chunk_header(fA3D, ROTATION_TRACK_ID, node->GetName(), 1+2+4+1*size_key); export_1key_rot_track(c, fA3D); } // SCALE CONTROLLER c=node->GetTMController()->GetScaleController(); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=36; else if (IsBezierControl(c)) size_key=40; else size_key=16; fprintf(fTXT, "Particle scaling track present.\n"); write_chunk_header(fA3D, SCALE_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_scale_track(c, fA3D); } else { fprintf(fTXT, "Particle scaling track present. (1 key case)\n"); size_key=36; write_chunk_header(fA3D, SCALE_TRACK_ID, node->GetName(), 1+2+4+1*size_key); export_1key_scale_track(c, fA3D); } // keyframer emitter width c=partsys->pblock->GetController(PB_EMITTERWIDTH); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=28; else if (IsBezierControl(c)) size_key=16; else size_key=8; fprintf(fTXT, "Particle emitter width track present.\n"); write_chunk_header(fA3D, PARTICLE_EMITTER_WIDTH_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_float_track(c, 1, fA3D); } // keyframer emitter length c=partsys->pblock->GetController(PB_EMITTERHEIGHT); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=28; else if (IsBezierControl(c)) size_key=16; else size_key=8; fprintf(fTXT, "Particle emitter length track present.\n"); write_chunk_header(fA3D, PARTICLE_EMITTER_LENGTH_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_float_track(c, 1, fA3D); } // keyframer particles speed c=partsys->pblock->GetController(PB_SPEED); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=28; else if (IsBezierControl(c)) size_key=16; else size_key=8; fprintf(fTXT, "Particle emitter speed track present.\n"); write_chunk_header(fA3D, PARTICLE_EMITTER_SPEED_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_float_track(c, 1, fA3D); } // keyframer particles variations c=partsys->pblock->GetController(PB_VARIATION); if ((c) && (c->NumKeys()>0)) { if (IsTCBControl(c)) size_key=28; else if (IsBezierControl(c)) size_key=16; else size_key=8; fprintf(fTXT, "Particle emitter variation track present.\n"); write_chunk_header(fA3D, PARTICLE_EMITTER_VARIATION_TRACK_ID, node->GetName(), 1+2+4+c->NumKeys()*size_key); export_float_track(c, 1, fA3D); } if (makeADP) { fprintf(fADP, " texture=%cNONE%c;\n", '"', '"'); my_ftoa(width, sval); fprintf(fADP, " emitter_width=%c%s%c;\n", '"', sval, '"'); my_ftoa(height, sval); fprintf(fADP, " emitter_height=%c%s%c;\n", '"', sval, '"'); fprintf(fADP, " faded_particles=%cOFF%c;\n", '"', '"'); fprintf(fADP, " max_particles=%c%d%c;\n", '"', count, '"'); fprintf(fADP, " start_time=%c%d%c;\n", '"', start_time, '"'); fprintf(fADP, " end_time=%c%d%c;\n", '"', stop_time, '"'); fprintf(fADP, " life=%c%d%c;\n", '"', life, '"'); my_ftoa(initVel, sval); fprintf(fADP, " speed=%c%s%c;\n", '"', sval, '"'); my_ftoa(var, sval); fprintf(fADP, " variation=%c%s%c;\n", '"', sval, '"'); fprintf(fADP, " size_attenuation=%c0.4, 1.0, 0.8, 0.1%c;\n", '"', '"'); fprintf(fADP, " }\n\n"); } fprintf(fTXT, "\n\n"); }
void MaxAWDExporter::ProcessGeoBlocks() { AWDTriGeom *geoBlock; AWDBlockIterator *it; int proccessed=0; it = new AWDBlockIterator(awd->get_mesh_data_blocks()); UpdateProgressBar(MAXAWD_PHASE_PROCESS_GEOMETRY, (double)proccessed/(double)awd->get_mesh_data_blocks()->get_num_blocks()); INodeTab lNodes; while ((geoBlock = (AWDTriGeom * ) it->next()) != NULL){ INode * node = (INode *)INodeToGeoBlockCache->Get(geoBlock); if (node==NULL){ AWDMessageBlock * newWarning = new AWDMessageBlock(geoBlock->get_name(), "ERROR: Could not find the INode for this AWDGeometry."); awd->get_message_blocks()->append(newWarning); return; } lNodes.AppendNode( node ); } IGameScene* _pIgame = NULL; _pIgame = GetIGameInterface(); _pIgame->InitialiseIGame( lNodes ); it->reset(); while ((geoBlock = (AWDTriGeom * ) it->next()) != NULL){ INode * node = (INode *)INodeToGeoBlockCache->Get(geoBlock); if (node==NULL){ AWDMessageBlock * newWarning = new AWDMessageBlock(geoBlock->get_name(), "ERROR: Could not find the INode for this AWDGeometry."); awd->get_message_blocks()->append(newWarning); } else{ int exportThis=false; IGameObject * gobj = NULL; IGameMesh * igame_mesh = NULL; gobj = GetIGameInterface()->GetIGameNode(node)->GetIGameObject(); if(gobj->GetIGameType()==IGameObject::IGAME_MESH){ igame_mesh = (IGameMesh*)gobj; if (igame_mesh!=NULL){ igame_mesh->InitializeData(); if(igame_mesh->GetNumberOfFaces()>0){ exportThis=true; } } } if (exportThis){ Object *obj; obj = node->GetObjectRef(); int skinIdx; ObjectState os; IDerivedObject *derivedObject = NULL; skinIdx = IndexOfSkinMod(node->GetObjectRef(), &derivedObject); if (skinIdx >= 0) { // Flatten all modifiers up to but not including // the skin modifier. // to do: get the correct time for the neutral-pose os = derivedObject->Eval(0, skinIdx + 1); } else { // Flatten entire modifier stack // to do: get the correct time for the neutral-pose os = node->EvalWorldState(maxInterface->GetTime()); } obj = os.obj; ISkin *skin = NULL; if (derivedObject != NULL && skinIdx >= 0) { Modifier *mod = derivedObject->GetModifier(skinIdx); skin = (ISkin *)mod->GetInterface(I_SKIN); } ExportTriGeom(geoBlock,obj,node,skin, igame_mesh); RETURN_IF_ERROR; } } proccessed++; UpdateProgressBar(MAXAWD_PHASE_PROCESS_GEOMETRY, (double)proccessed/(double)awd->get_mesh_data_blocks()->get_num_blocks()); } delete it; _pIgame->ReleaseIGame(); }
static void extractTriangleGeometry( GmModel* gm, INode* node, Mesh* mesh, Mtl* material ) { #ifdef SGEXPORT_PHYSIQUE Modifier* phyMod = 0; IPhysiqueExport* phyExport = 0; IPhyContextExport* mcExport = 0; #endif Modifier* skinMod = 0; ISkin* skin = 0; String nodeName ( node->GetName() ); try { // vertex transform to left-handed system Matrix3 pivot = TmUtil::getPivotTransform( node ); Matrix3 vertexTM = pivot * s_convtm; bool insideOut = TmUtil::hasNegativeParity( pivot ); /*Matrix4x4 pm = TmUtil::toLH( vertexTM ); Debug::println( "Object {0} vertex local TM is", nodeName ); Debug::println( " {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(0,0), pm(0,1), pm(0,2), pm(0,3) ); Debug::println( " {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(1,0), pm(1,1), pm(1,2), pm(1,3) ); Debug::println( " {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(2,0), pm(2,1), pm(2,2), pm(2,3) ); Debug::println( " {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(3,0), pm(3,1), pm(3,2), pm(3,3) );*/ // add vertex positions int vertices = mesh->getNumVerts(); for ( int vi = 0 ; vi < vertices ; ++vi ) { Point3 v = vertexTM * mesh->verts[vi]; mb::Vertex* vert = gm->addVertex(); vert->setPosition( v.x, v.y, v.z ); } // add vertex weights (from Physique modifier) #ifdef SGEXPORT_PHYSIQUE phyMod = PhyExportUtil::findPhysiqueModifier( node ); if ( phyMod ) { Debug::println( " Found Physique modifier: {0}", gm->name ); // get (possibly shared) Physique export interface phyExport = (IPhysiqueExport*)phyMod->GetInterface( I_PHYINTERFACE ); if( !phyExport ) throw Exception( Format("No Physique modifier export interface") ); // export from initial pose? phyExport->SetInitialPose( false ); // get (unique) context dependent export inteface mcExport = (IPhyContextExport*)phyExport->GetContextInterface( node ); if( !mcExport ) throw Exception( Format("No Physique modifier context export interface") ); // convert to rigid for time independent vertex assignment mcExport->ConvertToRigid( true ); // allow blending to export multi-link assignments mcExport->AllowBlending( true ); // list bones Vector<INode*> bones( Allocator<INode*>(__FILE__,__LINE__) ); PhyExportUtil::listBones( mcExport, bones ); // add vertex weight maps for ( int i = 0 ; i < bones.size() ; ++i ) { INode* bone = bones[i]; String name = bone->GetName(); mb::VertexMap* vmap = gm->addVertexMap( 1, name, mb::VertexMapFormat::VERTEXMAP_WEIGHT ); PhyExportUtil::addWeights( vmap, bone, mcExport ); } } #endif // SGEXPORT_PHYSIQUE // add vertex weights (from Skin modifier) skinMod = SkinExportUtil::findSkinModifier( node ); if ( skinMod ) { skin = (ISkin*)skinMod->GetInterface(I_SKIN); require( skin ); ISkinContextData* skincx = skin->GetContextInterface( node ); require( skincx ); Debug::println( " Found Skin modifier: {0} ({1} bones, {2} points)", gm->name, skin->GetNumBones(), skincx->GetNumPoints() ); if ( skincx->GetNumPoints() != gm->vertices() ) throw Exception( Format("Only some vertices ({0}/{1}) of {2} are skinned", skincx->GetNumPoints(), gm->vertices(), gm->name) ); // list bones Vector<INode*> bones( Allocator<INode*>(__FILE__,__LINE__) ); SkinExportUtil::listBones( skin, bones ); // add vertex weight maps for ( int i = 0 ; i < bones.size() ; ++i ) { INode* bone = bones[i]; String name = bone->GetName(); mb::VertexMap* vmap = gm->addVertexMap( 1, name, mb::VertexMapFormat::VERTEXMAP_WEIGHT ); SkinExportUtil::addWeights( vmap, bone, skin, skincx ); //Debug::println( " Bone {0} is affecting {1} vertices", name, vmap->size() ); } // DEBUG: print skin node tm and initial object tm /*Matrix3 tm; int ok = skin->GetSkinInitTM( node, tm ); require( ok == SKIN_OK ); Debug::println( " NodeInitTM of {0}", nodeName ); TmUtil::println( tm, 4 ); ok = skin->GetSkinInitTM( node, tm, true ); require( ok == SKIN_OK ); Debug::println( " NodeObjectTM of {0}", nodeName ); TmUtil::println( tm, 4 );*/ // DEBUG: print bones /*Debug::println( " bones of {0}:", nodeName ); for ( int i = 0 ; i < bones.size() ; ++i ) { Debug::println( " bone ({0}): {1}", i, String(bones[i]->GetName()) ); skin->GetBoneInitTM( bones[i], tm ); Debug::println( " InitNodeTM:" ); TmUtil::println( tm, 6 ); skin->GetBoneInitTM( bones[i], tm, true ); Debug::println( " InitObjectTM:" ); TmUtil::println( tm, 6 ); }*/ // DEBUG: print bones used by the points /*for ( int i = 0 ; i < skincx->GetNumPoints() ; ++i ) { int bonec = skincx->GetNumAssignedBones(i); Debug::println( " point {0} has {1} bones", i, bonec ); for ( int k = 0 ; k < bonec ; ++k ) { int boneidx = skincx->GetAssignedBone( i, k ); float w = skincx->GetBoneWeight( i, k ); Debug::println( " point {0} boneidx ({1}): {2}, weight {3}", i, k, boneidx, w ); } }*/ } // ensure clockwise polygon vertex order int vx[3] = {2,1,0}; if ( insideOut ) { int tmp = vx[0]; vx[0] = vx[2]; vx[2] = tmp; } // list unique materials used by the triangles Vector<ShellMaterial> usedMaterials( Allocator<ShellMaterial>(__FILE__,__LINE__) ); if ( material ) { for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi ) { Face& face = mesh->faces[fi]; int mergesubmaterial = -1; int originalsubmaterial = -1; for ( int j = 0; j < material->NumSubMtls(); ++j) { // Get Sub Material Slot name TSTR name = material->GetSubMtlSlotName(j); // Light maps are stored in sub material slot named "Baked Material" if ( strcmp( name, "Baked Material" ) == 0 ) mergesubmaterial = j; else originalsubmaterial = j; } if ( mergesubmaterial != -1 ) // A baked material was found, shell materials will be created { Mtl* mat = material->GetSubMtl( originalsubmaterial ); Mtl* bakedmtl = material->GetSubMtl( mergesubmaterial ); if ( mat->NumSubMtls() > 0 ) // Check for nested multi-material { for ( int j = 0; j < mat->NumSubMtls(); ++j) usedMaterials.add( ShellMaterial( mat->GetSubMtl( face.getMatID() % mat->NumSubMtls() ), bakedmtl ) ); } else usedMaterials.add( ShellMaterial( mat, bakedmtl ) ); } else if ( material->NumSubMtls() > 0 ) // Multi-material without baked material { usedMaterials.add( ShellMaterial( material->GetSubMtl( face.getMatID() % material->NumSubMtls() ), 0 ) ); } else // Single material without baked material { usedMaterials.add( ShellMaterial( material, 0 ) ); } } std::sort( usedMaterials.begin(), usedMaterials.end() ); usedMaterials.setSize( std::unique( usedMaterials.begin(), usedMaterials.end() ) - usedMaterials.begin() ); } // create used materials for ( int mi = 0 ; mi < usedMaterials.size() ; ++mi ) { ShellMaterial shellmtl = usedMaterials[mi]; gm->materials.add( GmUtil::createGmMaterial( shellmtl.original, shellmtl.baked ) ); } // add triangles for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi ) { mb::Polygon* poly = gm->addPolygon(); // triangle indices Face& face = mesh->faces[fi]; for ( int vxi = 0 ; vxi < 3 ; ++vxi ) { int vi = face.v[ vx[vxi] ]; require( vi >= 0 && vi < gm->vertices() ); mb::Vertex* vert = gm->getVertex( vi ); poly->addVertex( vert ); } // triangle material int polyMaterialIndex = 0; if ( material ) { ShellMaterial mat( material, 0 ); int numsubmaterials = material->NumSubMtls(); if ( numsubmaterials > 0 ) { mat.original = material->GetSubMtl( face.getMatID() % material->NumSubMtls() ); for ( int j = 0; j < numsubmaterials; ++j) // Is baked material present? { TSTR name = material->GetSubMtlSlotName(j); if ( strcmp( name, "Baked Material" ) == 0 ) mat.baked = material->GetSubMtl( j ); if ( strcmp( name, "Original Material" ) == 0 ) mat.original = material->GetSubMtl( j ); } if ( mat.original->NumSubMtls() > 0 ) // Is there a nested multi-material? { mat.original = mat.original->GetSubMtl( face.getMatID() % mat.original->NumSubMtls() ); } } for ( int mi = 0 ; mi < usedMaterials.size() ; ++mi ) { if ( usedMaterials[mi] == mat ) { polyMaterialIndex = mi; break; } } } poly->setMaterial( polyMaterialIndex ); } // add vertex colors int mp = 0; if ( mesh->mapSupport(mp) && mesh->getNumMapVerts(mp) > 0 ) { mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 3, "rgb", mb::VertexMapFormat::VERTEXMAP_RGB ); int tverts = mesh->getNumMapVerts( mp ); UVVert* tvert = mesh->mapVerts( mp ); TVFace* tface = mesh->mapFaces( mp ); //Debug::println( "Vertex colors:" ); for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi ) { Face& face = mesh->faces[fi]; mb::Polygon* poly = gm->getPolygon( fi ); for ( int vxi = 0 ; vxi < 3 ; ++vxi ) { int vi = face.v[ vx[vxi] ]; mb::Vertex* vert = gm->getVertex( vi ); Point3 tc = tvert[ tface[fi].t[ vx[vxi] ] % tverts ]; float rgb[3] = {tc.x, tc.y, tc.z}; vmad->addValue( vert->index(), poly->index(), rgb, 3 ); //Debug::println( " vertex[{0}].rgb: {1} {2} {3}", vert->index(), rgb[0], rgb[1], rgb[2] ); } } } // add texcoord layers int lastCoords = MAX_MESHMAPS-2; while ( lastCoords > 0 && (!mesh->mapSupport(lastCoords) || 0 == mesh->getNumMapVerts(lastCoords)) ) --lastCoords; if ( lastCoords > 8 ) throw IOException( Format("Too many texture coordinate sets ({1}) in {0}", gm->name, lastCoords) ); for ( mp = 1 ; mp <= lastCoords ; ++mp ) { mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 2, "uv", mb::VertexMapFormat::VERTEXMAP_TEXCOORD ); if ( mesh->mapSupport(mp) && mesh->getNumMapVerts(mp) > 0 ) { int tverts = mesh->getNumMapVerts( mp ); UVVert* tvert = mesh->mapVerts( mp ); TVFace* tface = mesh->mapFaces( mp ); for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi ) { Face& face = mesh->faces[fi]; mb::Polygon* poly = gm->getPolygon( fi ); for ( int vxi = 0 ; vxi < 3 ; ++vxi ) { int vi = face.v[ vx[vxi] ]; mb::Vertex* vert = gm->getVertex( vi ); Point3 tc = tvert[ tface[fi].t[ vx[vxi] ] % tverts ]; float uv[2] = {tc.x, 1.f-tc.y}; vmad->addValue( vert->index(), poly->index(), uv, 2 ); } } } } // compute face vertex normals from smoothing groups require( mesh->getNumFaces() == gm->polygons() ); mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 3, "vnormals", mb::VertexMapFormat::VERTEXMAP_NORMALS ); for ( int fi = 0 ; fi < gm->polygons() ; ++fi ) { mb::Polygon* poly = gm->getPolygon( fi ); require( poly ); require( poly->index() >= 0 && poly->index() < mesh->getNumFaces() ); Face& face = mesh->faces[ poly->index() ]; require( poly->vertices() == 3 ); for ( int j = 0 ; j < poly->vertices() ; ++j ) { Vector3 vn(0,0,0); mb::Vertex* vert = poly->getVertex( j ); // sum influencing normals for ( int k = 0 ; k < vert->polygons() ; ++k ) { mb::Polygon* vpoly = vert->getPolygon( k ); require( vpoly ); require( vpoly->index() >= 0 && vpoly->index() < mesh->getNumFaces() ); Face& vface = mesh->faces[ vpoly->index() ]; if ( 0 != (face.smGroup & vface.smGroup) || poly == vpoly ) { Vector3 vpolyn; vpoly->getNormal( &vpolyn.x, &vpolyn.y, &vpolyn.z ); vn += vpolyn; } } // normalize float lensqr = vn.lengthSquared(); if ( lensqr > Float::MIN_VALUE ) vn *= 1.f / Math::sqrt(lensqr); else vn = Vector3(0,0,0); vmad->addValue( vert->index(), poly->index(), vn.begin(), 3 ); } } // re-export mesh points in non-deformed pose if Skin modifier present // NOTE: 3ds Mesh must not be used after this, because collapsing can invalidate it if ( skin ) { // evaluate derived object before Skin modifier TimeValue time = 0; bool evalNext = false; bool evalDone = false; ::ObjectState os; ::Object* obj = node->GetObjectRef(); while ( obj->SuperClassID() == GEN_DERIVOB_CLASS_ID && !evalDone ) { IDerivedObject* derivedObj = static_cast<IDerivedObject*>(obj); for ( int modStack = 0 ; modStack < derivedObj->NumModifiers() ; ++modStack ) { if ( evalNext ) { os = derivedObj->Eval( time, modStack ); evalDone = true; break; } Modifier* mod = derivedObj->GetModifier(modStack); if ( mod->ClassID() == SKIN_CLASSID ) evalNext = true; } obj = derivedObj->GetObjRef(); } // evaluate possible non-derived object if ( evalNext && !evalDone ) { os = obj->Eval( time ); evalDone = true; } // convert to TriObject and get points if ( evalDone && os.obj->CanConvertToType( Class_ID(TRIOBJ_CLASS_ID,0) ) ) { Debug::println( " Evaluating object {0} before Skin modifier", nodeName ); // get TriObject std::auto_ptr<TriObject> triAutoDel(0); TriObject* tri = static_cast<TriObject*>( os.obj->ConvertToType( time, Class_ID(TRIOBJ_CLASS_ID,0) ) ); if ( tri != os.obj ) triAutoDel = std::auto_ptr<TriObject>( tri ); // get mesh points before Skin is applied //Debug::println( " Original collapsed mesh has {0} points, before Skin modifier {1} points", mesh->getNumVerts(), tri->mesh.getNumVerts() ); require( gm->vertices() == tri->mesh.getNumVerts() ); Mesh* mesh = &tri->mesh; int vertices = mesh->getNumVerts(); for ( int vi = 0 ; vi < vertices ; ++vi ) { Point3 v = vertexTM * mesh->verts[vi]; mb::Vertex* vert = gm->getVertex( vi ); vert->setPosition( v.x, v.y, v.z ); } } } // split vertices with discontinuous vertex map values for ( int vmi = 0 ; vmi < gm->discontinuousVertexMaps() ; ++vmi ) { mb::DiscontinuousVertexMap* vmad = gm->getDiscontinuousVertexMap( vmi ); gm->splitVertexDiscontinuities( vmad ); } // find base texcoord layer mb::DiscontinuousVertexMap* texcoords = 0; for ( int i = 0 ; i < gm->discontinuousVertexMaps() ; ++i ) { mb::DiscontinuousVertexMap* vmad = gm->getDiscontinuousVertexMap(i); if ( vmad->dimensions() == 2 && vmad->format() == mb::VertexMapFormat::VERTEXMAP_TEXCOORD ) { texcoords = vmad; break; } } if ( !texcoords ) Debug::printlnError( "Object {0} must have texture coordinates", gm->name ); // requires identification of footsteps in MySceneExport::isExportableGeometry //throw IOException( Format("Object {0} must have texture coordinates", gm->name) ); // optimize gm->removeUnusedVertices(); // cleanup export interfaces #ifdef SGEXPORT_PHYSIQUE if ( mcExport ) { require( phyExport ); phyExport->ReleaseContextInterface( mcExport ); mcExport = 0; } if ( phyExport ) { require( phyMod ); phyMod->ReleaseInterface( I_PHYINTERFACE, phyExport ); phyExport = 0; } #endif // SGEXPORT_PHYSIQUE if ( skin ) { skinMod->ReleaseInterface( I_SKIN, skin ); skin = 0; skinMod = 0; } } catch ( ... ) { // cleanup export interfaces #ifdef SGEXPORT_PHYSIQUE if ( mcExport ) { require( phyExport ); phyExport->ReleaseContextInterface( mcExport ); mcExport = 0; } if ( phyExport ) { require( phyMod ); phyMod->ReleaseInterface( I_PHYINTERFACE, phyExport ); phyExport = 0; } #endif // SGEXPORT_PHYSIQUE if ( skin ) { skinMod->ReleaseInterface( I_SKIN, skin ); skin = 0; skinMod = 0; } throw; } }
INT_PTR CALLBACK BindProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { M3Mat *mp = (M3Mat*)GetWindowLongPtr(hWnd,GWLP_USERDATA); if (!mp && msg!=WM_INITDIALOG) return FALSE; int id = LOWORD(wParam); int notify = HIWORD(wParam); switch (msg) { case WM_INITDIALOG:{ mp = (M3Mat*)lParam; SetWindowLongPtr(hWnd,GWLP_USERDATA,(LONG_PTR)mp); HWND modList = GetDlgItem(hWnd,IDC_MODLIST); SendMessage(modList,LB_RESETCONTENT,0,0); POINT lpPt; GetCursorPos(&lpPt); SetWindowPos(hWnd, NULL, lpPt.x, lpPt.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); Object *pObj = mp->Wnode->GetObjectRef(); IDerivedObject *pDerObj = NULL; Modifier *pMod = NULL; if( pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { pDerObj = (IDerivedObject *) pObj; for(int i = 0 ; i < pDerObj->NumModifiers() ; i++ ) { pMod = pDerObj->GetModifier(i); SendMessage(modList,LB_ADDSTRING,0,(LPARAM) (LPCTSTR) pMod->GetName()); } } SendMessage(modList,LB_SETCURSEL ,(WPARAM)-1,0); break;} case WM_COMMAND: if (notify==LBN_SELCHANGE){ if(id==IDC_MODLIST){ int mkSel = SendMessage(GetDlgItem(hWnd, IDC_MODLIST), LB_GETCURSEL, 0, 0); if(mkSel>=0){ Object *pObj = mp->Wnode->GetObjectRef(); IDerivedObject *pDerObj = NULL; Modifier *pMod = NULL; if( pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { pDerObj = (IDerivedObject *) pObj; pMod = pDerObj->GetModifier(mkSel); if(pMod->ClassID() == MR3_CLASS_ID) EnableWindow(GetDlgItem(hWnd,IDOK),TRUE); else EnableWindow(GetDlgItem(hWnd,IDOK),FALSE); } } } } switch (id) { case IDOK: { int mkSel = SendMessage(GetDlgItem(hWnd, IDC_MODLIST), LB_GETCURSEL, 0, 0); if(mkSel>=0){ Object *pObj = mp->Wnode->GetObjectRef(); IDerivedObject *pDerObj = NULL; Modifier *pMod = NULL; if( pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { pDerObj = (IDerivedObject *) pObj; pMod = pDerObj->GetModifier(mkSel); MorphR3 *mod = (MorphR3*)pMod; if(mod->CheckMaterialDependency() ) { EndDialog(hWnd,1);return TRUE; } // Make sure the node does not depend on us mod->BeginDependencyTest(); mp->NotifyDependents(FOREVER,0,REFMSG_TEST_DEPENDENCY); if (mod->EndDependencyTest()) { // display cyclic warning // if (GetCOREInterface()->GetQuietMode()) { TSTR cyclic; cyclic = GetString(IDS_CANNOT_BIND); GetCOREInterface()->Log()->LogEntry(SYSLOG_WARN,NO_DIALOG,GetString(IDS_CLASS_NAME),cyclic); } else { TSTR cyclic; cyclic = GetString(IDS_CANNOT_BIND); MessageBox(hWnd,cyclic,GetString(IDS_CLASS_NAME),MB_OK); } EndDialog(hWnd,1); return TRUE; } if(mod) mod->morphmaterial = mp; mp->ReplaceReference(102, mod); mp->obName = mp->Wnode->GetName(); mp->morphp = mod; if (mp->matDlg ){ mp->matDlg->UpdateMorphInfo(UD_LINK); mp->matDlg->ReloadDialog(); } } } } case IDCANCEL: EndDialog(hWnd,1); break; } break; default: return FALSE; } return TRUE; }
void HavokExport::makeHavokRigidBody(NiNodeRef parent, INode *ragdollParent, float scale) { this->scale = scale; Object *Obj = ragdollParent->GetObjectRef(); Modifier* rbMod = nullptr; Modifier* shapeMod = nullptr; Modifier* constraintMod = nullptr; SimpleObject* havokTaperCapsule = nullptr; //get modifiers while (Obj->SuperClassID() == GEN_DERIVOB_CLASS_ID) { IDerivedObject *DerObj = static_cast<IDerivedObject *> (Obj); const int nMods = DerObj->NumModifiers(); //it is really the last modifier on the stack, and not the total number of modifiers for (int i = 0; i < nMods; i++) { Modifier *Mod = DerObj->GetModifier(i); if (Mod->ClassID() == HK_RIGIDBODY_MODIFIER_CLASS_ID) { rbMod = Mod; } if (Mod->ClassID() == HK_SHAPE_MODIFIER_CLASS_ID) { shapeMod = Mod; } if (Mod->ClassID() == HK_CONSTRAINT_RAGDOLL_CLASS_ID || Mod->ClassID() == HK_CONSTRAINT_HINGE_CLASS_ID) { constraintMod = Mod; } } if (Obj->SuperClassID() == GEOMOBJECT_CLASS_ID) { havokTaperCapsule = (SimpleObject*)Obj; } Obj = DerObj->GetObjRef(); } if (!rbMod) { throw exception(FormatText("No havok rigid body modifier found on %s", ragdollParent->GetName())); } if (!shapeMod) { throw exception(FormatText("No havok shape modifier found on %s", ragdollParent->GetName())); } // Object* taper = ragdollParent->GetObjectRef(); IParamBlock2* taperParameters = Obj->GetParamBlockByID(PB_TAPEREDCAPSULE_OBJ_PBLOCK); float radius; enum { // GENERAL PROPERTIES ROLLOUT PA_TAPEREDCAPSULE_OBJ_RADIUS = 0, PA_TAPEREDCAPSULE_OBJ_TAPER, PA_TAPEREDCAPSULE_OBJ_HEIGHT, PA_TAPEREDCAPSULE_OBJ_VERSION_INTERNAL, }; taperParameters->GetValue(PA_TAPEREDCAPSULE_OBJ_RADIUS, 0, radius, FOREVER); int shapeType; if (IParamBlock2* shapeParameters = shapeMod->GetParamBlockByID(PB_SHAPE_MOD_PBLOCK)) { shapeParameters->GetValue(PA_SHAPE_MOD_SHAPE_TYPE,0,shapeType,FOREVER); } //Havok Shape bhkShapeRef shape; if (shapeType == 2) { // Capsule bhkCapsuleShapeRef capsule = new bhkCapsuleShape(); capsule->SetRadius(radius/scale); capsule->SetRadius1(radius/scale); capsule->SetRadius2(radius/scale); float length; taperParameters->GetValue(PA_TAPEREDCAPSULE_OBJ_HEIGHT, 0, length, FOREVER); //get the normal Matrix3 axis(true); ragdollParent->GetObjOffsetRot().MakeMatrix(axis); Point3 normalAx = axis.GetRow(2); //capsule center Point3 center = ragdollParent->GetObjOffsetPos(); //min and max points Point3 pt1 = center - normalAx*(length/2); Point3 pt2 = center + normalAx*(length/2); capsule->SetFirstPoint(TOVECTOR3(pt1)/scale); capsule->SetSecondPoint(TOVECTOR3(pt2)/scale); capsule->SetMaterial(HAV_MAT_SKIN); shape = StaticCast<bhkShape>(capsule); } else { // Sphere //CalcBoundingSphere(node, tm.GetTrans(), radius, 0); bhkSphereShapeRef sphere = new bhkSphereShape(); sphere->SetRadius(radius/scale); sphere->SetMaterial(HAV_MAT_SKIN); shape = StaticCast<bhkShape>(sphere); } bhkRigidBodyRef body; if (shape) { bhkBlendCollisionObjectRef blendObj = new bhkBlendCollisionObject(); body = new bhkRigidBody(); Matrix3 tm = ragdollParent->GetObjTMAfterWSM(0); //Calculate Object Offset Matrix Matrix3 otm(1); Point3 pos = ragdollParent->GetObjOffsetPos(); otm.PreTranslate(pos); Quat quat = ragdollParent->GetObjOffsetRot(); PreRotateMatrix(otm, quat); Matrix3 otmInvert = otm; otmInvert.Invert(); //correct object tm Matrix3 tmbhk = otmInvert * tm; //set geometric parameters body->SetRotation(TOQUATXYZW(Quat(tmbhk).Invert())); body->SetTranslation(TOVECTOR4(tmbhk.GetTrans() / scale)); body->SetCenter(TOVECTOR4(ragdollParent->GetObjOffsetPos())/scale); //set physics if (IParamBlock2* rbParameters = rbMod->GetParamBlockByID(PB_RB_MOD_PBLOCK)) { //These are fundamental parameters int lyr = NP_DEFAULT_HVK_LAYER; int mtl = NP_DEFAULT_HVK_MATERIAL; int msys = NP_DEFAULT_HVK_MOTION_SYSTEM; int qtype = NP_DEFAULT_HVK_QUALITY_TYPE; float mass = NP_DEFAULT_HVK_MASS; float lindamp = NP_DEFAULT_HVK_LINEAR_DAMPING; float angdamp = NP_DEFAULT_HVK_ANGULAR_DAMPING; float frict = NP_DEFAULT_HVK_FRICTION; float maxlinvel = NP_DEFAULT_HVK_MAX_LINEAR_VELOCITY; float maxangvel = NP_DEFAULT_HVK_MAX_ANGULAR_VELOCITY; float resti = NP_DEFAULT_HVK_RESTITUTION; float pendepth = NP_DEFAULT_HVK_PENETRATION_DEPTH; Point3 InertiaTensor; rbParameters->GetValue(PA_RB_MOD_MASS, 0, mass, FOREVER); rbParameters->GetValue(PA_RB_MOD_RESTITUTION, 0, resti, FOREVER); rbParameters->GetValue(PA_RB_MOD_FRICTION, 0, frict, FOREVER); rbParameters->GetValue(PA_RB_MOD_INERTIA_TENSOR, 0, InertiaTensor, FOREVER); rbParameters->GetValue(PA_RB_MOD_LINEAR_DAMPING, 0, lindamp, FOREVER); rbParameters->GetValue(PA_RB_MOD_CHANGE_ANGULAR_DAMPING, 0, angdamp, FOREVER); rbParameters->GetValue(PA_RB_MOD_MAX_LINEAR_VELOCITY, 0, maxlinvel, FOREVER); rbParameters->GetValue(PA_RB_MOD_MAX_ANGULAR_VELOCITY, 0, maxangvel, FOREVER); rbParameters->GetValue(PA_RB_MOD_ALLOWED_PENETRATION_DEPTH, 0, pendepth, FOREVER); rbParameters->GetValue(PA_RB_MOD_QUALITY_TYPE, 0, qtype, FOREVER); body->SetMass(mass); body->SetRestitution(resti); body->SetFriction(frict); body->SetLinearDamping(lindamp); body->SetMaxLinearVelocity(maxlinvel); body->SetMaxAngularVelocity(maxangvel); body->SetPenetrationDepth(pendepth); InertiaMatrix im; im[0][0] = InertiaTensor[0]; im[1][1] = InertiaTensor[1]; im[2][2] = InertiaTensor[2]; body->SetInertia(im); /*switch (qtype) { case QT_FIXED: body->SetQualityType(MO_QUAL_FIXED); break; case QT_KEYFRAMED: body->SetQualityType(MO_QUAL_KEYFRAMED); break; case QT_DEBRIS: body->SetQualityType(MO_QUAL_DEBRIS); break; case QT_MOVING: body->SetQualityType(MO_QUAL_MOVING); break; case QT_CRITICAL: body->SetQualityType(MO_QUAL_CRITICAL); break; case QT_BULLET: body->SetQualityType(MO_QUAL_BULLET); break; case QT_KEYFRAMED_REPORTING: body->SetQualityType(MO_QUAL_KEYFRAMED_REPORT); break; }*/ body->SetSkyrimLayer(SkyrimLayer::SKYL_BIPED); body->SetSkyrimLayerCopy(SkyrimLayer::SKYL_BIPED); body->SetMotionSystem(MotionSystem::MO_SYS_BOX); body->SetDeactivatorType(DeactivatorType::DEACTIVATOR_NEVER); body->SetSolverDeactivation(SolverDeactivation::SOLVER_DEACTIVATION_LOW); body->SetQualityType(MO_QUAL_FIXED); } if (constraintMod && ragdollParent->GetParentNode() && parent->GetParent()) { if (constraintMod->ClassID() == HK_CONSTRAINT_RAGDOLL_CLASS_ID) { bhkRagdollConstraintRef ragdollConstraint = new bhkRagdollConstraint(); //entities ragdollConstraint->AddEntity(body); NiNodeRef parentRef = parent->GetParent(); bhkRigidBodyRef nifParentRigidBody; while (parentRef) { if (parentRef->GetCollisionObject()) { nifParentRigidBody = StaticCast<bhkRigidBody>(StaticCast<bhkBlendCollisionObject>(parentRef->GetCollisionObject())->GetBody()); break; } parentRef = parentRef->GetParent(); } if (!nifParentRigidBody) throw exception(FormatText("Unable to find NIF constraint parent for ragdoll node %s", ragdollParent->GetName())); ragdollConstraint->AddEntity(nifParentRigidBody); RagdollDescriptor desc; //parameters if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_CONSTRAINT_MOD_COMMON_SPACES_PARAMS)) { Point3 pivotA; Matrix3 parentRotation; Point3 pivotB; Matrix3 childRotation; constraintParameters->GetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_TRANSLATION, 0, pivotB, FOREVER); constraintParameters->GetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_ROTATION, 0, childRotation, FOREVER); constraintParameters->GetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_TRANSLATION, 0, pivotA, FOREVER); constraintParameters->GetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_ROTATION, 0, parentRotation, FOREVER); desc.pivotA = TOVECTOR4(pivotA); desc.pivotB = TOVECTOR4(pivotB); desc.planeA = TOVECTOR4(parentRotation.GetRow(0)); desc.motorA = TOVECTOR4(parentRotation.GetRow(1)); desc.twistA = TOVECTOR4(parentRotation.GetRow(2)); desc.planeB = TOVECTOR4(childRotation.GetRow(0)); desc.motorB = TOVECTOR4(childRotation.GetRow(1)); desc.twistB = TOVECTOR4(childRotation.GetRow(2)); } if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_RAGDOLL_MOD_PBLOCK)) { float coneMaxAngle; float planeMinAngle; float planeMaxAngle; float coneMinAngle; float twistMinAngle; float maxFriction; constraintParameters->GetValue(PA_RAGDOLL_MOD_CONE_ANGLE, 0, coneMaxAngle, FOREVER); constraintParameters->GetValue(PA_RAGDOLL_MOD_PLANE_MIN, 0, planeMinAngle, FOREVER); constraintParameters->GetValue(PA_RAGDOLL_MOD_PLANE_MAX, 0, planeMaxAngle, FOREVER); constraintParameters->GetValue(PA_RAGDOLL_MOD_TWIST_MIN, 0, coneMinAngle, FOREVER); constraintParameters->GetValue(PA_RAGDOLL_MOD_TWIST_MAX, 0, twistMinAngle, FOREVER); constraintParameters->GetValue(PA_RAGDOLL_MOD_MAX_FRICTION_TORQUE, 0, maxFriction, FOREVER); desc.coneMaxAngle = TORAD(coneMaxAngle); desc.planeMinAngle = TORAD(planeMinAngle); desc.planeMaxAngle = TORAD(planeMaxAngle); desc.coneMaxAngle = TORAD(coneMinAngle); desc.twistMinAngle = TORAD(twistMinAngle); desc.maxFriction = maxFriction; } ragdollConstraint->SetRagdoll(desc); body->AddConstraint(ragdollConstraint); } else if (constraintMod->ClassID() == HK_CONSTRAINT_HINGE_CLASS_ID) { bhkLimitedHingeConstraintRef limitedHingeConstraint = new bhkLimitedHingeConstraint(); //entities limitedHingeConstraint->AddEntity(body); NiNodeRef parentRef = parent->GetParent(); bhkRigidBodyRef nifParentRigidBody; while (parentRef) { if (parentRef->GetCollisionObject()) { nifParentRigidBody = StaticCast<bhkRigidBody>(StaticCast<bhkBlendCollisionObject>(parentRef->GetCollisionObject())->GetBody()); break; } parentRef = parentRef->GetParent(); } if (!nifParentRigidBody) throw exception(FormatText("Unable to find NIF constraint parent for limited hinge node %s", ragdollParent->GetName())); limitedHingeConstraint->AddEntity(nifParentRigidBody); LimitedHingeDescriptor lh; if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_CONSTRAINT_MOD_COMMON_SPACES_PARAMS)) { Matrix3 parentRotation; Matrix3 childRotation; constraintParameters->GetValue(PA_CONSTRAINT_MOD_CHILD_SPACE_ROTATION, 0, childRotation, FOREVER); constraintParameters->GetValue(PA_CONSTRAINT_MOD_PARENT_SPACE_ROTATION, 0, parentRotation, FOREVER); lh.perp2AxleInA1 = TOVECTOR4(parentRotation.GetRow(0)); lh.perp2AxleInA2 = TOVECTOR4(parentRotation.GetRow(1)); lh.axleA = TOVECTOR4(parentRotation.GetRow(2)); lh.perp2AxleInB1 = TOVECTOR4(childRotation.GetRow(0)); lh.perp2AxleInB2 = TOVECTOR4(childRotation.GetRow(1)); lh.axleB = TOVECTOR4(childRotation.GetRow(2)); } if (IParamBlock2* constraintParameters = constraintMod->GetParamBlockByID(PB_HINGE_MOD_PBLOCK)) { float minAngle; float maxAngle; float maxFriction; constraintParameters->GetValue(PA_HINGE_MOD_LIMIT_MIN, 0, minAngle, FOREVER); constraintParameters->GetValue(PA_HINGE_MOD_LIMIT_MAX, 0, maxAngle, FOREVER); constraintParameters->GetValue(PA_HINGE_MOD_MAX_FRICTION_TORQUE, 0, maxFriction, FOREVER); // constraintParameters->SetValue(PA_HINGE_MOD_MOTOR_TYPE, 0, lh.motor., 0); lh.minAngle = TORAD(minAngle); lh.maxAngle = TORAD(maxAngle); lh.maxAngle = maxFriction; } limitedHingeConstraint->SetLimitedHinge(lh); body->AddConstraint(limitedHingeConstraint); } } //InitializeRigidBody(body, node); body->SetShape(shape); blendObj->SetBody(StaticCast<NiObject>(body)); parent->SetCollisionObject(StaticCast<NiCollisionObject>(blendObj)); } ////rigid body parameters // // get data from node //int lyr = NP_DEFAULT_HVK_LAYER; //int mtl = NP_DEFAULT_HVK_MATERIAL; //int msys = NP_DEFAULT_HVK_MOTION_SYSTEM; //int qtype = NP_DEFAULT_HVK_QUALITY_TYPE; //float mass = NP_DEFAULT_HVK_MASS; //float lindamp = NP_DEFAULT_HVK_LINEAR_DAMPING; //float angdamp = NP_DEFAULT_HVK_ANGULAR_DAMPING; //float frict = NP_DEFAULT_HVK_FRICTION; //float maxlinvel = NP_DEFAULT_HVK_MAX_LINEAR_VELOCITY; //float maxangvel = NP_DEFAULT_HVK_MAX_ANGULAR_VELOCITY; //float resti = NP_DEFAULT_HVK_RESTITUTION; //float pendepth = NP_DEFAULT_HVK_PENETRATION_DEPTH; //BOOL transenable = TRUE; //if (IParamBlock2* rbParameters = rbMod->GetParamBlockByID(PB_SHAPE_MOD_PBLOCK)) //{ // //These are fundamental parameters // rbParameters->GetValue(PA_RB_MOD_MASS, 0, mass, FOREVER); // rbParameters->GetValue(PA_RB_MOD_RESTITUTION, 0, resti, FOREVER); // rbParameters->GetValue(PA_RB_MOD_FRICTION, 0, frict, FOREVER); // rbParameters->GetValue(PA_RB_MOD_LINEAR_DAMPING, 0, lindamp, FOREVER); // rbParameters->GetValue(PA_RB_MOD_CHANGE_ANGULAR_DAMPING, 0, angdamp, FOREVER); // rbParameters->GetValue(PA_RB_MOD_MAX_LINEAR_VELOCITY, 0, maxlinvel, FOREVER); // rbParameters->GetValue(PA_RB_MOD_MAX_ANGULAR_VELOCITY, 0, maxangvel, FOREVER); // rbParameters->GetValue(PA_RB_MOD_ALLOWED_PENETRATION_DEPTH, 0, pendepth, FOREVER); // rbParameters->GetValue(PA_RB_MOD_QUALITY_TYPE, 0, qtype, FOREVER); // switch (qtype) { // case MO_QUAL_INVALID: // break; // case QT_FIXED: // rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, MO_QUAL_FIXED, 0); // break; // case MO_QUAL_KEYFRAMED: // rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_KEYFRAMED, 0); // break; // case MO_QUAL_DEBRIS: // rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_DEBRIS, 0); // break; // case MO_QUAL_MOVING: // rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_MOVING, 0); // break; // case MO_QUAL_CRITICAL: // rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_CRITICAL, 0); // break; // case MO_QUAL_BULLET: // rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_BULLET, 0); // break; // case MO_QUAL_USER: // break; // case MO_QUAL_CHARACTER: // break; // case MO_QUAL_KEYFRAMED_REPORT: // rbParameters->SetValue(PA_RB_MOD_QUALITY_TYPE, 0, QT_KEYFRAMED_REPORTING, 0); // break; // } // // setup body // bhkRigidBodyRef body = transenable ? new bhkRigidBodyT() : new bhkRigidBody(); // OblivionLayer obv_layer; SkyrimLayer sky_layer; // GetHavokLayersFromIndex(lyr, (int*)&obv_layer, (int*)&sky_layer); // body->SetLayer(obv_layer); // body->SetLayerCopy(obv_layer); // body->SetSkyrimLayer(sky_layer); // body->SetMotionSystem(MotionSystem(msys)); // body->SetQualityType(MotionQuality(qtype)); // body->SetMass(mass); // body->SetLinearDamping(lindamp); // body->SetAngularDamping(angdamp); // body->SetFriction(frict); // body->SetRestitution(resti); // body->SetMaxLinearVelocity(maxlinvel); // body->SetMaxAngularVelocity(maxangvel); // body->SetPenetrationDepth(pendepth); // body->SetCenter(center); // QuaternionXYZW q; q.x = q.y = q.z = 0; q.w = 1.0f; // body->SetRotation(q); //} }