/********************************************************** * * * Morphing * * * * This file contains the main functions for the morphing * * * * Author : Ubi China - Alexis Vaisse * * * **********************************************************/ #ifndef U64 //AR980226 These functions are in u_morph.c for U64 #define HieFriend #define PO_FRIEND #define ENV_FRIEND #define D_3dData_StructureDefine #define D_ObjsTbls_Define #include "ACP_base.h" #include "GAM/ToolsCPA.h" #include "gam.h" #include "GMT.h" #include "GEO.h" #include "GLI.h" #include "PCS.h" #include "COL.h" #include "SPO.h" #include "PO.h" #include "mec.h" #include "prt.h" #include "fil.h" #include "snd.h" //#include "fon.h" #include "ipt.h" //#include "env.h" //#include "srf.h" #include "sct.h" // ANNECY - MT 08/05/98 { #include "TMP.h" // END ANNECY MT } #include "x:/cpa/tempgrp/gliglou/multidrv/inc/visus_st.h" //End XB #include "mor.h" /* Variables */ int MaxMorphTask = -1; // The last morph task used. -1 if none MOR_tdstMorphStruct MorphList [MAX_MORPH_TASKS]; // List of the objects being morphed /*----------------------------------------------------------------------------- * Name : MOR_fn_xPrepareMorph *----------------------------------------------------------------------------- * Status : public function * Description : Launch a morphing task *-----------------------------------------------------------------------------*/ ACP_tdxIndex MOR_fn_xPrepareMorph (HIE_tdxHandleToSuperObject _hActorSuperObject , ACP_tdxIndex _xStartIndexInObjectTable , ACP_tdxIndex _xEndIndexInObjectTable , int _iNbMillisecond , int _iStart , int _iEnd , unsigned char _ucMorphType , ACP_tdxIndex _xChannelIndex) { ACP_tdxIndex xMorphListIndex; ACP_tdxIndex j; ACP_tdxIndex xFreePosition=-1; MOR_tdstMorphStruct * mp; PO_tdstPhysicalObject* pStartPhysicalObject; PO_tdstPhysicalObject* pEndPhysicalObject; PO_tdstPhysicalObject* pNewPhysicalObject; _xStartIndexInObjectTable --; // The user enters index >= 1 _xEndIndexInObjectTable --; // and internal indexes are >= 0 // Check if there is already a morphing in the given channel of the given actor xMorphListIndex = fn_hMorphListIndex (_hActorSuperObject->hLinkedObject.p_stCharacter->h_3dData->hMorphChannelList,_xChannelIndex); if(xMorphListIndex != -1 && MorphList [xMorphListIndex] . bInUse == TRUE) return -1; // Find an empty position in the list for(j=0 ; jhLinkedObject.p_stCharacter->h_3dData->h_CurrentObjectsTable->d_stObjectsTable[_xStartIndexInObjectTable].h_Target; pEndPhysicalObject = (PO_tdxHandleToPhysicalObject) _hActorSuperObject->hLinkedObject.p_stCharacter->h_3dData->h_CurrentObjectsTable->d_stObjectsTable[_xEndIndexInObjectTable].h_Target; if (GLI_lGetVisualSetNumbertOfLOD(pStartPhysicalObject->_hVisualSet) != GLI_lGetVisualSetNumbertOfLOD(pEndPhysicalObject->_hVisualSet)) return -1; // The physical objects don't have the same number of geometric objects for(j=0 ; j_hVisualSet); j++) { if (GLI_hGetVisualSetGeometricForADistance(pStartPhysicalObject->_hVisualSet,j)->xNbPoints != GLI_hGetVisualSetGeometricForADistance(pEndPhysicalObject->_hVisualSet,j) -> xNbPoints) return -1; // The geometric objects don't have the same number of points } // Fill the element in the list mp = MorphList + xFreePosition; mp -> bInUse = TRUE; // Copy the parameters mp -> xChannelIndex = _xChannelIndex; mp -> hActorSuperObject = _hActorSuperObject; mp -> xStartIndexInObjectTable = _xStartIndexInObjectTable; mp -> xEndIndexInObjectTable = _xEndIndexInObjectTable; mp -> iNbMillisecond = _iNbMillisecond * 10; mp -> iStart = _iStart * 10; mp -> iEnd = _iEnd * 10; mp -> iCurrent = _iStart * 10; mp -> ucMorphType = _ucMorphType; mp -> iStep = mp -> iStart <= mp -> iEnd ? 10 : -10; // Store the original physical object mp -> pOriginalPhysicalObject = pStartPhysicalObject; // Create a new physical object // ANNECY - MT 08/05/98 { MMG_fn_vAddMemoryInfo (MMG_C_lTypeMOR , MMG_C_lSubTypePO , 0); MOR_M_pvMalloc (pNewPhysicalObject , PO_tdstPhysicalObject * , sizeof (PO_tdstPhysicalObject)); // END ANNECY MT } // Store it into the element of the list mp -> pMorphedPhysicalObject = pNewPhysicalObject; // Create its visual set // ANNECY - MT 11/05/98 { pNewPhysicalObject -> _hVisualSet = GLI_p_stCreateTMPVisualSet (GLI_lGetVisualSetNumbertOfLOD(pStartPhysicalObject->_hVisualSet)); // END ANNECY MT } pNewPhysicalObject -> _hVisualSet -> xLastDistance = pStartPhysicalObject->_hVisualSet->xLastDistance; pNewPhysicalObject -> _hVisualSet -> xNbLodDefinitions = (short)GLI_lGetVisualSetNumbertOfLOD(pStartPhysicalObject->_hVisualSet); // Copy the collision set pNewPhysicalObject -> _hCollideSet = pStartPhysicalObject->_hCollideSet; pNewPhysicalObject -> _hBoundingVolume = pStartPhysicalObject->_hBoundingVolume; // Create the geometric objects for(j=0 ; j_hVisualSet) ; j++) { pNewPhysicalObject->_hVisualSet->d_xThresholdsTable[j] = mp -> pOriginalPhysicalObject->_hVisualSet->d_xThresholdsTable[j]; pNewPhysicalObject->_hVisualSet->d_p_stLodDefinitions[j] = MOR_fn_xCopyGeometricObjectForMorph (mp->pOriginalPhysicalObject->_hVisualSet->d_p_stLodDefinitions[j]); } // Put the morphed object into the list of morphed objects of the actor fn_vPutMorphElementInChannel (_hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> hMorphChannelList , _xChannelIndex , xFreePosition); // Update MaxMorphTask (which contains the maximum index of the used elements in the list if (xFreePosition > MaxMorphTask) MaxMorphTask = xFreePosition; return xFreePosition; } /*----------------------------------------------------------------------------- * Name : MOR_fn_xStopMorph *----------------------------------------------------------------------------- * Status : public function * Description : Stop a morphing task *-----------------------------------------------------------------------------*/ ACP_tdxIndex MOR_fn_xStopMorph(HIE_tdxHandleToSuperObject _hActorSuperObject, ACP_tdxIndex _xChannelIndex) { ACP_tdxIndex xMorphListIndex; ACP_tdxIndex j; MOR_tdstMorphStruct * mp=NULL; // Check that the given channel of the given actor has a morphed object xMorphListIndex = fn_hMorphListIndex (_hActorSuperObject->hLinkedObject.p_stCharacter->h_3dData->hMorphChannelList, _xChannelIndex); if(xMorphListIndex == -1 || MorphList [xMorphListIndex] . bInUse == FALSE) return -1; // Not found // Find the element in the list for(j=0 ; j<=MaxMorphTask ; j++) { mp=MorphList+j; if (mp -> bInUse && mp -> hActorSuperObject == _hActorSuperObject && mp -> xChannelIndex == _xChannelIndex) break; else mp = NULL; } if (mp == NULL) return -1; // Not found into the list // Replace the morphed object by the 'end' object in the hierarchy MOR_fn_bRemoveMorphedObjectFromHierarchy (mp -> hActorSuperObject , mp -> pMorphedPhysicalObject, (PO_tdxHandleToPhysicalObject) mp -> hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> h_CurrentObjectsTable -> d_stObjectsTable [mp -> xEndIndexInObjectTable] . h_Target); // Delete the created physical object MOR_fn_vDeletePhysicalObject (mp -> pMorphedPhysicalObject); mp -> pMorphedPhysicalObject = NULL; // Remove the element in the list (if we remove the last morph task, we can decreaze MaxMorphTask) MOR_fn_vCleanMorph (mp); if (j == MaxMorphTask) MaxMorphTask --; // Remove the morphed object from the list of morphed objects of the actor fn_vRemoveChannelFromMorphList (_hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> hMorphChannelList , _xChannelIndex); return 0; // No error } /*----------------------------------------------------------------------------- * Name : MOR_fn_xMorphing *----------------------------------------------------------------------------- * Status : public function * Description : Morph an object in a channel *-----------------------------------------------------------------------------*/ ACP_tdxIndex MOR_fn_xMorphing (HIE_tdxHandleToSuperObject _hActorSuperObject , ACP_tdxIndex _xStartIndexInObjectTable , ACP_tdxIndex _xEndIndexInObjectTable , int _iRatio , ACP_tdxIndex _xChannelIndex) { ACP_tdxIndex xMorphListIndex; ACP_tdxIndex j; MOR_tdstMorphStruct * mp; PO_tdstPhysicalObject* pStartPhysicalObject; PO_tdstPhysicalObject* pEndPhysicalObject; PO_tdstPhysicalObject* pNewPhysicalObject; ACP_tdxBool bCreateObject; // Check of the two objects have the same number of points pStartPhysicalObject = (PO_tdxHandleToPhysicalObject) _hActorSuperObject->hLinkedObject.p_stCharacter->h_3dData->h_CurrentObjectsTable->d_stObjectsTable[_xStartIndexInObjectTable].h_Target; pEndPhysicalObject = (PO_tdxHandleToPhysicalObject) _hActorSuperObject->hLinkedObject.p_stCharacter->h_3dData->h_CurrentObjectsTable->d_stObjectsTable[_xEndIndexInObjectTable].h_Target; if (GLI_lGetVisualSetNumbertOfLOD(pStartPhysicalObject->_hVisualSet) != GLI_lGetVisualSetNumbertOfLOD(pEndPhysicalObject->_hVisualSet)) return -1; // The physical objects don't have the same number of geometric objects for(j=0 ; j_hVisualSet); j++) { if (pStartPhysicalObject -> _hVisualSet -> d_p_stLodDefinitions [j] -> xNbPoints != pEndPhysicalObject -> _hVisualSet -> d_p_stLodDefinitions [j] -> xNbPoints) return -1; // The geometric objects don't have the same number of points } // Check if there is already a morphing in the given channel of the given actor xMorphListIndex = fn_hMorphListIndex (_hActorSuperObject->hLinkedObject.p_stCharacter->h_3dData->hMorphChannelList,_xChannelIndex); // If not, create the morphing task if (xMorphListIndex == -1 || MorphList [xMorphListIndex] . bInUse == FALSE) { xMorphListIndex = -1; // Find an empty position in the list for(j=0 ; j bInUse = TRUE; // Copy the parameters mp -> xChannelIndex = _xChannelIndex; mp -> hActorSuperObject = _hActorSuperObject; mp -> xStartIndexInObjectTable = _xStartIndexInObjectTable; mp -> xEndIndexInObjectTable = _xEndIndexInObjectTable; mp -> iNbMillisecond = 100; // 10 milliseconds < 1/60 second mp -> iEnd = _iRatio; mp -> iStart = mp -> iEnd - 1; mp -> iCurrent = mp -> iStart; mp -> ucMorphType = MORPH_WAITATEND; mp -> iStep = 10; // Store the original physical object mp -> pOriginalPhysicalObject = pStartPhysicalObject; if (bCreateObject) { // Create a new physical object // ANNECY - MT 08/05/98 { MMG_fn_vAddMemoryInfo (MMG_C_lTypeMOR , MMG_C_lSubTypePO , 0); MOR_M_pvMalloc (pNewPhysicalObject , PO_tdstPhysicalObject * , sizeof (PO_tdstPhysicalObject)); // END ANNECY MT } // Store it into the element of the list mp -> pMorphedPhysicalObject = pNewPhysicalObject; // Create its visual set // ANNECY - MT 11/05/98 { pNewPhysicalObject -> _hVisualSet = GLI_p_stCreateTMPVisualSet (GLI_lGetVisualSetNumbertOfLOD(pStartPhysicalObject->_hVisualSet)); // END ANNECY MT } pNewPhysicalObject -> _hVisualSet -> xLastDistance = pStartPhysicalObject->_hVisualSet->xLastDistance; pNewPhysicalObject -> _hVisualSet -> xNbLodDefinitions = (short)GLI_lGetVisualSetNumbertOfLOD(pStartPhysicalObject->_hVisualSet); // Copy the collision set pNewPhysicalObject -> _hCollideSet = pStartPhysicalObject->_hCollideSet; pNewPhysicalObject -> _hBoundingVolume = pStartPhysicalObject->_hBoundingVolume; // Create the geometric objects for(j=0 ; j_hVisualSet) ; j++) { pNewPhysicalObject->_hVisualSet->d_xThresholdsTable[j] = mp -> pOriginalPhysicalObject->_hVisualSet->d_xThresholdsTable[j]; pNewPhysicalObject->_hVisualSet->d_p_stLodDefinitions[j] = MOR_fn_xCopyGeometricObjectForMorph (mp->pOriginalPhysicalObject->_hVisualSet->d_p_stLodDefinitions[j]); } // Put the morphed object into the list of morphed objects of the actor fn_vPutMorphElementInChannel (_hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> hMorphChannelList , _xChannelIndex , xMorphListIndex); } // Update MaxMorphTask (which contains the maximum index of the used elements in the list if (xMorphListIndex > MaxMorphTask) MaxMorphTask = xMorphListIndex; return xMorphListIndex; } /*----------------------------------------------------------------------------- * Name : MOR_fn_vMorphTo *----------------------------------------------------------------------------- * Status : private function * Description : Compute one frame of a morphed object *-----------------------------------------------------------------------------*/ void MOR_fn_vMorphTo (MOR_tdstMorphStruct * mp) { MTH_tdxReal xRatio; ACP_tdxIndex i,j; PO_tdstPhysicalObject * phy1 , * phy2 , * phy3; GEO_tdstGeometricObject * geo1 , * geo2 , * geo3; // Compute the ratio (between 0 and 1) xRatio = MTH_M_xDiv (MTH_M_xLongToReal (mp -> iCurrent) , MTH_M_xLongToReal (mp -> iNbMillisecond)); if (MTH_M_bGreater (xRatio , MTH_C_ONE )) xRatio = MTH_C_ONE; else if (MTH_M_bLess (xRatio , MTH_C_ZERO)) xRatio = MTH_C_ZERO; // Get the physical object : phy1 is the 'start' object, phy2 the 'end' object and phy3 the morphed object phy1 = (PO_tdxHandleToPhysicalObject) mp -> hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> h_CurrentObjectsTable -> d_stObjectsTable [mp -> xStartIndexInObjectTable] . h_Target; phy2 = (PO_tdxHandleToPhysicalObject) mp -> hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> h_CurrentObjectsTable -> d_stObjectsTable [mp -> xEndIndexInObjectTable ] . h_Target; phy3 = mp -> pMorphedPhysicalObject; // For each geometric object of the physical object ... for(i=0 ; i_hVisualSet) ; i++) { geo1 = phy1 -> _hVisualSet -> d_p_stLodDefinitions [i]; geo2 = phy2 -> _hVisualSet -> d_p_stLodDefinitions [i]; geo3 = phy3 -> _hVisualSet -> d_p_stLodDefinitions [i]; // For each point of the geometric object ... for(j=0 ; j xNbPoints ; j++) { MTH3D_M_vLinearInterpolVector (& geo3 -> d_stListOfPoints [j] , & geo1 -> d_stListOfPoints [j] , & geo2 -> d_stListOfPoints [j] , xRatio); /* The calculation of the normals is done by the GEO_vEndModifyObject2 function MTH3D_M_vLinearInterpolVector (& geo3 -> d_stListOfPointsNormals [j] , & geo1 -> d_stListOfPointsNormals [j] , & geo2 -> d_stListOfPointsNormals [j] , xRatio); */ } // Recompute the normals GEO_vEndModifyObject2 (geo3); } } /*----------------------------------------------------------------------------- * Name : MOR_fn_vCleanMorph *----------------------------------------------------------------------------- * Status : private function * Description : Remove one element in the list of morph elements *-----------------------------------------------------------------------------*/ void MOR_fn_vCleanMorph (MOR_tdstMorphStruct * mp) { if( mp -> bInUse == FALSE) return; memset(mp , 0 , sizeof (MOR_tdstMorphStruct)); mp -> bInUse = FALSE; } /*----------------------------------------------------------------------------- * Name : MOR_fn_vMorphAddInMainLoop *----------------------------------------------------------------------------- * Status : public function * Description : Call each frame to compute the morphed objects *-----------------------------------------------------------------------------*/ void GEO_fn_vMorphAddInMainLoop (void) { ACP_tdxIndex i; MOR_tdstMorphStruct * mp; int iIncrement; for(i=0 ; i<=MaxMorphTask ; i++) { mp = MorphList + i; if(mp -> bInUse) { // Increaze the counter of the duration of the last frame (in millisecond) iIncrement = g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime * mp -> iStep; mp -> iCurrent += iIncrement; switch (mp -> ucMorphType) { case MORPH_STOPATEND: // If we have reached the end of the morphing, we stop the morphing task if(mp -> iCurrent > mp -> iEnd) { // Replace the morphed object by the 'end' object in the hierarchy MOR_fn_bRemoveMorphedObjectFromHierarchy (mp -> hActorSuperObject, mp -> pMorphedPhysicalObject, (PO_tdxHandleToPhysicalObject) mp -> hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> h_CurrentObjectsTable -> d_stObjectsTable [mp -> xEndIndexInObjectTable] . h_Target); // Delete the create physical object MOR_fn_vDeletePhysicalObject (mp -> pMorphedPhysicalObject); // Remove the morphed object from the list of morphed objects of the actor fn_vRemoveChannelFromMorphList (mp -> hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> hMorphChannelList, mp -> xChannelIndex); // Remove the element in the list (if we remove the last morph task, we can decreaze MaxMorphTask) MOR_fn_vCleanMorph (mp); if (i == MaxMorphTask) MaxMorphTask --; break; } // Compute the morphed object MOR_fn_vMorphTo (mp); break; case MORPH_WAITATEND: // If we have reached the end of the morphing ... if (mp -> iCurrent > mp -> iEnd) { // If the last computed frame was not the 'end' frame, we compute it if (mp -> iCurrent - iIncrement < mp -> iEnd) mp -> iCurrent = mp -> iEnd; // Else we do nothing else break; } // Compute the morphed object MOR_fn_vMorphTo (mp); break; case MORPH_ROLLBACKATEND: // If we have reached the end of the first morph (from 'Start' to 'End') if(mp -> iCurrent > mp -> iEnd) { if ( mp -> iCurrent < mp -> iEnd + (mp -> iEnd - mp -> iStart)) mp -> iCurrent = mp -> iEnd - (mp -> iCurrent - mp -> iEnd); else mp -> iCurrent = mp -> iEnd; mp -> iStep = - abs (mp -> iStep); } else // If we have reached the end of the second morph (from 'End' to 'Start') if (mp -> iCurrent < mp -> iStart) { if (mp -> iCurrent > mp -> iStart - (mp -> iEnd - mp -> iStart)) mp -> iCurrent = mp -> iStart + (mp -> iStart - mp -> iCurrent); else mp -> iCurrent = mp -> iStart; mp -> iStep = abs (mp -> iStep); } // Compute the morphed object MOR_fn_vMorphTo (mp); break; } // end switch } // end if } // end for } /*----------------------------------------------------------------------------- * Name : MOR_fn_vFirstInitMorphTaskList *----------------------------------------------------------------------------- * Status : public function * Description : Initialization of the morphing module *-----------------------------------------------------------------------------*/ void fn_vFirstInitMorphTaskList() { memset (MorphList , 0 , sizeof (MOR_tdstMorphStruct) * MAX_MORPH_TASKS); } /*----------------------------------------------------------------------------- * Name : MOR_fn_vLastDeinitMorphTaskList *----------------------------------------------------------------------------- * Status : public function * Description : Desinitialization of the morphing module *-----------------------------------------------------------------------------*/ void fn_vLastDeinitMorphTaskList() { ACP_tdxIndex i; for(i=0 ; i<=MaxMorphTask ; i++) { if(MorphList[i] . bInUse) { MOR_fn_vCleanMorph (MorphList + i); } } } /*----------------------------------------------------------------------------- * Name : MOR_fn_bIsChannelMorphed *----------------------------------------------------------------------------- * Status : public function * Description : Return TRUE if there is a morphed object in the given channel of the given actor *-----------------------------------------------------------------------------*/ ACP_tdxBool MOR_fn_bIsChannelMorphed (HIE_tdxHandleToSuperObject _hActorSuperObject, ACP_tdxIndex _xChannelIndex) { ACP_tdxIndex i; MOR_tdstMorphStruct * mp; for (i = 0 ; i <= MaxMorphTask ; i ++) { mp = MorphList + i; if (mp -> bInUse && mp -> hActorSuperObject == _hActorSuperObject && mp -> xChannelIndex == _xChannelIndex) { // With the 'MORPH_WAITATEND' or 'MORPH_STOPATEND' type, the morphing is finished if we have reached the end if ((mp -> ucMorphType == MORPH_WAITATEND || mp -> ucMorphType == MORPH_STOPATEND) && mp -> iCurrent >= mp -> iEnd) return FALSE; else return TRUE; } } return FALSE; // Not found } /*----------------------------------------------------------------------------- * Name : MOR_fn_vRemoveAllMorphedObject *----------------------------------------------------------------------------- * Status : public function * Description : Remove all the morphed objects (used when there is a 'Reinit the map' or when entering the editor) *-----------------------------------------------------------------------------*/ void MOR_fn_vRemoveAllMorphedObjects (void) { ACP_tdxIndex i; MOR_tdstMorphStruct * mp; for (i = 0 ; i <= MaxMorphTask ; i ++) { mp = MorphList + i; if (mp -> bInUse) { // Replace the morphed object by the original physical object in the hierarchy MOR_fn_bRemoveMorphedObjectFromHierarchy (mp -> hActorSuperObject , mp -> pMorphedPhysicalObject , mp -> pOriginalPhysicalObject); // Remove the morphed object from the list of morphed objects of the actor if (mp->hActorSuperObject->hLinkedObject.p_stCharacter->h_StandardGame) fn_vRemoveChannelFromMorphList (mp -> hActorSuperObject -> hLinkedObject . p_stCharacter -> h_3dData -> hMorphChannelList, mp -> xChannelIndex); // Delete the created physical object MOR_fn_vDeletePhysicalObject (mp->pMorphedPhysicalObject); // Remove the element in the list MOR_fn_vCleanMorph (mp); } } MaxMorphTask = -1; } /*----------------------------------------------------------------------------- * Name : MOR_fn_bRemoveMorphedObjectFromHierarchy *----------------------------------------------------------------------------- * Status : Private function * Description : Recursiv function to remove and replace an object in the hierarchy *-----------------------------------------------------------------------------*/ ACP_tdxBool MOR_fn_bRemoveMorphedObjectFromHierarchy (HIE_tdxHandleToSuperObject hSuperObject , PO_tdstPhysicalObject * p_stPhysicalObjectToRemove , PO_tdstPhysicalObject * p_stPhysicalObjectToPut) { HIE_tdxHandleToSuperObject hChildSuperObject; ACP_tdxIndex i; if (HIE_fn_hGetSuperObjectObject (hSuperObject) == p_stPhysicalObjectToRemove) { HIE_fn_vSetSuperObjectObjectAndType (hSuperObject , p_stPhysicalObjectToPut , HIE_C_ulPO); return TRUE; } HIE_M_ForEachChildOf (hSuperObject , hChildSuperObject , i) { if (MOR_fn_bRemoveMorphedObjectFromHierarchy (hChildSuperObject , p_stPhysicalObjectToRemove , p_stPhysicalObjectToPut)) return TRUE; } return FALSE; } /*----------------------------------------------------------------------------- * Name : MOR_fn_hGetMorphedObject *----------------------------------------------------------------------------- * Status : Public function * Description : Return the morphed object of an element in the list *-----------------------------------------------------------------------------*/ PO_tdxHandleToPhysicalObject MOR_fn_hGetMorphedObject (ACP_tdxIndex _xIndex) { return MorphList [_xIndex] . pMorphedPhysicalObject; } /*---------------------------------------------------------------------------- -- Description : MOR_fn_vDoMorph -- Execute the morphing operation corresponding to an index into the morph -- task list ------------------------------------------------------------------------------ -- Methods : Use the morphto function ------------------------------------------------------------------------------ -- Input : _xIndex : Index of the task -- Output : ------------------------------------------------------------------------------ -- Creation date : Mar 97 Author: Alain Robin ------------------------------------------------------------------------------ -- Modifications : -- Modification date : Modification author : ----------------------------------------------------------------------------*/ void MOR_fn_vDoMorph(ACP_tdxIndex _xIndex) { MOR_tdstMorphStruct * mp; mp = MorphList + _xIndex; MOR_fn_vMorphTo(mp); } #endif //U64 AR980226