reman3/Rayman_X/cpa/tempgrp/GEO/Culling.c

862 lines
32 KiB
C

/*
=======================================================================================
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