862 lines
32 KiB
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
|