/* ======================================================================================= Name : Culling.c Author : vincent lhullier Date :15/06/98 Description : culling functions ======================================================================================= */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #include "acp_base.h" #include "Geo.h" #include "Gli.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* ======================================================================================= External function prototype ======================================================================================= */ /* * retrieve current matrix for function that avoid MulMatrixMatrix */ extern POS_tdstCompletePosition *HIE_hRetrieveCurrentMatrix(); #ifdef __cplusplus extern "C" { #endif /* ======================================================================================= static global var ======================================================================================= */ MTH_tdxReal GEO_g_xZFar = 0.0f; MTH_tdxReal GEO_g_xZFarTransparencyZone = 10.0f; MTH_tdxReal GEO_g_xOoZFarTransparencyZone = 0.1f; MTH_tdxReal GEO_g_xZFarTransparencyLevel; static MTH3D_tdstVector gs_stGlobalNormPlaneLeft; static MTH3D_tdstVector gs_stGlobalNormPlaneRight; static MTH3D_tdstVector gs_stGlobalNormPlaneUp; static MTH3D_tdstVector gs_stGlobalNormPlaneDown; static MTH3D_tdstVector gs_stGlobalNormPlaneNear; static MTH3D_tdstVector gs_stCameraPosInGlobal; /* ======================================================================================= Access function ======================================================================================= */ MTH_tdxReal GEO_xGetZFar( void ) { return GEO_g_xZFar; } void GEO_vSetZFar( MTH_tdxReal _xZ ) { GEO_g_xZFar = _xZ; } MTH_tdxReal GEO_xGetZFarTransparencyZone( void ) { return GEO_g_xZFarTransparencyZone; } void GEO_vSetZFarTransparencyZone( MTH_tdxReal _xZ ) { GEO_g_xZFarTransparencyZone = _xZ; if (_xZ) GEO_g_xOoZFarTransparencyZone = MTH_M_xInv( _xZ ); } MTH_tdxReal GEO_xGetZFarTransparencyLevel( void ) { return GEO_g_xZFarTransparencyLevel; } /* ======================================================================================= Local functions ======================================================================================= */ /**********************************************************************************************/ /* local function !!*/ /* use GEO_lCullingSphere or GEO_lCullingSphereNoMMM instead !!*/ /**/ /* Name: GEO_lMainCullingSphere*/ /* Goal: Return 1 if the sphere is visible with the viewport's camera, 0 else.*/ /* Code: Philippe Vimont*/ /* modif : Fabien Bole-Feysot*/ /* entry : the viewport to test*/ /* the center of the sphere, in object's local axis system*/ /* the radius of the sphere, not including any scale or so*/ /* the matrix that must be used to compute coords in the camera axis system*/ /* the matrix that must be used to compute coords in the world axis system*/ /**********************************************************************************************/ long GEO_lMainCullingSphere ( GLD_tdstViewportAttributes *p_stVpt , MTH3D_tdstVector *p_stShereCenter , MTH_tdxReal xRadius, POS_tdstCompletePosition *p_stMatrix, POS_tdstCompletePosition *p_stMatrixW, long _lCullingResult ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_tdstSpecificAttributesFor3D *p_stSpecifAttrib3D; /* XB 05/05/99 */ /* MTH3D_tdstVector stMin,stMax,stMinG,stMaxG; */ /* End XB 05/05/99 */ MTH3D_tdstVector stCenter; GLI_tdxHandleToCamera hCamera; MTH_tdxReal xDotProduct; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ if (!POS_fn_ulIsNotScaledMatrix ( p_stMatrix )) { /* the matrix is scaled...*/ /* so compute a parallel box around the sphere (in global coords) and call the cullingbox function*/ /* stMin.xX = p_stShereCenter -> xX - xRadius; stMin.xY = p_stShereCenter -> xY - xRadius; stMin.xZ = p_stShereCenter -> xZ - xRadius; stMax.xX = p_stShereCenter -> xX + xRadius; stMax.xY = p_stShereCenter -> xY + xRadius; stMax.xZ = p_stShereCenter -> xZ + xRadius; */ /* here, stMin & stMax are not scaled and in local coordinates system compute them in global coordinates*/ /* POS_fn_vMulMatrixVertex (&stMinG,p_stMatrixW,&stMin); POS_fn_vMulMatrixVertex (&stMaxG,p_stMatrixW,&stMax); */ /* and cull this parallel box*/ /* return GEO_lCullingBox (p_stVpt,&stMinG,&stMaxG, _lCullingResult); */ /* the previous box isn't ligned in global axis system */ xRadius = MTH_M_xMul(xRadius,POS_fn_xGetMaxScale(p_stMatrix)); } /* the matrix is not scaled, so perform plan rejection for sphere*/ p_stSpecifAttrib3D = (GLI_tdstSpecificAttributesFor3D *) p_stVpt -> p_vSpecificToXD; hCamera = p_stSpecifAttrib3D->p_stCam; /* compute sphere center in camera coords*/ POS_fn_vMulMatrixVertex (&stCenter,p_stMatrix,p_stShereCenter); _lCullingResult |= GEO_C_lCullingIntersect; /* if the culling result against the near border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingNear) ) { if ( stCenter.xZ + xRadius < hCamera->xNear ) { return GEO_C_lCullingOut; } xDotProduct = MTH_M_xSub(stCenter.xZ, xRadius); /* if all points are beyond the near plane, the sphere is inside relatively to this plane*/ if ( MTH_M_bGreater(xDotProduct, hCamera->xNear) ) { _lCullingResult |= GEO_C_lCullingNear; } } /* if the culling result against the far border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingFar) ) { if ( MTH_M_bDifferentZero(GEO_g_xZFar) ) { if ( xDotProduct > GEO_g_xZFar ) { GEO_g_xZFarTransparencyLevel = MTH_C_ZERO; return GEO_C_lCullingOut; } if ( xDotProduct > GEO_g_xZFar - GEO_g_xZFarTransparencyZone ) { GEO_g_xZFarTransparencyLevel = MTH_C_ONE - ((stCenter.xZ - xRadius - GEO_g_xZFar + GEO_g_xZFarTransparencyZone) * GEO_g_xOoZFarTransparencyZone); } else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; /* if all points are in front of the far plane, the sphere is inside relatively to this plane*/ _lCullingResult |= GEO_C_lCullingFar; } } else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; /* if all points are in front of the far plane, the sphere is inside relatively to this plane*/ _lCullingResult |= GEO_C_lCullingFar; } } else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; } /* if the culling result against the left border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingLeft) ) { xDotProduct = MTH3D_M_xDotProductVector(&stCenter, &hCamera->stNormPlaneRight); /*left and right plane normal car names are inversed!*/ if (xDotProduct > xRadius + hCamera->xDistPlaneLeft) { return GEO_C_lCullingOut; } if (xDotProduct < hCamera->xDistPlaneLeft - xRadius) { _lCullingResult |= GEO_C_lCullingLeft; } } /* if the culling result against the right border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingRight) ) { xDotProduct = MTH3D_M_xDotProductVector(&stCenter, &hCamera->stNormPlaneLeft); /*left and right plane normal car names are inversed!*/ if (xDotProduct > xRadius + hCamera->xDistPlaneRight) { return GEO_C_lCullingOut; } if (xDotProduct < hCamera->xDistPlaneRight - xRadius) { _lCullingResult |= GEO_C_lCullingRight; } } /* if the culling result against the up border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingUp) ) { xDotProduct = MTH3D_M_xDotProductVector(&stCenter, &hCamera->stNormPlaneUp); if (xDotProduct > xRadius + hCamera->xDistPlaneUp) { return GEO_C_lCullingOut; } if (xDotProduct < hCamera->xDistPlaneUp - xRadius) { _lCullingResult |= GEO_C_lCullingUp; } } /* if the culling result against the down border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingDown) ) { xDotProduct = MTH3D_M_xDotProductVector(&stCenter, &hCamera->stNormPlaneDown); if (xDotProduct > xRadius + hCamera->xDistPlaneDown) { return GEO_C_lCullingOut; } if (xDotProduct < hCamera->xDistPlaneDown - xRadius) { _lCullingResult |= GEO_C_lCullingDown; } } return _lCullingResult; } /* ======================================================================================= Exported functions ======================================================================================= */ /* *************************************************************************************** Name: GLI_fn_vComputeCameraParametersForCulling Goal: pre compute camera parameters for faster culling compute clipping plane normal in global system axis to avoid object transformation from global to camera system axis Code: *************************************************************************************** */ void GEO_fn_vComputeCameraParametersForCulling( GLD_tdstViewportAttributes *p_stVpt, MTH_tdxReal _xZFar ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ POS_tdstCompletePosition stMatrixInverse; register GLI_tdxHandleToCamera hCamera; register MTH3D_tdstMatrix *hInvTransformMatrix; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ hCamera = ((GLI_tdstSpecificAttributesFor3D *) p_stVpt->p_vSpecificToXD)->p_stCam; /* STM - camera matrix should _never_ be scaled*/ assert (hCamera->stMatrix.ulType <= POS_C_ulRotationMatrixFlag); /*invert the camera's position and get an handle on the rotation*/ POS_fn_vInvertIsoMatrix( &stMatrixInverse, &hCamera->stMatrix); hInvTransformMatrix = &stMatrixInverse.stTransformMatrix; /*near plane (we use stCameraPosInGlobal as a temporary vector...)*/ MTH3D_M_vSetVectorElements( &gs_stCameraPosInGlobal, MTH_C_ZERO, MTH_C_ZERO, MTH_C_MinusONE ); MTH3D_M_vMulMatrixVectorWithoutBuffer( &gs_stGlobalNormPlaneNear, hInvTransformMatrix, &gs_stCameraPosInGlobal ); /*position*/ MTH3D_M_vCopyVector( &gs_stCameraPosInGlobal, &stMatrixInverse.stTranslationVector ); /*left plane (the relative left and right planes are inversed in the camera...)*/ MTH3D_M_vMulMatrixVectorWithoutBuffer( &gs_stGlobalNormPlaneLeft, hInvTransformMatrix, &hCamera->stNormPlaneRight ); /*right plane (the relative left and right planes are inversed in the camera...)*/ MTH3D_M_vMulMatrixVectorWithoutBuffer( &gs_stGlobalNormPlaneRight, hInvTransformMatrix, &hCamera->stNormPlaneLeft ); /*upper plane*/ MTH3D_M_vMulMatrixVectorWithoutBuffer( &gs_stGlobalNormPlaneUp, hInvTransformMatrix, &hCamera->stNormPlaneUp ); /*lower plane*/ MTH3D_M_vMulMatrixVectorWithoutBuffer( &gs_stGlobalNormPlaneDown, hInvTransformMatrix, &hCamera->stNormPlaneDown ); GEO_g_xZFar = _xZFar; } /**********************************************************************************************/ /* Name: GEO_lCullingGlobalSphere*/ /* Goal: Return 1 if the sphere is visible with the viewport's camera, 0 else.*/ /* Code: Philippe Vimont*/ /* modif : Fabien Bole-Feysot*/ /* entry : the viewport to test*/ /* the center of the sphere, in global axis system*/ /* the radius of the sphere, not including any scale or so*/ /**/ /* if you plan to use this function during the drawing process, then look at the*/ /* GEO_lCullingSphereNoMMM below, which is faster.*/ /**********************************************************************************************/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ long GEO_lCullingGlobalSphere ( GLD_tdstViewportAttributes *_p_stVpt, MTH3D_tdstVector *_p_stSphereCenter, MTH_tdxReal _xRadius, long _lCullingResult ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_tdstSpecificAttributesFor3D *p_stSpecifAttrib3D; GLI_tdxHandleToCamera hCamera; MTH_tdxReal xDotProduct; MTH3D_tdstVector stCenter; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* the matrix is not scaled, so perform plan rejection for sphere*/ p_stSpecifAttrib3D = (GLI_tdstSpecificAttributesFor3D *) _p_stVpt -> p_vSpecificToXD; hCamera = p_stSpecifAttrib3D->p_stCam; /* compute sphere center in camera coords*/ POS_fn_vMulMatrixVertex (&stCenter,&hCamera->stMatrix,_p_stSphereCenter); _lCullingResult |= GEO_C_lCullingIntersect; /* if the culling result against the near border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingNear) ) { if (stCenter.xZ + _xRadius < hCamera->xNear) { return GEO_C_lCullingOut; } xDotProduct = stCenter.xZ - _xRadius; if (xDotProduct > hCamera->xNear) { /* if all points are beyond the near plane, the sphere is inside relatively to this plane*/ _lCullingResult |= GEO_C_lCullingNear; } } /* if the culling result against the far border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingFar) ) { if ( MTH_M_bDifferentZero(GEO_g_xZFar) ) { if (stCenter.xZ - _xRadius > GEO_g_xZFar ) return GEO_C_lCullingOut; if ( stCenter.xZ - _xRadius > GEO_g_xZFar - GEO_g_xZFarTransparencyZone ) GEO_g_xZFarTransparencyLevel = MTH_C_ONE - ((stCenter.xZ - _xRadius - GEO_g_xZFar + GEO_g_xZFarTransparencyZone) * GEO_g_xOoZFarTransparencyZone); else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; /* if all points are in front of the far plane, the sphere is inside relatively to this plane*/ _lCullingResult |= GEO_C_lCullingFar; } } else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; /* if all points are in front of the far plane, the sphere is inside relatively to this plane*/ _lCullingResult |= GEO_C_lCullingFar; } } else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; } /* if the culling result against the left border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingLeft) ) { xDotProduct = MTH3D_M_xDotProductVector(&stCenter, &hCamera->stNormPlaneRight); /*left and right plane normal car names are inversed!*/ if (xDotProduct > _xRadius + hCamera->xDistPlaneLeft) { return GEO_C_lCullingOut; } if (xDotProduct < hCamera->xDistPlaneLeft - _xRadius) { _lCullingResult |= GEO_C_lCullingLeft; } } /* if the culling result against the right border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingRight) ) { xDotProduct = MTH3D_M_xDotProductVector(&stCenter, &hCamera->stNormPlaneLeft); /*left and right plane normal car names are inversed!*/ if (xDotProduct > _xRadius + hCamera->xDistPlaneRight) { return GEO_C_lCullingOut; } if (xDotProduct < hCamera->xDistPlaneRight - _xRadius) { _lCullingResult |= GEO_C_lCullingRight; } } /* if the culling result against the up border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingUp) ) { xDotProduct = MTH3D_M_xDotProductVector(&stCenter, &hCamera->stNormPlaneUp); if (xDotProduct > _xRadius + hCamera->xDistPlaneUp) { return GEO_C_lCullingOut; } if (xDotProduct < hCamera->xDistPlaneUp - _xRadius) { _lCullingResult |= GEO_C_lCullingUp; } } /* if the culling result against the down border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingDown) ) { xDotProduct = MTH3D_M_xDotProductVector(&stCenter, &hCamera->stNormPlaneDown); if (xDotProduct > _xRadius + hCamera->xDistPlaneDown) { return GEO_C_lCullingOut; } if (xDotProduct < hCamera->xDistPlaneDown - _xRadius) { _lCullingResult |= GEO_C_lCullingDown; } } return _lCullingResult; } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /* Name: GEO_lCullingSphere*/ /* Goal: Return 1 if the sphere is visible with the viewport's camera, 0 else.*/ /* Code: Philippe Vimont*/ /* modif : Fabien Bole-Feysot*/ /* entry : the viewport to test*/ /* the center of the sphere, in object's local axis system*/ /* the radius of the sphere, not including any scale or so*/ /* the object's matrix (that must be used to compute coords in the global axis system)*/ /**/ /* if you plan to use this function during the drawing process, then look at the*/ /* GEO_lCullingSphereNoMMM below, which is faster.*/ /**********************************************************************************************/ #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */ long GEO_lCullingSphere ( GLD_tdstViewportAttributes *p_stVpt, MTH3D_tdstVector *p_stSphereCenter, MTH_tdxReal xRadius, POS_tdstCompletePosition *p_stMatrix, long _lCullingResult ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ POS_tdstCompletePosition stTempMatrix; GLI_tdstSpecificAttributesFor3D *p_stSpecifAttrib3D; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ p_stSpecifAttrib3D = (GLI_tdstSpecificAttributesFor3D*) p_stVpt -> p_vSpecificToXD; /* compute the camera * local matrix*/ POS_fn_vMulMatrixMatrix (&stTempMatrix,&p_stSpecifAttrib3D->p_stCam->stMatrix,p_stMatrix); /* call the sphere culling main function*/ return GEO_lMainCullingSphere(p_stVpt,p_stSphereCenter,xRadius,&stTempMatrix,p_stMatrix,_lCullingResult); } #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */ /**********************************************************************************************/ /* Name: GEO_lCullingSphereNoMMM*/ /* Goal: Return 1 if the sphere is visible with the viewport's camera, 0 else.*/ /* Code: Philippe Vimont*/ /* modif : Fabien Bole-Feysot*/ /* entry : the viewport to test*/ /* the center of the sphere, in object's local axis system*/ /* the radius of the sphere, not including any scale or so*/ /* the object's matrix (that must be used to compute coords in the global axis system)*/ /**/ /* use this function only in the drawing process, because the matrix that */ /* will be used for computing will be retrieved with the HIE_hRetrieveCurrentMatrix() function.*/ /**/ /* if the HIE_hRetrieveCurrentMatrix() matrix is not up to date, use GEO_lCullingSphere instead*/ /**********************************************************************************************/ long GEO_lCullingSphereNoMMM ( GLD_tdstViewportAttributes *p_stVpt , MTH3D_tdstVector *p_stSphereCenter , MTH_tdxReal xRadius, POS_tdstCompletePosition *p_stMatrix, long _lCullingResult ) { return GEO_lMainCullingSphere(p_stVpt,p_stSphereCenter,xRadius,HIE_hRetrieveCurrentMatrix(),p_stMatrix,_lCullingResult); } /**********************************************************************************************/ /* Name: GEO_lCullingBox*/ /* Goal: Return 1 if the parallele box is visible with the viewport's camera, 0 else.*/ /* Code: Philippe Vimont*/ /* modif : Fabien Bole-Feysot (optimisation)*/ /* modif : Vincent Lhullier (optimisation )*/ /* entry : the viewport to test*/ /* the min point of the parallel box, in the world global axis system*/ /* the max point of the parallel box, in the world global axis system*/ /**********************************************************************************************/ long GEO_lCullingBox ( GLD_tdstViewportAttributes *p_stVpt, MTH3D_tdstVector *p_stMin, MTH3D_tdstVector *p_stMax, long _lCullingResult ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ MTH3D_tdstVector stMinWithCamera, stMaxWithCamera; MTH_tdxReal xCompute, xValue0, xValue1, xValue2, xValue3, xValue4, xValue5; GLI_tdxHandleToCamera hCamera; ACP_tdxBool bComputed = FALSE; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ hCamera = ((GLI_tdstSpecificAttributesFor3D *) p_stVpt -> p_vSpecificToXD) -> p_stCam; MTH3D_M_vSubVector( &stMinWithCamera, p_stMin, &gs_stCameraPosInGlobal ); MTH3D_M_vSubVector( &stMaxWithCamera, p_stMax, &gs_stCameraPosInGlobal ); _lCullingResult |= GEO_C_lCullingIntersect; /* if the culling result against the near border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingNear) ) { xValue0 = stMinWithCamera.xX * gs_stGlobalNormPlaneNear.xX; xValue1 = stMinWithCamera.xY * gs_stGlobalNormPlaneNear.xY; xValue2 = stMinWithCamera.xZ * gs_stGlobalNormPlaneNear.xZ; xValue3 = stMaxWithCamera.xX * gs_stGlobalNormPlaneNear.xX; xValue4 = stMaxWithCamera.xY * gs_stGlobalNormPlaneNear.xY; xValue5 = stMaxWithCamera.xZ * gs_stGlobalNormPlaneNear.xZ; xCompute = ((xValue0 < xValue3) ? xValue0 : xValue3) + ((xValue1 < xValue4) ? xValue1 : xValue4) + ((xValue2 < xValue5) ? xValue2 : xValue5); /*if all points are behind the near plane, the box is out*/ if ( xCompute > - hCamera->xNear ) { return GEO_C_lCullingOut; } /* if all points are beyond the near plane, the box is inside relatively to this plane*/ xCompute = ((xValue0 > xValue3) ? xValue0 : xValue3) + ((xValue1 > xValue4) ? xValue1 : xValue4) + ((xValue2 > xValue5) ? xValue2 : xValue5); if ( xCompute < - hCamera->xNear ) { _lCullingResult |= GEO_C_lCullingNear; } bComputed = TRUE; /*the test against the plane normal is already computed*/ } /* if the culling result against the far border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingFar) ) { if ( MTH_M_bDifferentZero(GEO_g_xZFar) ) { if ( !bComputed ) /* we did not test agains the near plane, so we need to compute the test against the far plane normal*/ { xValue0 = stMinWithCamera.xX * gs_stGlobalNormPlaneNear.xX; xValue1 = stMinWithCamera.xY * gs_stGlobalNormPlaneNear.xY; xValue2 = stMinWithCamera.xZ * gs_stGlobalNormPlaneNear.xZ; xValue3 = stMaxWithCamera.xX * gs_stGlobalNormPlaneNear.xX; xValue4 = stMaxWithCamera.xY * gs_stGlobalNormPlaneNear.xY; xValue5 = stMaxWithCamera.xZ * gs_stGlobalNormPlaneNear.xZ; xCompute = - (((xValue0 > xValue3) ? xValue0 : xValue3) + ((xValue1 > xValue4) ? xValue1 : xValue4) + ((xValue2 > xValue5) ? xValue2 : xValue5)); } else { xCompute = - xCompute; } /* if all points are beyond the far clipping plane, the box is out*/ if ( xCompute > GEO_g_xZFar ) return GEO_C_lCullingOut; GEO_g_xZFarTransparencyLevel = GEO_g_xZFar - GEO_g_xZFarTransparencyZone; if ( xCompute > GEO_g_xZFarTransparencyLevel ) GEO_g_xZFarTransparencyLevel = MTH_C_ONE - ((xCompute - GEO_g_xZFarTransparencyLevel) * GEO_g_xOoZFarTransparencyZone); else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; /* if all points are in front of the far plane, the box is inside relatively to this plane*/ _lCullingResult |= GEO_C_lCullingFar; } } else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; /* since there is no far plane, the box is inside relatively to this plane*/ _lCullingResult |= GEO_C_lCullingFar; } } else { GEO_g_xZFarTransparencyLevel = MTH_C_ONE; } /* if the culling result against the left border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingLeft) ) { xValue0 = stMinWithCamera.xX * gs_stGlobalNormPlaneLeft.xX; xValue1 = stMinWithCamera.xY * gs_stGlobalNormPlaneLeft.xY; xValue2 = stMinWithCamera.xZ * gs_stGlobalNormPlaneLeft.xZ; xValue3 = stMaxWithCamera.xX * gs_stGlobalNormPlaneLeft.xX; xValue4 = stMaxWithCamera.xY * gs_stGlobalNormPlaneLeft.xY; xValue5 = stMaxWithCamera.xZ * gs_stGlobalNormPlaneLeft.xZ; /*if all points on the left side of the left plane, the box is out*/ xCompute = ((xValue0 < xValue3) ? xValue0 : xValue3) + ((xValue1 < xValue4) ? xValue1 : xValue4) + ((xValue2 < xValue5) ? xValue2 : xValue5); if ( xCompute > hCamera->xDistPlaneLeft ) { return GEO_C_lCullingOut; } /*if all points are on the right side of the left plane, the box is inside relatively to this plane*/ xCompute = ((xValue0 > xValue3) ? xValue0 : xValue3) + ((xValue1 > xValue4) ? xValue1 : xValue4) + ((xValue2 > xValue5) ? xValue2 : xValue5); if (xCompute < hCamera->xDistPlaneLeft ) { _lCullingResult |= GEO_C_lCullingLeft; } } /* if the culling result against the right border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingRight) ) { xValue0 = stMinWithCamera.xX * gs_stGlobalNormPlaneRight.xX; xValue1 = stMinWithCamera.xY * gs_stGlobalNormPlaneRight.xY; xValue2 = stMinWithCamera.xZ * gs_stGlobalNormPlaneRight.xZ; xValue3 = stMaxWithCamera.xX * gs_stGlobalNormPlaneRight.xX; xValue4 = stMaxWithCamera.xY * gs_stGlobalNormPlaneRight.xY; xValue5 = stMaxWithCamera.xZ * gs_stGlobalNormPlaneRight.xZ; /*if all points on the right side of the right plane, the box is out*/ xCompute = ((xValue0 < xValue3) ? xValue0 : xValue3) + ((xValue1 < xValue4) ? xValue1 : xValue4) + ((xValue2 < xValue5) ? xValue2 : xValue5); if (xCompute > hCamera->xDistPlaneRight ) { return GEO_C_lCullingOut; } /*if all points are on the left side of the right plane, the box is inside relatively to this plane*/ xCompute = ((xValue0 > xValue3) ? xValue0 : xValue3) + ((xValue1 > xValue4) ? xValue1 : xValue4) + ((xValue2 > xValue5) ? xValue2 : xValue5); if (xCompute < hCamera->xDistPlaneRight ) { _lCullingResult |= GEO_C_lCullingRight; } } /* if the culling result against the up border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingUp) ) { xValue0 = stMinWithCamera.xX * gs_stGlobalNormPlaneUp.xX; xValue1 = stMinWithCamera.xY * gs_stGlobalNormPlaneUp.xY; xValue2 = stMinWithCamera.xZ * gs_stGlobalNormPlaneUp.xZ; xValue3 = stMaxWithCamera.xX * gs_stGlobalNormPlaneUp.xX; xValue4 = stMaxWithCamera.xY * gs_stGlobalNormPlaneUp.xY; xValue5 = stMaxWithCamera.xZ * gs_stGlobalNormPlaneUp.xZ; /*if all points are above the upper plane, the box is out*/ xCompute = ((xValue0 < xValue3) ? xValue0 : xValue3) + ((xValue1 < xValue4) ? xValue1 : xValue4) + ((xValue2 < xValue5) ? xValue2 : xValue5); if (xCompute > hCamera->xDistPlaneUp ) { return GEO_C_lCullingOut; } /*if all points are below the upper plane, the box is inside relatively to this plane*/ xCompute = ((xValue0 > xValue3) ? xValue0 : xValue3) + ((xValue1 > xValue4) ? xValue1 : xValue4) + ((xValue2 > xValue5) ? xValue2 : xValue5); if (xCompute < hCamera->xDistPlaneUp ) { _lCullingResult |= GEO_C_lCullingUp; } } /* if the culling result against the down border is not known as in, compute it*/ if ( !(_lCullingResult & GEO_C_lCullingDown) ) { xValue0 = stMinWithCamera.xX * gs_stGlobalNormPlaneDown.xX; xValue1 = stMinWithCamera.xY * gs_stGlobalNormPlaneDown.xY; xValue2 = stMinWithCamera.xZ * gs_stGlobalNormPlaneDown.xZ; xValue3 = stMaxWithCamera.xX * gs_stGlobalNormPlaneDown.xX; xValue4 = stMaxWithCamera.xY * gs_stGlobalNormPlaneDown.xY; xValue5 = stMaxWithCamera.xZ * gs_stGlobalNormPlaneDown.xZ; /*if all points are under the lower plane, the box is out*/ xCompute = ((xValue0 < xValue3) ? xValue0 : xValue3) + ((xValue1 < xValue4) ? xValue1 : xValue4) + ((xValue2 < xValue5) ? xValue2 : xValue5); if (xCompute > hCamera->xDistPlaneDown ) { return GEO_C_lCullingOut; } /*if all points are above the lower plane, the box is inside relatively to this plane*/ xCompute = ((xValue0 > xValue3) ? xValue0 : xValue3) + ((xValue1 > xValue4) ? xValue1 : xValue4) + ((xValue2 > xValue5) ? xValue2 : xValue5); if (xCompute < hCamera->xDistPlaneDown ) { _lCullingResult |= GEO_C_lCullingDown; } } return _lCullingResult; } /* * OLD CULLING // DONT REMOVE SPACE ******************************************************************************************** // Name: GLI_lCullingBox // Goal: Return 1 if the parallele box is visible with the viewport's camera, 0 else. // Code: Philippe Vimont // modif : Fabien Bole-Feysot (optimisation) // entry : the viewport to test // the min point of the parallel box, in the world global axis system // the max point of the parallel box, in the world global axis system // DONT REMOVE SPACE ******************************************************************************************** long GLI_lNormalCullingBox ( GLD_tdstViewportAttributes *p_stVpt , MTH3D_tdstVector *p_stMin , MTH3D_tdstVector *p_stMax ) { GLI_tdstAligned3DVector a8_stVertexTrans [8], *p_stFastPointer; GLI_tdstSpecificAttributesFor3D *p_stSpecifAttrib3D; MTH3D_tdstVector stDiago, stOrigin; MTH3D_tdstVector stIp, stJp, stKp; POS_tdstCompletePosition *p_stPos; MTH3D_tdstMatrix *p_stMatrix; GLI_tdstAligned2DVector a8_st2DVertex [8] ; ACP_tdxIndex xCounter; MTH_tdxReal xNearPlane; p_stSpecifAttrib3D = (GLI_tdstSpecificAttributesFor3D *) p_stVpt -> p_vSpecificToXD; p_stPos = &p_stSpecifAttrib3D->p_stCam->stMatrix; p_stMatrix = &p_stPos->stTransformMatrix; xNearPlane = p_stSpecifAttrib3D->p_stCam->xNear; // build the diagonal vector MTH3D_M_vSubVector(&stDiago,p_stMax,p_stMin); // compute the new box origin point POS_fn_vMulMatrixVertex (&stOrigin,p_stPos,p_stMin); // compute the new Ip,Jp,Kp vectors stIp.xX = MTH_M_xMul( p_stMatrix->stCol_0.xX, stDiago.xX); stIp.xY = MTH_M_xMul( p_stMatrix->stCol_0.xY, stDiago.xX); stIp.xZ = MTH_M_xMul( p_stMatrix->stCol_0.xZ, stDiago.xX); stJp.xX = MTH_M_xMul( p_stMatrix->stCol_1.xX, stDiago.xY); stJp.xY = MTH_M_xMul( p_stMatrix->stCol_1.xY, stDiago.xY); stJp.xZ = MTH_M_xMul( p_stMatrix->stCol_1.xZ, stDiago.xY); stKp.xX = MTH_M_xMul( p_stMatrix->stCol_2.xX, stDiago.xZ); stKp.xY = MTH_M_xMul( p_stMatrix->stCol_2.xY, stDiago.xZ); stKp.xZ = MTH_M_xMul( p_stMatrix->stCol_2.xZ, stDiago.xZ); // Build The Cube from its new origin and new base vectors MTH3D_M_vCopyVector(&a8_stVertexTrans[0],&stOrigin); MTH3D_M_vAddVector(&a8_stVertexTrans[1],&stOrigin,&stIp); //i MTH3D_M_vAddVector(&a8_stVertexTrans[2],&stOrigin,&stJp); //j MTH3D_M_vAddVector(&a8_stVertexTrans[3],&stOrigin,&stKp); //k MTH3D_M_vAddVector(&a8_stVertexTrans[4],&a8_stVertexTrans[1],&stJp); //i+j MTH3D_M_vAddVector(&a8_stVertexTrans[5],&a8_stVertexTrans[1],&stKp); //i+k MTH3D_M_vAddVector(&a8_stVertexTrans[6],&a8_stVertexTrans[2],&stKp); //j+k MTH3D_M_vAddVector(&a8_stVertexTrans[7],&a8_stVertexTrans[4],&stKp); //i+j+k // Fast Cull on Z xCounter = 8; // count the points that are not visible for (p_stFastPointer = a8_stVertexTrans+7; p_stFastPointer != a8_stVertexTrans-1; p_stFastPointer--) { if (xNearPlane >= p_stFastPointer->xZ) { // this point is invisible ! xCounter--; p_stFastPointer->xZ = xNearPlane; // in case we must project this point... } } if (!xCounter) { // every point is invisible ! return 0; } // part of the cube is in front of the camera, so project GLI_xSerialProjection (p_stSpecifAttrib3D -> p_stCam ,8,a8_stVertexTrans,a8_st2DVertex); // correct 3DFX bug g_stCurLLInterface.p_fnSerialSnap2DVertices (a8_st2DVertex,8); // and clip return g_stCurLLInterface.p_fnCullListOfPoints (p_stVpt , 8 , a8_st2DVertex); } * END OLD CULLING */ /* * TEST FOR CULLING // DONT REMOVE SPACE ******************************************************************************************** // Name: GLI_lCullingBox // Goal: Return 1 if the parallele box is visible with the viewport's camera, 0 else. // Code: Philippe Vimont // modif : Fabien Bole-Feysot (optimisation) // entry : the viewport to test // the min point of the parallel box, in the world global axis system // the max point of the parallel box, in the world global axis system // DONT REMOVE SPACE ******************************************************************************************** extern struct tdstEngineStructure_ g_stEngineStructure; long GLI_lCullingBox ( GLD_tdstViewportAttributes *p_stVpt , MTH3D_tdstVector *p_stMin , MTH3D_tdstVector *p_stMax ) { long lMyResult, lNormalResult; static unsigned long lClippedByMeButNotByNormal = 0; static unsigned long lClippedByNormalButNotByMe = 0; static char cReturnType = 0; static unsigned long ulTrameNumber = 0xFF; static GLD_tdstViewportAttributes *p_stLastVpt = NULL; if ( ( *(unsigned long*) ((char *) &g_stEngineStructure + 0xEA8 ) != ulTrameNumber) || (p_stVpt != p_stLastVpt) ) { ulTrameNumber = *(unsigned long*) ((char *) &g_stEngineStructure + 0xEA8 ); p_stLastVpt = p_stVpt; GLI_fn_vComputeCameraParametersForCulling( p_stVpt ); } lMyResult = GLI_lMyCullingBox( p_stVpt , p_stMin , p_stMax ); lNormalResult = GLI_lNormalCullingBox( p_stVpt , p_stMin , p_stMax ); if ((lMyResult == 0) && (lNormalResult != 0)) lClippedByMeButNotByNormal++; else if ((lMyResult != 0) && (lNormalResult == 0)) lClippedByNormalButNotByMe++; switch (cReturnType) { case 0 : return lMyResult; case 1 : return lNormalResult; } } * END TEST FOR CULLING */ #ifdef __cplusplus } /*extern "C"*/ #endif