/* ======================================================================================= Name : VisuaSet.c Author : philippe vimont Description : manage visual set structure ======================================================================================= */ #include "Gli_st.h" #include "GLI_Defn.h" #include "VisuS_st.h" #include "light_st.h" #include "PvObj_st.h" #include "matstack.h" #include "VisuSet.h" #include "proj.h" #include "linear.h" #include "vpt3D.h" #include "camera.h" #include "Object.h" #include "pvobj_st.h" #include "PCS.h" #include "PO.h" #include "IPO.h" #include "ISI.h" //#include "light.h" /* See "ACP_Visualsets.DOC" for more */ #ifdef __cplusplus extern "C" { #endif /* ======================================================================================= externals ======================================================================================= */ extern GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BIG_GLOBALS; /* ======================================================================================= Creation ======================================================================================= */ /* ---------------------------------------------------------------------------------------- Description : create a visual set lNbLOD -> number of Level Of Detail ---------------------------------------------------------------------------------------- */ GEO_tdstVisualSet *GLI_p_stCreateVisualSet( long lNbLOD ) { GEO_tdstVisualSet *p_stLocalVS; ACP_tdxIndex xLodCounter; MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeVisualSet , NULL); GEO_M_CPAMalloc(p_stLocalVS ,GEO_tdstVisualSet * ,sizeof ( GEO_tdstVisualSet ) ,E_uwGEONotEnoughtMemory ); if ( p_stLocalVS == NULL) return NULL; MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeVisualSet , NULL); GEO_M_CPAMalloc(p_stLocalVS -> d_xThresholdsTable ,MTH_tdxReal *,sizeof ( MTH_tdxReal ) * lNbLOD,E_uwGEONotEnoughtMemory ); if ( p_stLocalVS -> d_xThresholdsTable == NULL) return NULL; MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeVisualSet , NULL); GEO_M_CPAMalloc(p_stLocalVS -> d_p_stLodDefinitions ,GEO_tdstGeometricObject ** ,sizeof ( GEO_tdstGeometricObject * ) * lNbLOD,E_uwGEONotEnoughtMemory ); if ( p_stLocalVS -> d_p_stLodDefinitions == NULL) return NULL; p_stLocalVS -> xNbLodDefinitions = (ACP_tdxIndex)lNbLOD; for (xLodCounter = 0; xLodCounter < lNbLOD; xLodCounter ++) { p_stLocalVS -> d_xThresholdsTable[xLodCounter] = 0.0; p_stLocalVS -> d_p_stLodDefinitions[xLodCounter] = NULL; } return (p_stLocalVS); }; /* ---------------------------------------------------------------------------------------- Description : create a visual set in the TMP memory block lNbLOD -> number of Level Of Detail ---------------------------------------------------------------------------------------- */ GEO_tdstVisualSet *GLI_p_stCreateTMPVisualSet ( long lNbLOD) { GEO_tdstVisualSet *p_stLocalVS; ACP_tdxIndex xLodCounter; MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeVisualSet , NULL); GEO_M_TMPMalloc(p_stLocalVS ,GEO_tdstVisualSet * ,sizeof ( GEO_tdstVisualSet ) ); if ( p_stLocalVS == NULL) return(NULL); MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeVisualSet , NULL); GEO_M_TMPMalloc(p_stLocalVS -> d_xThresholdsTable ,MTH_tdxReal *,sizeof ( MTH_tdxReal ) * lNbLOD ); if ( p_stLocalVS -> d_xThresholdsTable == NULL) return(NULL); MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeVisualSet , NULL); GEO_M_TMPMalloc(p_stLocalVS -> d_p_stLodDefinitions ,GEO_tdstGeometricObject ** ,sizeof ( GEO_tdstGeometricObject * ) * lNbLOD ); if ( p_stLocalVS -> d_p_stLodDefinitions == NULL) return(NULL); p_stLocalVS -> xNbLodDefinitions = (ACP_tdxIndex)lNbLOD; for (xLodCounter = 0; xLodCounter < lNbLOD; xLodCounter ++) { p_stLocalVS -> d_xThresholdsTable[xLodCounter] = 0.0; p_stLocalVS -> d_p_stLodDefinitions[xLodCounter] = NULL; } return (p_stLocalVS); }; /* ======================================================================================= Access functions ======================================================================================= */ /* ---------------------------------------------------------------------------------------- Description : set / get a LOD of a visual set object ---------------------------------------------------------------------------------------- */ void GLI_vSetVisualSetLOD ( GEO_tdstVisualSet *p_stVisualSet, long lNumberOfLodToSet, MTH_tdxReal xThreshold, GEO_tdstGeometricObject *p_stObject) { if (lNumberOfLodToSet < p_stVisualSet->xNbLodDefinitions) { p_stVisualSet -> d_xThresholdsTable[lNumberOfLodToSet] = xThreshold; p_stVisualSet -> d_p_stLodDefinitions[lNumberOfLodToSet] = p_stObject; } } void GLI_vGetVisualSetLOD ( GEO_tdstVisualSet *p_stVisualSet, long lNumberOfLodToGet, MTH_tdxReal *p_xThreshold, GEO_tdstGeometricObject **h_stObject ) { if (lNumberOfLodToGet < p_stVisualSet -> xNbLodDefinitions) { *p_xThreshold = p_stVisualSet -> d_xThresholdsTable[lNumberOfLodToGet] ; *h_stObject = p_stVisualSet -> d_p_stLodDefinitions[lNumberOfLodToGet] ; } } GEO_tdstGeometricObject *GLI_hGetVisualSetGeometricForADistance( GEO_tdstVisualSet *p_stVSE, MTH_tdxReal xThreshold ) { long lLod; for (lLod = 0; lLod < p_stVSE->xNbLodDefinitions - 1; lLod ++) { if (p_stVSE->d_xThresholdsTable[ lLod + 1 ] > xThreshold) break; } return (p_stVSE->d_p_stLodDefinitions[lLod]); } /* ---------------------------------------------------------------------------------------- Description : get number of LOD ---------------------------------------------------------------------------------------- */ long GLI_lGetVisualSetNumbertOfLOD ( GEO_tdstVisualSet *p_stVisualSet ) { return (p_stVisualSet->xNbLodDefinitions); } /* ======================================================================================= Display ======================================================================================= */ /* ---------------------------------------------------------------------------------------- Description : send object to display, with distance to camera computation, choice of LOD, fog check, and RLI ---------------------------------------------------------------------------------------- */ void GLI_lSendVisualSetToViewportWithRLI2 ( struct GLD_tdstViewportAttributes_ *p_stVpt , GEO_tdstVisualSet *p_stVisualSet, MTH3D_tdstVector *p_xCenter, long lDrawModeMask, ACP_tdxHandleToRadiosity hISI ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ ACP_tdxIndex lNumberOfLodToSend; MTH_tdxReal xDistance; MTH3D_tdstVector stLocal; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_xSetRLIForNextObjectToDraw ( NULL , NULL ); /* if visualset has only one LOD, and no fog or infinite fog distance, then display the LOD 0 */ if (p_stVisualSet -> xNbLodDefinitions == 1 && ( GLI_BIG_GLOBALS->xFogIsOn == 0 || GLI_BIG_GLOBALS->p_stActiveFog->xInfinite >= 50000.0f ) ) { lNumberOfLodToSend = 0; } else { /* * compute distance from camera to center of object */ POS_fn_vMulMatrixVertex ( &stLocal, g_p_stCurrentMatrix,p_xCenter ); POS_fn_vMulMatrixVertex ( &stLocal, &(( GLI_tdstSpecificAttributesFor3D *)p_stVpt->p_vSpecificToXD)->p_stCam->stMatrix , &stLocal); xDistance = MTH3D_M_xNormVector( &stLocal ) ; /* if fog is on and object is hidden by fog, then no display */ if (GLI_BIG_GLOBALS->xFogIsOn && xDistance >= GLI_BIG_GLOBALS->p_stActiveFog->xInfinite) return; /* find number of LOD to use according to distance */ for (lNumberOfLodToSend = 0; lNumberOfLodToSend < p_stVisualSet -> xNbLodDefinitions - 1; lNumberOfLodToSend ++) { if (p_stVisualSet -> d_xThresholdsTable [ lNumberOfLodToSend+1 ] > xDistance) break; } } /* look if it exist a RLI for the chosen LOD, if yes, set it */ if ((hISI) && (lNumberOfLodToSend<=ISI_fn_xGetNbLOD(hISI))) { GLI_xSetRLIForNextObjectToDraw (ISI_fn_dGetVertexRLILOD(hISI,lNumberOfLodToSend), p_stVisualSet -> d_p_stLodDefinitions[lNumberOfLodToSend]); } /* look if it exist a Geometric Object for the chosen LOD (???), if yes, send it to display */ if (p_stVisualSet -> d_p_stLodDefinitions[lNumberOfLodToSend] != NULL) { GLI_xSendObjectToViewportWithLights ( p_stVpt ,p_stVisualSet -> d_p_stLodDefinitions[lNumberOfLodToSend],lDrawModeMask); } } /* ---------------------------------------------------------------------------------------- Description : send object to display, with distance to camera computation, choice of LOD, fog check, but no RLI ---------------------------------------------------------------------------------------- */ void GLI_lSendVisualSetToViewportBV2( struct GLD_tdstViewportAttributes_ *p_stVpt, GEO_tdstVisualSet *p_stVisualSet, MTH3D_tdstVector *p_xCenter, MTH_tdxReal xRadiusOfSphere, long lDrawModeMask) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ long lNumberOfLodToSend; MTH3D_tdstVector stLocal; MTH_tdxReal xDistance; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_xSetRLIForNextObjectToDraw ( NULL , NULL ); /* if visualset has only one LOD, and no fog or infinite fog distance, then display the LOD 0 */ if (p_stVisualSet -> xNbLodDefinitions == 1 && ( GLI_BIG_GLOBALS->xFogIsOn == 0 || GLI_BIG_GLOBALS->p_stActiveFog->xInfinite >= 50000.0f ) ) { lNumberOfLodToSend = 0; } else { /* * compute distance from camera to center of object */ POS_fn_vMulMatrixVertex ( &stLocal, g_p_stCurrentMatrix,p_xCenter ); POS_fn_vMulMatrixVertex ( &stLocal, &(( GLI_tdstSpecificAttributesFor3D *)p_stVpt->p_vSpecificToXD)->p_stCam->stMatrix , &stLocal); xDistance = MTH3D_M_xNormVector( &stLocal ) ; /* if fog is on and object is hidden by fog, then no display */ if (GLI_BIG_GLOBALS->xFogIsOn && xDistance >= GLI_BIG_GLOBALS->p_stActiveFog->xInfinite) return; /* find number of LOD to use according to distance */ for (lNumberOfLodToSend = 0; lNumberOfLodToSend < p_stVisualSet -> xNbLodDefinitions - 1; lNumberOfLodToSend ++) { if (p_stVisualSet -> d_xThresholdsTable [ lNumberOfLodToSend+1 ] > xDistance) break; } } /* look if it exist a Geometric Object for the chosen LOD (???), if yes, send it to display */ if (p_stVisualSet -> d_p_stLodDefinitions[lNumberOfLodToSend] != NULL) { GLI_xSendObjectToViewportWithLights (p_stVpt, p_stVisualSet->d_p_stLodDefinitions[lNumberOfLodToSend], lDrawModeMask); } } /* ---------------------------------------------------------------------------------------- Description : send object to display, with absolute distance, choice of LOD ---------------------------------------------------------------------------------------- */ void GLI_lSendVisualSetToViewport( struct GLD_tdstViewportAttributes_ *p_stVpt, GEO_tdstVisualSet *p_stVisualSet, MTH_tdxReal xDistance, long lDrawModeMask) { long lNumberOfLodToSend; /* reset RLI : no RLI for this function */ GLI_xSetRLIForNextObjectToDraw ( NULL , NULL ); /* find the right LOD for the given dstance */ for (lNumberOfLodToSend = 0; lNumberOfLodToSend < p_stVisualSet -> xNbLodDefinitions - 1; lNumberOfLodToSend ++) { if (p_stVisualSet -> d_xThresholdsTable [ lNumberOfLodToSend+1 ] > xDistance) break; } /* LOD found, check if exist and send to drawing */ if (p_stVisualSet -> d_p_stLodDefinitions[lNumberOfLodToSend] != NULL) { GLI_xSendObjectToViewportWithLights ( p_stVpt, p_stVisualSet -> d_p_stLodDefinitions[lNumberOfLodToSend], lDrawModeMask); } } /* ---------------------------------------------------------------------------------------- Description : send object to display, with distance to camera computation, choice of LOD ---------------------------------------------------------------------------------------- */ void GLI_lSendVisualSetToViewport2( struct GLD_tdstViewportAttributes_ *p_stVpt, GEO_tdstVisualSet *p_stVisualSet, MTH3D_tdstVector *p_xCenter, long lDrawModeMask) { MTH3D_tdstVector stLocal; GLI_tdstSpecificAttributesFor3D *p_stSpecifAttrib3D; /* put object center in camera axis system (p_xCenter is in local coordinates system */ p_stSpecifAttrib3D = ( GLI_tdstSpecificAttributesFor3D *)p_stVpt->p_vSpecificToXD; /* put center in world axis system */ POS_fn_vMulMatrixVertex ( &stLocal, g_p_stCurrentMatrix,p_xCenter ); /* and in camera axis system */ POS_fn_vMulMatrixVertex ( &stLocal, &(( GLI_tdstSpecificAttributesFor3D *)p_stVpt->p_vSpecificToXD)->p_stCam->stMatrix , &stLocal); /* and call display function with right distance */ GLI_lSendVisualSetToViewport( p_stVpt ,p_stVisualSet ,MTH3D_M_xNormVector( &stLocal ) ,lDrawModeMask); } /* ======================================================================================= RLI ======================================================================================= */ /* ---------------------------------------------------------------------------------------- Description : return one of RLI Table ---------------------------------------------------------------------------------------- */ ACP_tdxHandleToRadiosity GLI_hGetRLI ( GEO_tdxHandleToVisualSet hVisualSet, unsigned char ucIndex ) { if ( ucIndex < hVisualSet->lNumberOfRLI ) return hVisualSet->d_hRLI[ucIndex] ; return NULL; } /* ---------------------------------------------------------------------------------------- Description : compute a new RLI table that is a blend of two other table ---------------------------------------------------------------------------------------- */ ACP_tdxHandleToRadiosity GLI_hComputeBlendRLI (GEO_tdxHandleToVisualSet hVisualSet, unsigned char ucIndex1, unsigned char ucIndex2, ACP_tdxIndex xNumISILOD, MTH_tdxReal xPercent) { if ( ucIndex1 < hVisualSet->lNumberOfRLI && ucIndex2 < hVisualSet->lNumberOfRLI ) { return ISI_hComputeBlendRLI ( hVisualSet->d_hRLI[ucIndex1], hVisualSet->d_hRLI[ucIndex2], xNumISILOD, xPercent ); } return NULL; } /* ---------------------------------------------------------------------------------------- Description : Set RLI table of a visual set ---------------------------------------------------------------------------------------- */ void GLI_vVisualSetSetRLITable (GEO_tdxHandleToVisualSet hVisualSet, ACP_tdxHandleToRadiosity *d_hRLI, long lNumberOfTable) { if ( d_hRLI ) { hVisualSet->d_hRLI = d_hRLI ; hVisualSet->lNumberOfRLI = lNumberOfTable ; } } /* ---------------------------------------------------------------------------------------- Description : Load the RLI section of the VSE of a charactere ---------------------------------------------------------------------------------------- */ ACP_tdxHandleToRadiosity *GLI_vVisualSetLoadRLI (char *szSection, long *lNumberOfTable) { ACP_tdxHandleToRadiosity *d_hRLI ; SCR_tdst_Cxt_Values *p_stVal=NULL; p_stVal = SCR_fnp_st_RdL0_AnalyseSection(szSection, SCR_CDF_uw_Anl_Normal); d_hRLI = (ACP_tdxHandleToRadiosity *)SCR_M_ul_RdL0_ExtractLongValue(p_stVal,0); *lNumberOfTable = SCR_M_ul_RdL0_ExtractLongValue(p_stVal,1); return (d_hRLI); } /* ---------------------------------------------------------------------------------------- Description : script callback for RLI section ---------------------------------------------------------------------------------------- */ SCR_tde_Anl_ReturnValue GLI_fn_xLoadRLI(SCR_tdst_File_Description *p_fFile, char *szAction, char *szParams[], SCR_tde_Anl_Action cType) { long lNumberOfRLI ; ACP_tdxHandleToRadiosity *d_hRLI; switch (cType) { case SCR_EA_Anl_BeginSection: lNumberOfRLI = atol(szParams[1]) ; MMG_fn_vAddMemoryInfo (MMG_C_lTypeGLI , MMG_C_lSubTypeRLI , NULL); GEO_M_CPAMalloc(d_hRLI ,ACP_tdxHandleToRadiosity * ,sizeof ( ACP_tdxHandleToRadiosity ) ,E_uwGEONotEnoughtMemory ); SCR_M_RdL0_SetSectionLong(0,0,(long)d_hRLI); SCR_M_RdL0_SetSectionLong(0,1,lNumberOfRLI); SCR_M_RdL0_SetContextLong(0,0,(long)d_hRLI); break; } return SCR_ERV_Anl_NormalReturn; } #ifdef __cplusplus } /*extern "C"*/ #endif