HOW TO: Export 3ds max particle BY: Nithril 05/06/2001 Acronymes : WSM : World Space Modifier WSMO: World Space Modifier Object (la representation graphique d'un WSM) WSO : World Space Object PB : Parameter Block Introduction. Nous allons nous interresser plus particulierement à l'export de l'Object superspray et d'un space warp pouvant lui etre attaché : deflector. Il existe deux types de WSM pouvant etre attaché a un systeme de particule: -les CollisionObject -les ForceField I) Superspray a) Info path = .\maxsdk\Samples\Objects\Particles\blizzard.cpp SClass_ID = GEOMOBJECT_CLASS_ID Class_ID = SUPRSPRAY_CLASS_ID (Class_ID(0x74f811e3, 0x21fb7b57)) b) Exportation Superspray contient un grd nombre de parametre mais nous allons n'exporté que les plus vital, (pour les autres cf. $path) PB_OFFAXIS 0 TRUE FLOAT PB_AXISSPREAD 1 TRUE FLOAT PB_OFFPLANE 2 TRUE FLOAT PB_PLANESPREAD 3 TRUE FLOAT PB_SPEED 4 TRUE FLOAT PB_SPEEDVAR 5 TRUE FLOAT PB_BIRTHMETHOD 6 TRUE PB_PBIRTHRATE 7 TRUE PB_PTOTALNUMBER 8 TRUE PB_EMITSTART 9 TRUE PB_EMITSTOP 10 TRUE PB_DISPUNTIL 11 TRUE PB_LIFE 12 TRUE PB_LIFEVAR 13 TRUE PB_SUBFRAMEMOVE 14 TRUE PB_SUBFRAMETIME 15 TRUE PB_SIZE 16 TRUE PB_SIZEVAR 17 TRUE PB_GROWTIME 18 TRUE PB_FADETIME 19 TRUE PB_RNDSEED 20 TRUE PB_EMITRWID 21 TRUE PB_EMITRHID 22 TRUE PB_PARTICLECLASS 23 TRUE PB_PARTICLETYPE 24 TRUE En premier lieu il s'agit de recuperer l'object ayant un Class_ID = SUPRSPRAY_CLASS_ID. Un simple INode::GetObjectRef doit suffire, car les systemes de particules sont des WSO (ils ne sont reference que par une seule node), d'ailleurs les clonages de type instance ou ref sont impossibles. > Object* lpObj = lpINode->GetObjectRef(); Ensuite on recupere le IParamArray qui contient tous les parametres de la class > IParamArray* lpParamArray = lpObj->GetParameterBlock(); On peut maintenant exporté les infos qui nous interressent: > float fVal; > int iVal; > Interval intervalValid; > > //On recupere l'off axis au temps 0 dans fVal du parametre PB_OFFAXIS > //intervalValid, passe par reference, retournera l'interval de validité de fVal > lpParamArray->GetValue(PB_OFFAXIS , 0 , fVal , intervalValid); > //Stockage > > //On recupere l'axis spread > lpParamArray->GetValue(PB_AXISSPREAD , 0 , fVal , intervalValid); > //Stockage > //etc, etc Le static c bien, mais c encore mieux d'exporté des parametres animés. Recuperons le ParameterBlock: > IParamBlock* pblock = lpObj->GetParamBlock()->GetParamBlock(); Si cette ligne de code vous semble bizarre c normal. IParamblock herite de ReferenceTarget et de IParamArray, et donc à cause de l'heritage multiple, il faut appeler la fonction IParamArray::GetParamBlock(). Cette fonction renvoie null, si l'instance renvoyé par lpObj->GetParamBlock() n'est pas du type ou du sous type de IParamBlock. Predicat: on dispose d'une fonction ExportAnimation(Controler*) qui effectue des operations sur le controler passé en parametre sous reserve qu'il soit definie et animé. > //On traite l'off axis > ExportAnimation(pblock->GetController(PB_OFFAXIS)) > > //On traite l'axis spread > ExportAnimation(pblock->GetController(PB_OFFAXIS)) > > etc, etc Reste plus qu'à charger tout cela ds votre moteur 3d preferé. II) Deflector a) Info path = .\maxsdk\Samples\Modifiers\deflect.cpp SClass_ID = WSM_OBJECT_CLASS_ID Object Class_ID = Class_ID(DEFLECTOBJECT_CLASS_ID,0) Modifier Class_ID = Class_ID(DEFLECTMOD_CLASS_ID,0) b) Exportation Le deflector space warp ne contient que peu de parametre. C le plus basique des deflectors : une surface rectangulaire. Les parametres: // block IDs deflect_params 0 // geo_param param IDs deflect_bounce 0 TRUE FLOAT deflect_width 1 TRUE FLOAT deflect_height 2 TRUE FLOAT deflect_variation 3 TRUE % deflect_chaos 4 TRUE % deflect_friction 5 TRUE % deflect_inherit_vel 6 TRUE FLOAT deflect_quality 7 TRUE INT deflect_collider 8 FALSE PTR Les deflector ne sont pas des WSO, mais ce sont des WSMO. Ils peuvent donc etre cloné par copie, instance ou reference. Il faut donc parcourir toute la pile de mod des Objects, malgre que cela ne sert à rien d'attacher un modifier à un deflector. > IDerivedObject* lpIObj = lpINode->GetWSMDerivedObject(); > if (!lpIObj) return; > > //On recherche un WSM_OBJECT_CLASS_ID de Class_ID(DEFLECTOBJECT_CLASS_ID,0) > //en parcourant la pile tant que Class_ID(WSM_DERIVOB_CLASS_ID,0) > lpObj = GetRootObject(lpINode); > > //On recupere le PB > IParamBlock2* pblock2 = lpObj->GetParamBlockByID(deflect_params); > > //recupere le bounce > pblock2->GetValue(deflect_bounce , 0 , fVal , FOREVER); > //traitement > > //etc,etc > > //On exporte les anims > ExportAnimation(pblock2->GetControler((ParamID)deflect_bounce)); > > //etc,etc III) Autres Idem pour les autres types de CollisionObject, ForceField, une fois recuperé les param ids, exporte un object est un jeu d'enfant. IV) Liens Systeme Particule/WSM Maintenant il s'agit de recuperer les WSM attaché à notre SuperSpray, pour cela nous allons attaquer la liste de references makers. IDerivedObject* lpIObj = lpINode->GetWSMDerivedObject(); if (!lpIObj) return; for (int i = 0 ; i < lpIObj->NumModifiers() ; i++) { //recupere le ieme modifier Modifier* lpModif = lpIObj->GetModifier(i); for (int j = 0 ; j < lpModif->NumRefs() ; j++) { //recupere la ref RefTargetHandle lpRef = lpModif->GetReference(j); //test si cette ref est d'une part definie et ensuite si elle est une instance de la class INode if (lpRef && lpRef->ClassID() == Class_ID(BASENODE_CLASS_ID , 0)) { INode* lpINode = (INode*)lpRef; if (IsCollisionObjectObject(lpINode) || IsForceFieldObject(lpINode)) { //j'exporte son nom par exemple (nom non unique) //Export(lpINode->GetName()); } } } } V) Recapitulation SUPERSPRAY path = .\maxsdk\Samples\Objects\Particles\blizzard.cpp SClass_ID = GEOMOBJECT_CLASS_ID Class_ID = SUPRSPRAY_CLASS_ID (Class_ID(0x74f811e3 , 0x21fb7b57)) GRAVITY path = .\maxsdk\Samples\Modifiers\gravity.cpp Object SClass_ID = WSM_OBJECT_CLASS_ID Object Class_ID = Class_ID(GRAVITYOBJECT_CLASS_ID , 0) Modifier Class_ID = Class_ID(GRAVITYMOD_CLASS_ID , 0) WIND path = .\maxsdk\Samples\Modifiers\wind.cpp SClass_ID = WSM_OBJECT_CLASS_ID Object Class_ID = Class_ID(WINDOBJECT_CLASS_ID,0) Modifier Class_ID = Class_ID(WINDMOD_CLASS_ID,0) DEFLECTOR path = .\maxsdk\Samples\Modifiers\deflect.cpp SClass_ID = WSM_OBJECT_CLASS_ID Object Class_ID = Class_ID(DEFLECTOBJECT_CLASS_ID,0) Modifier Class_ID = Class_ID(DEFLECTMOD_CLASS_ID,0) SPHERICAL DEFLECTOR path = .\maxsdk\Samples\Objects\Particles\Sphered.cpp SClass_ID = WSM_OBJECT_CLASS_ID Object Class_ID = SPHEREDEF_CLASS_ID (Class_ID(0x6cbd289d, 0x3fef6656)) Modifier Class_ID = SPHEREDEFMOD_CLASS_ID (Class_ID(0x5cdf4181, 0x4c5b42f9)) Je vous laisse trouver les plus interressant :)