reman3/Rayman_X/cpa/tempgrp/MOR/specif/morph.c

643 lines
27 KiB
C

/**********************************************************
* *
* 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 ; j<MAX_MORPH_TASKS ; j++)
{
if(MorphList[j] . bInUse == FALSE)
{
xFreePosition = j;
break;
}
}
if(xFreePosition == -1) return -1; // The list is full
// 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<GLI_lGetVisualSetNumbertOfLOD(pStartPhysicalObject->_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<GLI_lGetVisualSetNumbertOfLOD(pNewPhysicalObject->_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<GLI_lGetVisualSetNumbertOfLOD(pStartPhysicalObject->_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<MAX_MORPH_TASKS ; j++)
{
if(MorphList[j] . bInUse == FALSE)
{
xMorphListIndex = j;
break;
}
}
if(xMorphListIndex == -1)
return -1; // The list is full
bCreateObject = TRUE;
}
else bCreateObject = FALSE;
// Fill the element in the list
mp = MorphList + xMorphListIndex;
mp -> 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<GLI_lGetVisualSetNumbertOfLOD(pNewPhysicalObject->_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<GLI_lGetVisualSetNumbertOfLOD(phy1->_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<geo3 -> 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