/********************************************************** * * * Magnet * * * * Author : Ubi China - Marc Trabucato * * * **********************************************************/ #include "acp_base.h" #define D_MSMagnet_StructureDefine #include "MTH.h" #include "GEO.h" #include "GLI.h" /*XB980506*/ /*#include "incGAM.h"*/ #include "mec.h" #include "fil.h" #include "snd.h" #include "pcs.h" #include "gld.h" #include "lst.h" #ifdef USE_IPT_DX5 #include "IPT_DX5.h" /* InPuT (absolutely before GAM.h)*/ #else /* USE_IPT_WIN */ #include "IPT.h" /* InPuT (absolutely before GAM.h)*/ #endif /* USE_IPT_WIN */ /*#include "srf.h"*/ /*#include "env.h"*/ #include "sct.h" #include "prt.h" #include "gam.h" /*#include "incSPO.h"*/ #include "pos.h" #include "spo.h" /*#include "incIPO.h"*/ #include "po.h" /*XB980821*/ #ifndef D_THROW_IPO #include "ipo.h" #endif /* D_THROW_IPO */ /*End XB*/ /*End XB*/ #include "COL.h" #include "MGT\MGTStruc.h" #include "MGTInit.h" #include "MGTMain.h" #include "MGTmm.h" #include "MGTmo.h" #ifdef MGT_RASTER #include "MGTRast.h" #endif #define MGT_C_NoMoveDistanceSqr MTH_M_xFloatToReal( 0.04 ) EXTERN HIE_tdxHandleToSuperObject SECT_hFatherSector; /*************************************************************************************************/ #define MGT_M_bIsSetBit( p_cTab , xIndex ) ( p_cTab[ xIndex >> 3 ] & ( 1 << (xIndex & 0x00000007) ) ) #define MGT_M_vSetBit( p_cTab , xIndex ) ( p_cTab[ xIndex >> 3 ] |= ( 1 << (xIndex & 0x00000007) ) ) #define MGT_M_vUnSetBit( p_cTab , xIndex ) ( p_cTab[ xIndex >> 3 ] &= ~((char)( 1 << (xIndex & 0x00000007) )) ) /* INLINE ACP_tdxBool MGT_M_bIsSetBit( char *p_cTab , ACP_tdxIndex xIndex ) { ACP_tdxIndex xDiv , xMod; xDiv = xIndex >> 3; xMod = ( xIndex & 0x00000007 ); return ( p_cTab[ xDiv ] & ( 1 << xMod ) ); } INLINE void MGT_M_vSetBit( char *p_cTab , ACP_tdxIndex xIndex ) { ACP_tdxIndex xDiv , xMod; xDiv = xIndex >> 3; xMod = ( xIndex & 0x00000007 ); p_cTab[ xDiv ] |= ( 1 << xMod ); } INLINE void MGT_M_vUnSetBit( char *p_cTab , ACP_tdxIndex xIndex ) { ACP_tdxIndex xDiv , xMod; char cValue; xDiv = xIndex >> 3; xMod = ( xIndex & 0x00000007 ); cValue = ~((char)( 1 << xMod )); p_cTab[ xDiv ] &= cValue; } */ /* =================================================================================================== * The main loop in Game Engine to deal with magnet morph. * * QZY 1997.11.18 =================================================================================================== */ void MGT_fn_vTreatMagnets(void) { ACP_tdxIndex xMagnetIndex , xObjectIndex; HIE_tdxHandleToSuperObject *p_h_SOMagnet; MS_tdxHandleToMSMagnet h_Magnet; MTH3D_tdstVector *p_stPreviousPosition , stCurrentPosition , stMove; MTH_tdxReal xDistance; MGT_tdxHandleToModifiedObject *p_h_ModifiedObject; MGT_tdxHandleToMagnetModification *p_h_MagnetModif; ACP_tdxBool bObjectChanged ; unsigned char ucStatus; /* update list of influenced points*/ if( MGT_g_xMaxIndexOfModifiedObject ) { MGT_fn_vInitTreatement(); } for ( xMagnetIndex = 0 , p_h_SOMagnet = MGT_g_aDEF_hActivatedMagnets ; xMagnetIndex < MGT_g_xMaxIndexOfActivatedMagnet ; xMagnetIndex++, p_h_SOMagnet++ ) { h_Magnet = (*p_h_SOMagnet) ? M_GetMSHandle( (*p_h_SOMagnet), MSMagnet) : NULL ; if( h_Magnet ) { ucStatus = fn_lMSMagnetGetStatus( h_Magnet ); if( fn_bMSMagnetIsNearFarModified( h_Magnet ) ) { POS_fn_vGetTranslationVector( HIE_fn_hGetSuperObjectGlobalMatrix( (*p_h_SOMagnet) ), & stCurrentPosition ); p_stPreviousPosition = fn_hMSMagnetGetPosition( h_Magnet ); MTH3D_M_vSubVector( & stMove , & stCurrentPosition , p_stPreviousPosition ); fn_vMSMagnetSetPosition( h_Magnet, & stCurrentPosition ); MGT_fn_vComputeInfluence( (*p_h_SOMagnet), h_Magnet, xMagnetIndex ); } else { /* compute movement distance*/ switch( fn_lMSMagnetGetStatus( h_Magnet ) ) { case MAGNETOFF: case MAGNETRECOVERING: fn_vMSMagnetSetPositionModification( h_Magnet, FALSE ); MGT_fn_vUpdateInfluence( h_Magnet , FALSE ); MGT_fn_vSetMagnetModificationUse( h_Magnet , TRUE ); break; case MAGNETON: case MAGNETGROWING: POS_fn_vGetTranslationVector( HIE_fn_hGetSuperObjectGlobalMatrix( (*p_h_SOMagnet) ), & stCurrentPosition ); p_stPreviousPosition = fn_hMSMagnetGetPosition( h_Magnet ); MTH3D_M_vSubVector( & stMove , & stCurrentPosition , p_stPreviousPosition ); xDistance = MTH3D_M_xSqrVector( & stMove ); if( MTH_M_bGreater( xDistance , MGT_C_NoMoveDistanceSqr ) ) { fn_vMSMagnetSetPosition( h_Magnet, & stCurrentPosition ); fn_vMSMagnetSetPositionModification( h_Magnet, TRUE ); MGT_fn_vComputeInfluence( (*p_h_SOMagnet), h_Magnet, xMagnetIndex ); } else { fn_vMSMagnetSetPositionModification( h_Magnet, FALSE ); MGT_fn_vSetMagnetModificationUse( h_Magnet , TRUE ); } break; } } } } if( MGT_g_xMaxIndexOfModifiedObject ) { MGT_fn_vEndTreatement(); } /* compute influence*/ for( xObjectIndex = 0 , p_h_ModifiedObject = MGT_g_aDEF_hModifiedObjects ; xObjectIndex < MGT_g_xMaxIndexOfModifiedObject ; xObjectIndex++, p_h_ModifiedObject++ ) { if( *p_h_ModifiedObject ) { bObjectChanged = FALSE; for( xMagnetIndex = 0 , p_h_MagnetModif = (*p_h_ModifiedObject) -> aDEF_hMagnet ; xMagnetIndex < MGT_MAX_NUMBEROF_MAGNETS ; xMagnetIndex++, p_h_MagnetModif++ ) { if( *p_h_MagnetModif ) { if( MGT_fn_bMorphMagnetModif( *p_h_MagnetModif ) ) bObjectChanged = TRUE; } } if( bObjectChanged ) { GEO_vEndModifyObject2( (*p_h_ModifiedObject) -> p_stMorphedObject ); } } } if( MGT_g_xMaxIndexOfModifiedObject ) { /* recompute bounding volume*/ MGT_fn_bUpdateBoundingVolume(); /* update ModifiedObjects List*/ MGT_fn_vUpdateModifiedObjectsList(); } /**/ if( MGT_g_xMaxIndexOfActivatedMagnet ) { /* update MSMagnet List*/ MGT_fn_vUpdateActivatedMagnetsList(); } } /*======================================================================================= * Description * * Creation date 02/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vInitTreatement( void ) { ACP_tdxIndex xIndex , xIndexMagnet; MGT_tdxHandleToModifiedObject *p_h_ModifiedObject; MGT_tdxHandleToMagnetModification *p_h_MagnetModif; for( xIndex = 0 , p_h_ModifiedObject = MGT_g_aDEF_hModifiedObjects ; xIndex < MGT_g_xMaxIndexOfModifiedObject ; xIndex++, p_h_ModifiedObject++ ) { if( *p_h_ModifiedObject ) { MGT_fn_vClearAlreadyInfluencedPointsOfModifiedObject( *p_h_ModifiedObject ); for ( xIndexMagnet = 0 , p_h_MagnetModif = (*p_h_ModifiedObject) -> aDEF_hMagnet ; xIndexMagnet < MGT_MAX_NUMBEROF_MAGNETS ; xIndexMagnet++, p_h_MagnetModif++ ) { if( (*p_h_MagnetModif) ) (*p_h_MagnetModif) -> bUsed = FALSE; } } } } /*======================================================================================= * Description * * Creation date 02/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vEndTreatement( void ) { ACP_tdxIndex xIndex , xIndexMagnet; MGT_tdxHandleToModifiedObject *p_h_ModifiedObject; MGT_tdxHandleToMagnetModification *p_h_MagnetModif; for( xIndex = 0 , p_h_ModifiedObject = MGT_g_aDEF_hModifiedObjects ; xIndex < MGT_g_xMaxIndexOfModifiedObject ; xIndex++, p_h_ModifiedObject++ ) { if( *p_h_ModifiedObject ) { MGT_fn_vClearAlreadyInfluencedPointsOfModifiedObject( *p_h_ModifiedObject ); for ( xIndexMagnet = 0 , p_h_MagnetModif = (*p_h_ModifiedObject) -> aDEF_hMagnet ; xIndexMagnet < MGT_MAX_NUMBEROF_MAGNETS ; xIndexMagnet++, p_h_MagnetModif++ ) { if( (*p_h_MagnetModif) ) { if( (*p_h_MagnetModif) -> bUsed ) break; else MGT_fn_vDeleteMagnetModification( *p_h_MagnetModif ); } } if( xIndexMagnet == MGT_MAX_NUMBEROF_MAGNETS ) MGT_fn_vDeleteModifiedObjectIfNeeded( xIndex ); } } } /*======================================================================================= * Description compute the influence of magnet in all static objects * * Creation date 01/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vComputeInfluence( HIE_tdxHandleToSuperObject h_SO , MS_tdxHandleToMSMagnet h_Magnet , ACP_tdxIndex x_Magnet ) { /* init influence*/ ACP_tdxIndex xIndex; MTH_tdxReal xFar, xFarFar; MS_tdxHandleToSectInfo hSectInfo; HIE_tdxHandleToSuperObject h_SOSector; SECT_tdxHandleOfElementLstCollisionInteraction hCollisionList; MGT_fn_vUpdateInfluence( h_Magnet , TRUE ); MGT_fn_vSetMagnetModificationUse( h_Magnet , FALSE ); xFar = fn_xMSMagnetGetFar( h_Magnet ); xFarFar = MTH_M_xSqr( xFar ); MGT_fn_vClearMagnetModificationFlagInHierarchy( SECT_hFatherSector ); hSectInfo = M_GetMSHandle( h_SO , SectInfo ); h_SOSector = fn_h_SectInfoGetCurrentSector( hSectInfo ); /* call recurse influence on Current sector*/ MGT_fn_bComputeInfluenceOnSuperObject( h_Magnet, x_Magnet, xFarFar, h_SOSector ); /* call recurse influence on collisionable sectors*/ SECT_M_ForEachCollisionNodeInCollisionInteractionList( h_SOSector, hCollisionList, xIndex ) { h_SOSector = SECT_GetSectorInCollisionList( hCollisionList ); MGT_fn_bComputeInfluenceOnSuperObject( h_Magnet, x_Magnet, xFarFar, h_SOSector ); } /* update MSMagnet*/ for( xIndex = 0 ; xIndex < MGT_MAX_NUMBEROF_MODIFIEDOBJECTS ; xIndex++ ) { if( fn_hMSMagnetGetMagnetModification( h_Magnet, xIndex ) ) { break; } } if( ( xIndex == MGT_MAX_NUMBEROF_MODIFIEDOBJECTS ) && (fn_lMSMagnetGetStatus( h_Magnet ) == MAGNETRECOVERING) ) { fn_vMSMagnetSetStatus( h_Magnet, MAGNETOFF); /* delete the magnet from the active magnet list.*/ MGT_fn_vDeleteMagnetFromMagnetList( x_Magnet ); } } /*======================================================================================= * Description * * Creation date 02/03/98 * Author Marc Trabucato *=====================================================================================*/ ACP_tdxIndex MGT_fn_bComputeInfluenceOnSuperObject( MS_tdxHandleToMSMagnet h_Magnet , ACP_tdxIndex x_Magnet , MTH_tdxReal xFarFar, HIE_tdxHandleToSuperObject h_SuperObject ) { GEO_tdstGeometricObject *p_stObject; HIE_tdxHandleToSuperObject h_Child; ACP_tdxIndex xIndex; POS_tdxHandleToPosition hMatrix; POS_tdstCompletePosition stMatrix; MTH3D_tdstVector stMagnetLocalPosition, *p_stPosition; MTH_tdxReal xRadius; ACP_tdxIndex x_ModifiedObject; ACP_tdxBool bObjectModified , bIntersectBdV, bBoxVolume; GEO_tdxHandleToParallelBox hBoxVolume; GEO_tdxHandleToBoundingSphere hSphereVolume; MTH3D_tdstVector stMaxBoxPoint , stMinBoxPoint , stCenter; /* compute influence on the SO*/ bIntersectBdV = TRUE; bObjectModified = FALSE; p_stObject = HIE_fn_p_stGetGeometricObjectFromSuperObject( h_SuperObject ); if( p_stObject ) { bBoxVolume = HIE_fn_SO_bHasABoxBoundingVolume( h_SuperObject ); x_ModifiedObject = MGT_fn_xFindModifiedObject( p_stObject ); bObjectModified = FALSE; hMatrix = HIE_fn_hGetSuperObjectGlobalMatrix( h_SuperObject ); p_stPosition = fn_hMSMagnetGetPosition( h_Magnet ); /**/ /* take account Bounding Box of SO*/ if( bBoxVolume ) { hBoxVolume = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume( h_SuperObject ); if( hBoxVolume ) { MTH3D_M_vAddVector( & stMaxBoxPoint, & hMatrix -> stTranslationVector, GEO_fn_pGetMaxPointOfParallelBox( hBoxVolume ) ); MTH3D_M_vAddVector( & stMinBoxPoint, & hMatrix -> stTranslationVector, GEO_fn_pGetMinPointOfParallelBox( hBoxVolume ) ); bIntersectBdV = INT_fn_bIntersectSphereWithBox( p_stPosition, fn_xMSMagnetGetFar( h_Magnet ), & stMinBoxPoint, & stMaxBoxPoint ); } if( bIntersectBdV ) { POS_fn_vInvertMatrix( & stMatrix , hMatrix ); POS_fn_vMulMatrixVertex( & stMagnetLocalPosition , & stMatrix , p_stPosition ); } } else { hSphereVolume = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume( h_SuperObject ); POS_fn_vInvertMatrix( & stMatrix , hMatrix ); POS_fn_vMulMatrixVertex( & stMagnetLocalPosition , & stMatrix , p_stPosition ); if( hSphereVolume ) { MTH3D_M_vCopyVector(&stCenter, GEO_fn_pGetCenterPointOfBoundingSphere(hSphereVolume)); xRadius = GEO_fn_xGetRadiusOfBoundingSphere(hSphereVolume); bIntersectBdV = INT_fn_bIntersectSphereWithSphere( & stMagnetLocalPosition, fn_xMSMagnetGetFar( h_Magnet ), & stCenter , xRadius ); } } if( bIntersectBdV ) { bObjectModified = MGT_fn_bComputeInfluenceOnObject( x_Magnet, xFarFar, p_stObject , &x_ModifiedObject, & stMagnetLocalPosition , h_SuperObject ); if( bObjectModified ) { HIE_fn_vSetMagnetModification( h_SuperObject, TRUE ); } } if( (x_ModifiedObject != MGT_C_xIndexError) && ! bObjectModified && ( fn_lMSMagnetGetStatus( h_Magnet ) == MAGNETRECOVERING ) ) { MGT_fn_hDeleteIfExistsMagnetModification( x_ModifiedObject, x_Magnet ); } } if( bIntersectBdV ) { /* node examination*/ HIE_M_ForEachChildOf(h_SuperObject, h_Child, xIndex) { /* recurence*/ bObjectModified |= MGT_fn_bComputeInfluenceOnSuperObject( h_Magnet , x_Magnet , xFarFar, h_Child ); } } HIE_fn_vSetMagnetModification( h_SuperObject, bObjectModified ); return bObjectModified; } /*======================================================================================= * Description * * Creation date 01/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vClearMagnetModificationFlagInHierarchy( HIE_tdxHandleToSuperObject h_SuperObject ) { HIE_tdxHandleToSuperObject h_Child; ACP_tdxIndex xIndex; HIE_fn_vSetMagnetModification( h_SuperObject, FALSE ); HIE_M_ForEachChildOf(h_SuperObject, h_Child, xIndex) { /* recurence*/ MGT_fn_vClearMagnetModificationFlagInHierarchy( h_Child); } } /*======================================================================================= * Description * * Creation date 01/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_bUpdateBoundingVolume( void ) { HIE_tdxHandleToSuperObject h_Child; ACP_tdxIndex xIndex; HIE_M_ForEachChildOf(SECT_hFatherSector, h_Child, xIndex) { if( HIE_fn_bGetMagnetModification( h_Child ) ) MGT_fn_vRecurUpdateBoundingVolumeInHierarchy( h_Child ); } } /*======================================================================================= * Description * * Creation date 01/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vRecurUpdateBoundingVolumeInHierarchy( HIE_tdxHandleToSuperObject h_SuperObject ) { HIE_tdxHandleToSuperObject h_Child; ACP_tdxIndex xIndex; GEO_tdstGeometricObject * hGeometricObject; GEO_tdxHandleToParallelBox hBdVBoxFather; GEO_tdxHandleToBoundingSphere hBdVSphereFather; MTH3D_tdstVector * p_stGlobalMaxBoxPointFather, *p_stGlobalMinBoxPointFather , stSphereCenterFather; ACP_tdxBool bBdVIsABox; MTH_tdxReal xRadiusFather; GEO_tdxHandleToMatrix hGlobalMatrix; if( ! HIE_fn_bGetMagnetModification( h_SuperObject ) ) return; /* current*/ /**/ hGeometricObject = HIE_fn_p_stGetGeometricObjectFromSuperObject( h_SuperObject ); hGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix( h_SuperObject ); bBdVIsABox = HIE_fn_SO_bHasABoxBoundingVolume( h_SuperObject ); /* add local bounding volume*/ /* compute local bounding volume*/ if( bBdVIsABox ) { hBdVBoxFather = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoundingVolume( h_SuperObject ); hBdVSphereFather = NULL; if( hBdVBoxFather ) { p_stGlobalMaxBoxPointFather = GEO_fn_pGetMaxPointOfParallelBox( hBdVBoxFather ); p_stGlobalMinBoxPointFather = GEO_fn_pGetMinPointOfParallelBox( hBdVBoxFather ); if( hGeometricObject ) { MTH3D_tdstVector stLocalMaxBoxPoint, stLocalMinBoxPoint; MTH3D_M_vCopyVector(&stLocalMaxBoxPoint, hGeometricObject->d_stListOfPoints); MTH3D_M_vCopyVector(&stLocalMinBoxPoint, hGeometricObject->d_stListOfPoints); MTH3D_M_vMulMatrixVector( p_stGlobalMaxBoxPointFather, &hGlobalMatrix->stTransformMatrix, &stLocalMaxBoxPoint); MTH3D_M_vMulMatrixVector( p_stGlobalMinBoxPointFather, &hGlobalMatrix->stTransformMatrix, &stLocalMinBoxPoint); GEO_fn_vAddObjectToBox(hGeometricObject, hGlobalMatrix, p_stGlobalMaxBoxPointFather, p_stGlobalMinBoxPointFather); } else { /* init bdv*/ MTH3D_M_vNullVector( p_stGlobalMaxBoxPointFather ); MTH3D_M_vNullVector( p_stGlobalMinBoxPointFather ); } } } else { hBdVSphereFather = (GEO_tdxHandleToBoundingSphere)HIE_fn_hGetSuperObjectBoundingVolume( h_SuperObject ); hBdVBoxFather = NULL; if( hBdVSphereFather ) { MTH3D_M_vCopyVector(&stSphereCenterFather, GEO_fn_pGetCenterPointOfBoundingSphere(hBdVSphereFather)); xRadiusFather = GEO_fn_xGetRadiusOfBoundingSphere(hBdVSphereFather); if( hGeometricObject ) { GEO_fn_vAddObjectToSphere(hGeometricObject, &stSphereCenterFather , & xRadiusFather ); } else { /* init bdv*/ MTH3D_M_vNullVector( & stSphereCenterFather ); xRadiusFather = MTH_C_ZERO; } } } HIE_M_ForEachChildOf(h_SuperObject, h_Child, xIndex) { /* compute bounding volume of child chil*/ MGT_fn_vRecurUpdateBoundingVolumeInHierarchy( h_Child ); /* Now, the bounding volume of a SuperObject doesn't take account the bounding volume of children // recompute Bounding volume with children if( hBdVBoxFather || hBdVSphereFather ) { // take account this bouding volume hLocalMatrix = HIE_fn_hGetSuperObjectMatrix( h_Child ); POS_fn_vGetTranslationVector( hLocalMatrix, &stTranslation ); if( HIE_fn_SO_bHasABoxBoundingVolume( h_Child ) ) { // Child has a Box as Bounding Volume GEO_tdxHandleToParallelBox hBdVBox; MTH3D_tdstVector *p_stGlobalMaxBoxPoint, *p_stGlobalMinBoxPoint; MTH3D_tdstVector stLocalMaxBoxPoint, stLocalMinBoxPoint; hBdVBox = (GEO_tdxHandleToParallelBox)HIE_fn_hGetSuperObjectBoxBoundingVolume( h_Child ); if( hBdVBox ) { p_stGlobalMaxBoxPoint = GEO_fn_pGetMaxPointOfParallelBox( hBdVBox ); p_stGlobalMinBoxPoint = GEO_fn_pGetMinPointOfParallelBox( hBdVBox ); // translate points to father axis MTH3D_M_vAddVector( &stLocalMaxBoxPoint, p_stGlobalMaxBoxPoint, &stTranslation ); MTH3D_M_vAddVector( &stLocalMinBoxPoint, p_stGlobalMinBoxPoint, &stTranslation ); if( bBdVIsABox ) { // Father has a Box as Bounding Volume // Box = Box + Box GEO_fn_vComputeParallelBoxOfTwoBoxes( p_stGlobalMaxBoxPointFather, p_stGlobalMinBoxPointFather, & stLocalMaxBoxPoint, & stLocalMinBoxPoint, p_stGlobalMaxBoxPointFather, p_stGlobalMinBoxPointFather ); } else { // Father has a Sphere as Bounding Volume // Sphere = Sphere + Box MTH3D_tdstVector stSphereCenter; MTH_tdxReal xRadius; GEO_fn_vGetSphereFromParallelBox( & stSphereCenter , &xRadius, & stLocalMaxBoxPoint, & stLocalMinBoxPoint ); GEO_fn_vComputeBoundingSphereOfTwoSpheres( & stSphereCenterFather , & xRadiusFather, & stSphereCenterFather , xRadiusFather, & stSphereCenter , xRadius ); } } } else { // Child has a Sphere as Bounding Volume ACP_tdxHandleOfObject hBdVSphere; MTH3D_tdstVector stSphereCenter; MTH_tdxReal xRadius; hBdVSphere = HIE_fn_hGetSuperObjectBoundingVolume( h_Child ); if( hBdVSphere ) { GEO_fn_vGetSphereFromBoundingVolume( & stSphereCenter , &xRadius , hBdVSphere ); // translate sphere to father axis MTH3D_M_vAddVector( & stSphereCenter, & stSphereCenter, & stTranslation ); if( bBdVIsABox ) { // Father has a Box as Bounding Volume // Box = Box + Sphere COL_fn_vComputeBoundingBoxOfSphereAndBox ( p_stGlobalMinBoxPointFather, p_stGlobalMaxBoxPointFather, & stSphereCenter , xRadius , p_stGlobalMinBoxPointFather, p_stGlobalMaxBoxPointFather ); } else { // Father has a Sphere as Bounding Volume // Sphere = Sphere + Sphere GEO_fn_vComputeBoundingSphereOfTwoSpheres( & stSphereCenterFather , & xRadiusFather, & stSphereCenterFather , xRadiusFather, & stSphereCenter , xRadius ); } } } if( ! bBdVIsABox ) { GEO_fn_vSetSphereToBoundingVolume( & stSphereCenterFather, xRadiusFather, hBdVSphereFather); } } */ } } /*======================================================================================= * Description * * Creation date 01/03/98 * Author Marc Trabucato *=====================================================================================*/ ACP_tdxBool MGT_fn_bComputeInfluenceOnObject( ACP_tdxIndex x_Magnet, MTH_tdxReal xFarFar, GEO_tdstGeometricObject *p_stObject , ACP_tdxIndex *p_x_ModifiedObject , MTH3D_tdstVector *p_stMagnetPosition , HIE_tdxHandleToSuperObject h_SuperObject ) { ACP_tdxIndex xIndexPoint; MTH3D_tdstVector *p_stCurrentPoint, stVect; MTH_tdxReal xDX , xTemp; MGT_tdxHandleToMagnetModification h_MagnetModif; ACP_tdxBool bObjectModified; bObjectModified = FALSE; h_MagnetModif = NULL; for ( xIndexPoint = 0 , p_stCurrentPoint = p_stObject -> d_stListOfPoints ; xIndexPoint < p_stObject -> xNbPoints ; xIndexPoint++, p_stCurrentPoint++ ) { MTH3D_M_vSubVector( &stVect , p_stMagnetPosition, p_stCurrentPoint ); xDX = MTH_M_xSqr( stVect . xX ); if (MTH_M_bLess( xDX, xFarFar )) { xTemp = MTH_M_xSqr( stVect . xY ); xDX = MTH_M_xAdd( xDX, xTemp ); if (MTH_M_bLess( xDX, xFarFar )) { xTemp = MTH_M_xSqr( stVect . xZ ); xDX = MTH_M_xAdd( xDX, xTemp ); if (MTH_M_bLess( xDX, xFarFar )) { /* the point is modified*/ if( h_MagnetModif == NULL ) { /* new object modified*/ if( *p_x_ModifiedObject == MGT_C_xIndexError ) *p_x_ModifiedObject = MGT_fn_xCreateModifiedObject( p_stObject ); h_MagnetModif = MGT_fn_hFindOrAddMagnetModification( x_Magnet , *p_x_ModifiedObject , p_stObject ); if( h_MagnetModif ) { h_MagnetModif -> h_SuperObject = h_SuperObject; h_MagnetModif -> bUsed = TRUE; bObjectModified = TRUE; } } if( h_MagnetModif ) { MGT_M_vSetBit( h_MagnetModif -> d_cFieldBitsModifiedPoints , xIndexPoint ); MGT_M_vSetBit( h_MagnetModif -> d_cFieldBitsInfluencedPoints , xIndexPoint ); } } } } } return bObjectModified; } /*======================================================================================= * Description * * Creation date 02/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vUpdateInfluence( MS_tdxHandleToMSMagnet h_Magnet, ACP_tdxBool bRecompute ) { ACP_tdxIndex xIndex; MGT_tdxHandleToMagnetModification h_MagnetModif; for ( xIndex = 0 ; xIndex < MGT_MAX_NUMBEROF_MODIFIEDOBJECTS ; xIndex++ ) { h_MagnetModif = fn_hMSMagnetGetMagnetModification( h_Magnet ,xIndex ); if( h_MagnetModif ) { MGT_fn_vClearInfluencedPointsOfMagnetModification( h_MagnetModif ); } } } /*======================================================================================= * Description * * Creation date 02/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vSetMagnetModificationUse( MS_tdxHandleToMSMagnet h_Magnet, ACP_tdxBool bUse ) { ACP_tdxIndex xIndex; MGT_tdxHandleToMagnetModification h_MagnetModif; for ( xIndex = 0 ; xIndex < MGT_MAX_NUMBEROF_MODIFIEDOBJECTS ; xIndex++ ) { h_MagnetModif = fn_hMSMagnetGetMagnetModification( h_Magnet ,xIndex ); if( h_MagnetModif ) { h_MagnetModif -> bUsed = bUse; } } } /*======================================================================================= * Description compute the influence of magnet in all static objects * * Creation date 01/03/98 * Author Marc Trabucato *=====================================================================================*/ ACP_tdxBool MGT_fn_bMorphMagnetModif( MGT_tdxHandleToMagnetModification h_MagnetModif ) { ACP_tdxIndex xIndexPoint; GEO_tdstGeometricObject *h_Object; POS_tdxHandleToPosition hMatrix; POS_tdstCompletePosition stMatrix; MTH3D_tdstVector stMagnetLocalPosition, *p_stPosition; MS_tdxHandleToMSMagnet h_Magnet; MTH_tdxReal xNear , xFar , xStrength , xInvFarMinusNear , xInvFrames; ACP_tdxBool bChanged , bUnsetPoint , bMagnetModified , bGrowing; unsigned long ulFrameDuration , *p_ulCurrentDuration; MTH3D_tdstVector *p_stOriginalPosition , *p_stCurrentPosition; MGT_tdxHandleToModifiedObject h_ModifiedObject; char *p_cFieldBitsOfAlreadyInfluencedPoints; /**/ if( ( h_MagnetModif == NULL ) || ! MGT_fn_bIsExistModifiedPointsOnMagnetModification( h_MagnetModif ) ) return FALSE; /**/ h_ModifiedObject = MGT_g_aDEF_hModifiedObjects[ h_MagnetModif -> xIndexOfModifiedObject ]; p_cFieldBitsOfAlreadyInfluencedPoints = h_ModifiedObject -> d_cFieldBitsAlreadyInfluencedPoints; ulFrameDuration = g_stEngineStructure.stEngineTimer.ulUsefulDeltaTime; h_Object = h_ModifiedObject -> p_stMorphedObject; if( MGT_g_aDEF_hActivatedMagnets[ h_MagnetModif -> xIndexOfActivatedMagnet ] == NULL ) { for ( xIndexPoint = 0 , p_ulCurrentDuration = h_MagnetModif -> d_ulCurrentDuration , p_stOriginalPosition = h_ModifiedObject -> d_stOriginalPosition , p_stCurrentPosition = h_Object -> d_stListOfPoints ; xIndexPoint < h_Object -> xNbPoints ; xIndexPoint++, p_ulCurrentDuration++, p_stOriginalPosition++, p_stCurrentPosition++ ) { if( MGT_M_bIsSetBit( h_MagnetModif -> d_cFieldBitsModifiedPoints , xIndexPoint ) /* the point is modified, recompute influence*/ && ! MGT_M_bIsSetBit( h_MagnetModif -> d_cFieldBitsInfluencedPoints , xIndexPoint ) /* the point is currently not influenced by the magnet*/ && ((*p_ulCurrentDuration) > 0) ) { (*p_ulCurrentDuration) -= ( (*p_ulCurrentDuration) >= ulFrameDuration ) ? ulFrameDuration : (*p_ulCurrentDuration); MGT_fn_vComputePreviousPosition( h_MagnetModif, xIndexPoint, p_cFieldBitsOfAlreadyInfluencedPoints, (*p_ulCurrentDuration) , ulFrameDuration , p_stOriginalPosition , p_stCurrentPosition ); bChanged = TRUE; if( (*p_ulCurrentDuration) == 0 ) { MGT_M_vUnSetBit( h_MagnetModif -> d_cFieldBitsModifiedPoints , xIndexPoint ); bUnsetPoint = TRUE; } } } } else if( h_Magnet = M_GetMSHandle( MGT_g_aDEF_hActivatedMagnets[ h_MagnetModif -> xIndexOfActivatedMagnet ], MSMagnet)) /* volontary assignment*/ { bGrowing = FALSE; xFar = fn_xMSMagnetGetFar(h_Magnet); xNear = fn_xMSMagnetGetNear(h_Magnet); xStrength = fn_xMSMagnetGetStrength(h_Magnet); xInvFarMinusNear = MTH_M_xSub( xFar , xNear ); bMagnetModified = fn_bMSMagnetIsNearFarModified (h_Magnet) || fn_bMSMagnetIsStrengthModified(h_Magnet) || fn_bMSMagnetIsPositionModified(h_Magnet); if( MTH_M_bDifferentZero( xInvFarMinusNear ) ) xInvFarMinusNear = MTH_M_xInv( xInvFarMinusNear ); else xInvFarMinusNear = MTH_C_ONE; xInvFrames = MTH_M_xInv( (float)(h_Magnet -> ulDuration) ); hMatrix = HIE_fn_hGetSuperObjectGlobalMatrix( h_MagnetModif -> h_SuperObject ); POS_fn_vInvertMatrix( & stMatrix , hMatrix ); p_stPosition = fn_hMSMagnetGetPosition( h_Magnet ); POS_fn_vMulMatrixVertex( & stMagnetLocalPosition , & stMatrix , p_stPosition ); h_Object = h_ModifiedObject -> p_stMorphedObject; bChanged = FALSE; bUnsetPoint = FALSE; for ( xIndexPoint = 0 , p_ulCurrentDuration = h_MagnetModif -> d_ulCurrentDuration , p_stOriginalPosition = h_ModifiedObject -> d_stOriginalPosition , p_stCurrentPosition = h_Object -> d_stListOfPoints ; xIndexPoint < h_Object -> xNbPoints ; xIndexPoint++, p_ulCurrentDuration++, p_stOriginalPosition++, p_stCurrentPosition++ ) { if( MGT_M_bIsSetBit( h_MagnetModif -> d_cFieldBitsModifiedPoints , xIndexPoint ) ) { /* the point is modified, recompute influence*/ if( MGT_M_bIsSetBit( h_MagnetModif -> d_cFieldBitsInfluencedPoints , xIndexPoint ) ) { /* the point is currently influenced by the magnet*/ if( ((*p_ulCurrentDuration) < h_Magnet -> ulDuration) || bMagnetModified ) { (*p_ulCurrentDuration) += ulFrameDuration; if( (*p_ulCurrentDuration) > h_Magnet -> ulDuration ) { (*p_ulCurrentDuration) = h_Magnet -> ulDuration; } MGT_fn_vComputeNewPosition( h_MagnetModif, xIndexPoint, p_cFieldBitsOfAlreadyInfluencedPoints, (*p_ulCurrentDuration) , p_stOriginalPosition , p_stCurrentPosition , p_stPosition , xNear , xStrength , xInvFarMinusNear , xInvFrames); bChanged = TRUE; } } else { /* the point is currently not influenced by the magnet*/ if( (*p_ulCurrentDuration) > 0 ) { (*p_ulCurrentDuration) -= ( (*p_ulCurrentDuration) >= ulFrameDuration ) ? ulFrameDuration : (*p_ulCurrentDuration); MGT_fn_vComputePreviousPosition( h_MagnetModif, xIndexPoint, p_cFieldBitsOfAlreadyInfluencedPoints, (*p_ulCurrentDuration) , ulFrameDuration , p_stOriginalPosition , p_stCurrentPosition ); bChanged = TRUE; if( (*p_ulCurrentDuration) == 0 ) { MGT_M_vUnSetBit( h_MagnetModif -> d_cFieldBitsModifiedPoints , xIndexPoint ); bUnsetPoint = TRUE; } } } } } } else return FALSE; if( bUnsetPoint && ! MGT_fn_bIsExistModifiedPointsOnMagnetModification( h_MagnetModif ) ) { MGT_fn_vDeleteMagnetModification( h_MagnetModif ); } return bChanged; } /*======================================================================================= * Description * * Creation date 02/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vComputeNewPosition( MGT_tdxHandleToMagnetModification h_MagnetModif , ACP_tdxIndex xIndexPoint, char *p_cFieldBitAlreadyInfluenced, unsigned long ulCurrentDuration , MTH3D_tdstVector *p_stInitialPosition , MTH3D_tdstVector *p_stCurrentPosition , MTH3D_tdstVector *p_stMagnetPosition , MTH_tdxReal xNear , MTH_tdxReal xStrength , MTH_tdxReal xInvFarMinusNear , MTH_tdxReal xInvFrames) { MTH_tdxReal xDistance , xFrameRatio, xRatio; MTH3D_tdstVector stVect , stVectA , stVectB ; xFrameRatio = MTH_M_xMul( (MTH_tdxReal)ulCurrentDuration , xInvFrames ) ; MTH3D_M_vSubVector( & stVect , p_stMagnetPosition, p_stInitialPosition ); xDistance = MTH3D_M_xNormVector( & stVect ); MTH3D_M_vNormalizeVector( & stVectB, & stVect ); if( MTH_M_bLess( xDistance , xNear) ) { if( MTH_M_bLess( xDistance , xStrength ) ) xRatio = MTH_M_xMul( xFrameRatio , xDistance ); else xRatio = MTH_M_xMul( xFrameRatio , xStrength ); } else { xRatio = MTH_M_xSub( xDistance, xNear ); xRatio = MTH_M_xMul( xRatio, xInvFarMinusNear ); xRatio = MTH_M_xSub( MTH_C_ONE, xRatio ); xRatio = MTH_M_xMul( xRatio, xStrength ); xRatio = MTH_M_xMul( xRatio, xFrameRatio ); } MTH3D_M_vMulScalarVector( & stVectA, xRatio, & stVectB); if( MGT_M_bIsSetBit( p_cFieldBitAlreadyInfluenced , xIndexPoint ) ) { /* the point isn't already influenced by another magnet, uses the initial value*/ MTH3D_M_vAddVector ( & stVectB , p_stInitialPosition , & stVectA ); MTH3D_M_vMiddleVector( p_stCurrentPosition , p_stCurrentPosition, & stVectB ); } else { /* the point is already influenced by another magnet, uses the modified value*/ MTH3D_M_vAddVector( p_stCurrentPosition , p_stInitialPosition , & stVectA ); MGT_M_vSetBit( p_cFieldBitAlreadyInfluenced , xIndexPoint ); } } /*======================================================================================= * Description * * Creation date 02/03/98 * Author Marc Trabucato *=====================================================================================*/ void MGT_fn_vComputePreviousPosition( MGT_tdxHandleToMagnetModification h_MagnetModif , ACP_tdxIndex xIndexPoint, char *p_cFieldBitAlreadyInfluenced, unsigned long ulCurrentDuration , unsigned long ulDecreaseDuration , MTH3D_tdstVector *p_stInitialPosition , MTH3D_tdstVector *p_stCurrentPosition) { MTH_tdxReal xFrameRatio; MTH3D_tdstVector stVect , stVectA , stVectB ; /* compute previous deformation*/ MTH3D_M_vSubVector( & stVect, p_stCurrentPosition, p_stInitialPosition ); /* compute previous to current ratio*/ xFrameRatio = MTH_M_xFloatToReal( ((float)ulCurrentDuration) / ((float)(ulCurrentDuration+ulDecreaseDuration)) ); /* compute current deformation*/ MTH3D_M_vMulScalarVector( & stVectA, xFrameRatio, & stVect ); if( MGT_M_bIsSetBit( p_cFieldBitAlreadyInfluenced , xIndexPoint ) ) { /* the point is already influenced by another magnet, uses the initial value*/ MTH3D_M_vAddVector ( & stVectB , p_stInitialPosition , & stVectA ); MTH3D_M_vMiddleVector( p_stCurrentPosition , p_stCurrentPosition, & stVectB ); } else { /* the point isn't already influenced by another magnet, uses the modified value*/ MTH3D_M_vAddVector( p_stCurrentPosition , p_stInitialPosition , & stVectA ); MGT_M_vSetBit( p_cFieldBitAlreadyInfluenced , xIndexPoint ); } }