00001 /****************************************************************************** 00002 *< 00003 FILE: PhyExp.h 00004 00005 DESCRIPTION: Export Interface Functionality for Physique 00006 00007 CREATED BY: John Chadwick with a lot of help from Jurie Horneman 00008 00009 HISTORY: created July 10, 1997, modified for Version 2.0 March 5, 1998 00010 00011 *> Copyright (c) Unreal Pictures, Inc. 1997, 1998 All Rights Reserved. 00012 *******************************************************************************/ 00013 #pragma once 00014 00015 #include "..\maxheap.h" 00016 #include "..\modstack.h" 00017 00018 #ifdef BLD_PHYSIQUE 00019 #define PHYExport __declspec( dllexport ) 00020 #else 00021 #define PHYExport __declspec( dllimport ) 00022 #endif 00023 00024 // this is the interface ID for a Physique Modifier Interface 00025 #define I_PHYINTERFACE 0x00100100 00026 #define I_PHYEXPORT 0x00100100 00027 #define I_PHYIMPORT 0x00100101 00028 00029 //return values for GetInitNodeTM 00030 #define MATRIX_RETURNED 0 00031 #define NODE_NOT_FOUND 1 00032 #define NO_MATRIX_SAVED 2 00033 #define INVALID_MOD_POINTER 3 00034 00035 // version control 00036 #define CURRENT_VERSION 313 00037 00038 00039 // these are the Class ID defines for Physique Modifier: 00040 // Physique Class_ID = ClassID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B); 00041 #define PHYSIQUE_CLASS_ID_A 0x00100 00042 #define PHYSIQUE_CLASS_ID_B 0x00000 00043 00044 00045 #define RIGID_TYPE 1 00046 #define DEFORMABLE_TYPE 2 00047 #define BLENDED_TYPE 4 00048 #define FLOATING_TYPE 8 00049 00050 #define RIGID_NON_BLENDED_TYPE (RIGID_TYPE) 00051 #define DEFORMABLE_NON_BLENDED_TYPE (DEFORMABLE_TYPE) 00052 #define RIGID_BLENDED_TYPE (RIGID_TYPE | BLENDED_TYPE) 00053 #define DEFORMABLE_BLENDED_TYPE (DEFORMABLE_TYPE | BLENDED_TYPE) 00054 00055 // NOTE: for Character Studio 2.1 Deformable Offset Vertices and Vertex Assignment 00056 // Import has been added. These classes and descriptions follow the standard Rigid 00057 // Export functionality at the end of this file. 00058 00059 00060 // Using the Physique Export Interface: 00061 // 00062 // 1. Find the Physique Modifier you which to export rigid vertex assignments from. 00063 // (there is a comment at the bottom of this file giving an example of this) 00064 // 00065 // 2. Given Physique Modifier Modifier *phyMod get the Physique Export Interface: 00066 // IPhysiqueExport *phyExport = (IPhysqiueExport *)phyMod->GetInterface(I_PHYINTERFACE); 00067 // 00068 // 3. For a given Object's INode get this ModContext Interface from the Physique Export Interface: 00069 // IPhyContextExport *contextExport = (IPhyContextExport *)phyExport->GetContextInterface(INode* nodePtr); 00070 // 00071 // 4. For each vertex of the Object get the Vertex Interface from the ModContext Export Interface: 00072 // IPhyVertexExport *vtxExport = (IPhyVertexExport *)contextExport->GetVertexInterface(int i); 00073 // NOTE: only Rigid Vertices are currently supported: (see ConvertToRigid(TRUE) to make all vertices rigid) 00074 // IPhyRigidVertex *rigidExport = (IPhyRigidVertex *)contextExport->GetVertexInterface(int i); 00075 // 00076 // 5. Get the INode for each Rigid Vertex Interface: 00077 // INode *nodePtr = rigidExport->GetNode(); 00078 // 00079 // 6. Get the Point3 Offset Vector in INode coordinates for each Rigid Vertex Interface: 00080 // Point3 offsetVector = rigidExport->GetOffsetVector(); 00081 00082 00083 00084 00085 00086 // IPhyVertexExport: this is the base class for Vertex Export Interface 00087 // NOTE: currently only RIGID_TYPE vertices are supported (IPhyRigidVertex) 00088 // When a vertex is not assigned Rigid in Physique, the VertexInterface will be NULL 00089 // Unless you call IPhyContextExport->ConvertToRigid(TRUE) (see IPhyContextExport below) 00090 // With ConvertToRigid(TRUE) you will always get a IPhyRigidVertex 00091 // from IPhyContextExport->GetVertexInterface(i) 00092 00093 class IPhyFloatingVertex; 00094 00095 class IPhyVertexExport: public MaxHeapOperators 00096 { 00097 public: 00098 00099 PHYExport virtual ~IPhyVertexExport() {} 00100 00101 // NOTE: currently only type RIGID_TYPE | RIGID_BLENDED_TYPE are supported 00102 PHYExport virtual int GetVertexType() = 0; 00103 00104 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00105 00106 }; 00107 00108 00109 00110 class IPhyRigidVertex : public IPhyVertexExport 00111 { 00112 public: 00113 00114 PHYExport virtual ~IPhyRigidVertex() {} 00115 00116 // GetNode() will return the INode pointer of the link of the given VertexInterface 00117 PHYExport virtual INode *GetNode() = 0; 00118 00119 // GetOffsetVector() will return the coordinates of the vertex 00120 // in the local coordinates of associated INode pointer from GetNode 00121 // this is NOT THE SAME as the .vph file coordinates. (It is simpler) 00122 // the world coordinates of the vertex have been transformed by the Inverse of the INode pointer. 00123 PHYExport virtual Point3 GetOffsetVector() = 0; 00124 00125 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00126 00127 }; 00128 00129 class IPhyBlendedRigidVertex : public IPhyVertexExport 00130 { 00131 public: 00132 00133 PHYExport virtual ~IPhyBlendedRigidVertex() {} 00134 00135 // GetNumberNodes() returns the number of nodes assigned to the given VertexInterface 00136 PHYExport virtual int GetNumberNodes() = 0; 00137 00138 // GetNode(i) will return the i'th INode pointer of the link of the given VertexInterface 00139 PHYExport virtual INode *GetNode(int i) = 0; 00140 00141 // GetOffsetVector(i) will return the coordinates of the vertex 00142 // in the local coordinates of associated i'th INode pointer from GetNode(i) 00143 // this is NOT THE SAME as the .vph file coordinates. (It is simpler) 00144 // the world coordinates of the vertex have been transformed by the Inverse of the INode pointer. 00145 PHYExport virtual Point3 GetOffsetVector(int i) = 0; 00146 00147 // GetWeight(i) will return the weight of the vertex associated with the i'th Node 00148 // pointer from GetNode(i) 00149 PHYExport virtual float GetWeight(int i) = 0; 00150 00151 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00152 00153 }; 00154 00155 00156 00157 00158 00159 // IPhyContextExport: This class can be returned by : 00160 // passing the INode pointer of an Object with the given Physique Modifier's IPhysiqueExport::GetContextInterface(node) 00161 // If this Node does contain the Physique Modifier associated with this interface an interface to this object's 00162 // interface is returned (several object's may share the same physique modifier), else returns NULL. 00163 00164 class IPhyContextExport: public MaxHeapOperators 00165 { 00166 public: 00167 00168 PHYExport virtual ~IPhyContextExport() {} 00169 00170 // this returns the number of vertices for the given modContext's Object 00171 PHYExport virtual int GetNumberVertices() = 0; 00172 00173 // If ConvertToRigid is set to TRUE, all GetVertexInterface calls will be IPhyRigidVertex OR IPhyBlendedRigidVertex. 00174 // Vertices which are not Rigid in Physique will be converted to Rigid for the VertexInterface. 00175 // When ConvertToRigid is set to FALSE, GetVertexInterface for non-Rigid vertices currently returns NULL. 00176 // By default, if you do not call ConvertToRigid, it is set to FALSE. 00177 PHYExport virtual void ConvertToRigid(BOOL flag = TRUE) = 0; 00178 00179 // If AllowBlending is set to FALSE then GetVertexInterface will return a non-blended subclass. 00180 // Currently the only valid VertexInterface subclasses are IPhyRigidVertex, and IPhyBlendedRigidVertex. 00181 // When AllowBlending is FALSE, either IPhyRigidVertex or NULL will be returned. 00182 // If ConvertToRigid is TRUE and AllowBlending is FALSE, all vertices will return 00183 // IPhyRigidVertex. By default AllowBlending is set to TRUE. 00184 PHYExport virtual void AllowBlending(BOOL flag = TRUE) = 0; 00185 00186 // GetVertexInterface return's a VertexInterface (IPhyVertexExport *) for the i'th vertex. 00187 // If ConvertToRigid has been set to TRUE, then all VertexInterfaces will return IPhyRigidVertex OR IPhyBlendedRigidVertex. 00188 // When ConvertToRigid has been set to FALSE, non-Rigid vertices will return NULL (CURRENTLY). 00189 PHYExport virtual IPhyVertexExport *GetVertexInterface(int i) = 0; 00190 00191 // You must call ReleaseVertexInterface to delete the VertexInterface when finished with it. 00192 PHYExport virtual void ReleaseVertexInterface(IPhyVertexExport *vertexExport) = 0; 00193 00194 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00195 00196 PHYExport virtual IPhyFloatingVertex *GetFloatingVertexInterface(int i) = 0; 00197 }; 00198 00199 // IPhysiqueExport: This class can be returned by calling the method GetInterface() for a Physique Modifier 00200 // given Modifier *mod points to a Physique Modifier, then: 00201 // IPhysiqueExport *phyInterface = (IPhysiqueExport *)( mod->GetInterface(I_PHYINTERFACE) ); 00202 // will return the interface for this Physique Modifier, else returns NULL. 00203 00204 class IPhysiqueExport: public MaxHeapOperators 00205 { 00206 00207 public: 00208 00209 PHYExport virtual ~IPhysiqueExport() {} 00210 00211 //GetContextInterface will return a pointer to IPhyContextExport Interface for a given INode. 00212 // Ff the given INode does not contain the Physique Modifier of this IPhysique Export then NULL is returned. 00213 PHYExport virtual IPhyContextExport *GetContextInterface(INode* nodePtr) = 0; 00214 00215 // You must call ReleaseContextInterface to delete the COntextInterface when finished with it. 00216 PHYExport virtual void ReleaseContextInterface(IPhyContextExport *contextExport) = 0; 00217 00218 PHYExport virtual int GetInitNodeTM(INode *node, Matrix3 &initNodeTM) = 0; 00219 00220 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00221 00222 PHYExport virtual int Version(void) = 0; 00223 00224 PHYExport virtual void SetInitialPose(bool set) = 0; 00225 }; 00226 00227 // example code to find if a given node contains a Physique Modifier 00228 // DerivedObjectPtr requires you include "modstack.h" from the MAX SDK 00229 /* 00230 Modifier* FindPhysiqueModifier (INode* nodePtr) 00231 { 00232 Object* ObjectPtr = nodePtr->GetObjectRef(); 00233 00234 if (!ObjectPtr ) return NULL; 00235 00236 while (ObjectPtr->SuperClassID() == GEN_DERIVOB_CLASS_ID && ObjectPtr) 00237 { 00238 // Yes -> Cast. 00239 IDerivedObject* DerivedObjectPtr = (IDerivedObject *)(ObjectPtr); 00240 00241 // Iterate over all entries of the modifier stack. 00242 int ModStackIndex = 0; 00243 00244 while (ModStackIndex < DerivedObjectPtr->NumModifiers()) 00245 { 00246 // Get current modifier. 00247 Modifier* ModifierPtr = DerivedObjectPtr->GetModifier(ModStackIndex); 00248 00249 // Is this Physique ? 00250 if (ModifierPtr->ClassID() == Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B)) 00251 { 00252 // is this the correct Physique Modifier based on index? 00253 SkinMod *phyMod = (SkinMod *)ModifierPtr; 00254 00255 if (phyMod == mod) 00256 { 00257 ModContext *mc = DerivedObjectPtr->GetModContext(ModStackIndex); 00258 } 00259 } 00260 00261 ModStackIndex++; 00262 } 00263 00264 ObjectPtr = DerivedObjectPtr->GetObjRef(); 00265 } 00266 00267 // Not found. 00268 return NULL; 00269 } 00270 */ 00271 00272 00273 // Deformable Vertex Export via Offset Vectors 00274 // 00275 // Character Studio 2.1 allows users to export Deformable Vertices 00276 // as time frame offsets from a rigid node offset 00277 // The Rigid Offset Vector is identical to the Rigid Vertex Offset Vector. 00278 // This represents the vertex in local coordinates from the attached node. 00279 // Note that since the deformable offset is relative to a single node, 00280 // Blending between links is handled internal to Physique in determining 00281 // this offset, so that the export is a single offset for a given time 00282 // for a single Node. 00283 // Basically, you export a deformable offset from a single node, while 00284 // Physique uses blending between several deformable links to determine 00285 // this offset. 00286 // NOTE: while the Rigid Vertex and Rigid Blended Vertex Export require 00287 // a one time export for replicating the deformabion internal to the game engine, 00288 // the Deformable Offset Vertex Export requires the export of DeformVertexOffset(t) 00289 // at several (or every) frame. 00290 00291 class IPhyDeformableOffsetVertex : public IPhyVertexExport 00292 { 00293 public: 00294 00295 PHYExport virtual ~IPhyDeformableOffsetVertex() {} 00296 00297 // GetNode() will return the INode pointer of the link of the given VertexInterface 00298 PHYExport virtual INode *GetNode() = 0; 00299 00300 // GetOffsetVector() will return the coordinates of the undeformed vertex 00301 // in the local coordinates of associated INode pointer from GetNode(). 00302 // This is IDENTICAL to the Rigid Non Blended OffsetVector. 00303 // It represents the Vertex in the local coordinates of the node via GetNode(). 00304 PHYExport virtual Point3 GetOffsetVector() = 0; 00305 00306 // GetDeformOffsetVector(t) will return the coorinates of the deformed vertex 00307 // in the local coordinates of the associated INode pointer from GetNode(). 00308 // Game Developers wishing to store relative offsets can subtract the 00309 // Deformable Offsets for given frames from the Base Offset Vector. 00310 PHYExport virtual Point3 GetDeformOffsetVector(TimeValue t) = 0; 00311 00312 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00313 00314 }; 00315 00316 00317 00318 00319 00320 // Import Interface Functionality for Physique 00321 // 00322 // Character Studio 2.1 allows users to programatically set the Rigid 00323 // Vertex Assignments (with or without Blending) via Import Interface 00324 00325 00326 // IPhyVertexImport: this is the base class for Vertex Export Interface 00327 // NOTE: currently only RIGID_TYPE vertices are supported (IPhyRigidVertex) 00328 // When a vertex is not assigned Rigid in Physique, the VertexInterface will be NULL 00329 // Unless you call IPhyContextExport->ConvertToRigid(TRUE) (see IPhyContextExport below) 00330 // With ConvertToRigid(TRUE) you will always get a IPhyRigidVertex 00331 // from IPhyContextExport->GetVertexInterface(i) 00332 00333 class IPhyVertexImport: public MaxHeapOperators 00334 { 00335 public: 00336 00337 PHYExport virtual ~IPhyVertexImport() {} 00338 00339 // NOTE: currently only type RIGID_TYPE | RIGID_BLENDED_TYPE are supported 00340 PHYExport virtual int GetVertexType() = 0; 00341 00342 // You can lock (TRUE) or unlock (FALSE) vertex assignments 00343 // To avoid changes to manual vertex assignments locking prevents 00344 // these vertices from being reinitialized by Physique. 00345 PHYExport virtual void LockVertex(BOOL lock) = 0; 00346 00347 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00348 }; 00349 00350 00351 00352 class IPhyRigidVertexImport : public IPhyVertexImport 00353 { 00354 public: 00355 00356 PHYExport virtual ~IPhyRigidVertexImport() {} 00357 00358 // SetNode() will define the INode pointer of the link of the given Rigid Vertex Interface 00359 // If this INode is a valid Physique Link SetNode returns TRUE, and this vertex is 00360 // now assigned Rigid (NonBlended) to this INode. 00361 // If this INode is not a valid Physique Link, then SetNode returns FALSE, 00362 // and no change to the vertex assignment occurs. 00363 PHYExport virtual BOOL SetNode(INode *nodePtr) = 0; 00364 00365 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00366 00367 }; 00368 00369 class IPhyBlendedRigidVertexImport : public IPhyVertexImport 00370 { 00371 public: 00372 00373 PHYExport virtual ~IPhyBlendedRigidVertexImport() {} 00374 00375 // SetWeightedNode will assign the given vertex to the nodePtr with the weight specified. 00376 // When init = TRUE, this will remove all existing asignments and define this nodePtr 00377 // as the first and only nodePtr assigned to the given vertex. When init = FALSE this 00378 // nodePtr and weight are appeneded to the current assignments. 00379 // Always set init = TRUE for the first nodePtr and weight for a given vertex 00380 // and init = FALSE for all additional 2nd thru Nth nodeptr and weights. 00381 // SetWeightedNode returns the number of Nodes assigned to the given Vertex 00382 // when set successfully, or when the given nodePtr is not a valid Physique Link 00383 // SetWeightedNode returns 0. 00384 PHYExport virtual int SetWeightedNode(INode *nodePtr, float weight, BOOL init = FALSE) = 0; 00385 00386 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00387 00388 }; 00389 00390 00391 00392 class IPhyContextImport: public MaxHeapOperators 00393 { 00394 public: 00395 00396 PHYExport virtual ~IPhyContextImport() {} 00397 00398 // this returns the number of vertices for the given modContext's Object 00399 PHYExport virtual int GetNumberVertices() = 0; 00400 00401 // SetVertexInterface return's a VertexInterface (IPhyVertexImport *) for the i'th vertex. 00402 // type = RIGID_NON_BLENDED_TYPE | RIGID_BLENDED_TYPE are currently supported. 00403 // Any other value for type will return NULL. 00404 00405 PHYExport virtual IPhyVertexImport *SetVertexInterface(int i, int type) = 0; 00406 00407 // You must call ReleaseVertexInterface to delete the VertexInterface when finished with it. 00408 PHYExport virtual void ReleaseVertexInterface(IPhyVertexImport *vertexImport) = 0; 00409 00410 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00411 00412 }; 00413 00414 00415 class IPhysiqueImport: public MaxHeapOperators 00416 { 00417 public: 00418 00419 PHYExport virtual ~IPhysiqueImport() {} 00420 00421 //GetContextInterface will return a pointer to IPhyContextImport Interface for a given INode. 00422 // if the given INode does not contain the Physique Modifier of this IPhysique Import then NULL is returned. 00423 PHYExport virtual IPhyContextImport *GetContextInterface(INode* nodePtr) = 0; 00424 00425 // You must call ReleaseContextInterface to delete the ContextInterface when finished with it. 00426 PHYExport virtual void ReleaseContextInterface(IPhyContextImport *contextImport) = 0; 00427 00428 // You call AttachRootNode to define the root node of the Physique Modifier 00429 // This will create default vertex assignments. 00430 // You MUST call AttachRootNode prior to any Imported Vertex Assignments 00431 // This method is designed specifically for developers wanting to 00432 // define Physique fully via import. Predictable results should only be 00433 // expected when this call is followed by a series of Vertex Import calls 00434 // for every ModContext and Vertex of the Modifier. 00435 // If the attach is successful it returns TRUE, otherwise it returns FALSE. 00436 // TimeValue t specifies the initial skeleton pose, the position of the 00437 // skeleton relative to the Object Geometry. 00438 PHYExport virtual BOOL AttachRootNode(INode *nodePtr, TimeValue t) = 0; 00439 00440 PHYExport virtual BOOL InitializePhysique(INode *nodePtr, TimeValue t) = 0; 00441 00442 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00443 00444 }; 00445 00446 class IPhyFloatingVertex : public IPhyVertexExport 00447 { 00448 public: 00449 00450 PHYExport virtual ~IPhyFloatingVertex() {} 00451 00452 PHYExport virtual int GetNumberNodes() = 0; 00453 PHYExport virtual INode *GetNode(int i) = 0; 00454 PHYExport virtual float GetWeight(int i, float &totalweight) = 0; 00455 PHYExport virtual Point3 GetOffsetVector(int i) = 0; 00456 PHYExport virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) = 0; 00457 00458 // GetNumberNodes() returns the number of nodes (bones) assigned to the given Vertex 00459 00460 // GetNode(i) will return the INode pointer of the ith node assigned to 00461 //this Vertex 00462 00463 // GetOffsetVector(i) will return the coordinates of the vertex 00464 // in the local coordinates of associated i'th INode pointer from GetNode(i) 00465 // this is NOT THE SAME as the .vph file coordinates. (It is simpler) 00466 // the world coordinates of the vertex have been transformed by the Inverse of the INode pointer. 00467 00468 // GetWeight(i) will return the normalized weight of the vertex associated with the i'th Node 00469 // pointer from GetNode(i) 00470 00471 }; 00472 00473 00474 00475