/* * KJL 15:13:43 7/17/97 - frustrum.c * * Contains all the functions connected * to the view frustrum and clipping * */ #include "3dc.h" #include "module.h" #include "inline.h" #include "stratdef.h" #include "gamedef.h" #include "kshape.h" #include "kzsort.h" #include "frustrum.h" #include "particle.h" #define UseLocalAssert Yes #include "ourasert.h" /*KJL**************************************************************************************** * G L O B A L S * ****************************************************************************************KJL*/ extern VECTORCH RotatedPts[]; extern DISPLAYBLOCK *Global_ODB_Ptr; extern SHAPEHEADER *Global_ShapeHeaderPtr; extern int *Global_ShapePoints; extern int *Global_ShapeNormals; extern VECTORCH LocalView; #define FAR_Z_CLIP 0 #define FAR_Z_CLIP_RANGE 49000 /*KJL**************************************************************************************** * P R O T O T Y P E S * ****************************************************************************************KJL*/ /* GOURAUD POLYGON CLIPPING */ void (*GouraudPolygon_ClipWithNegativeX)(void); void (*GouraudPolygon_ClipWithPositiveY)(void); void (*GouraudPolygon_ClipWithNegativeY)(void); void (*GouraudPolygon_ClipWithPositiveX)(void); /* TEXTURED POLYGON CLIPPING */ void (*TexturedPolygon_ClipWithNegativeX)(void); void (*TexturedPolygon_ClipWithPositiveY)(void); void (*TexturedPolygon_ClipWithNegativeY)(void); void (*TexturedPolygon_ClipWithPositiveX)(void); /* GOURAUD TEXTURED POLYGON CLIPPING */ void (*GouraudTexturedPolygon_ClipWithNegativeX)(void); void (*GouraudTexturedPolygon_ClipWithPositiveY)(void); void (*GouraudTexturedPolygon_ClipWithNegativeY)(void); void (*GouraudTexturedPolygon_ClipWithPositiveX)(void); /* FRUSTRUM TESTS */ int (*ObjectWithinFrustrum)(DISPLAYBLOCK *dbPtr); int (*ObjectCompletelyWithinFrustrum)(DISPLAYBLOCK *dbPtr); int (*VertexWithinFrustrum)(RENDERVERTEX *vertexPtr); void (*TestVerticesWithFrustrum)(void); static void GouraudPolygon_Norm_ClipWithNegativeX(void); static void GouraudPolygon_Wide_ClipWithNegativeX(void); static void GouraudPolygon_Norm_ClipWithPositiveY(void); static void GouraudPolygon_Wide_ClipWithPositiveY(void); static void GouraudPolygon_Norm_ClipWithNegativeY(void); static void GouraudPolygon_Wide_ClipWithNegativeY(void); static void GouraudPolygon_Norm_ClipWithPositiveX(void); static void GouraudPolygon_Wide_ClipWithPositiveX(void); static void TexturedPolygon_Norm_ClipWithNegativeX(void); static void TexturedPolygon_Wide_ClipWithNegativeX(void); static void TexturedPolygon_Norm_ClipWithPositiveY(void); static void TexturedPolygon_Wide_ClipWithPositiveY(void); static void TexturedPolygon_Norm_ClipWithNegativeY(void); static void TexturedPolygon_Wide_ClipWithNegativeY(void); static void TexturedPolygon_Norm_ClipWithPositiveX(void); static void TexturedPolygon_Wide_ClipWithPositiveX(void); static void GouraudTexturedPolygon_Norm_ClipWithNegativeX(void); static void GouraudTexturedPolygon_Wide_ClipWithNegativeX(void); static void GouraudTexturedPolygon_Norm_ClipWithPositiveY(void); static void GouraudTexturedPolygon_Wide_ClipWithPositiveY(void); static void GouraudTexturedPolygon_Norm_ClipWithNegativeY(void); static void GouraudTexturedPolygon_Wide_ClipWithNegativeY(void); static void GouraudTexturedPolygon_Norm_ClipWithPositiveX(void); static void GouraudTexturedPolygon_Wide_ClipWithPositiveX(void); static int VertexWithin_Norm_Frustrum(RENDERVERTEX *vertexPtr); static int VertexWithin_Wide_Frustrum(RENDERVERTEX *vertexPtr); static int ObjectWithin_Norm_Frustrum(DISPLAYBLOCK *dbPtr); static int ObjectWithin_Wide_Frustrum(DISPLAYBLOCK *dbPtr); static int ObjectCompletelyWithin_Norm_Frustrum(DISPLAYBLOCK *dbPtr); static int ObjectCompletelyWithin_Wide_Frustrum(DISPLAYBLOCK *dbPtr); static void TestVerticesWith_Norm_Frustrum(void); static void TestVerticesWith_Wide_Frustrum(void); /*KJL**************************************************************************************** * F U N C T I O N S * ****************************************************************************************KJL*/ void SetFrustrumType(enum FrustrumType frustrumType) { switch (frustrumType) { default: case FRUSTRUM_TYPE_NORMAL: { /* GOURAUD POLYGON CLIPPING */ GouraudPolygon_ClipWithNegativeX = GouraudPolygon_Norm_ClipWithNegativeX; GouraudPolygon_ClipWithPositiveY = GouraudPolygon_Norm_ClipWithPositiveY; GouraudPolygon_ClipWithNegativeY = GouraudPolygon_Norm_ClipWithNegativeY; GouraudPolygon_ClipWithPositiveX = GouraudPolygon_Norm_ClipWithPositiveX; /* TEXTURED POLYGON CLIPPING */ TexturedPolygon_ClipWithNegativeX = TexturedPolygon_Norm_ClipWithNegativeX; TexturedPolygon_ClipWithPositiveY = TexturedPolygon_Norm_ClipWithPositiveY; TexturedPolygon_ClipWithNegativeY = TexturedPolygon_Norm_ClipWithNegativeY; TexturedPolygon_ClipWithPositiveX = TexturedPolygon_Norm_ClipWithPositiveX; /* GOURAUD TEXTURED POLYGON CLIPPING */ GouraudTexturedPolygon_ClipWithNegativeX = GouraudTexturedPolygon_Norm_ClipWithNegativeX; GouraudTexturedPolygon_ClipWithPositiveY = GouraudTexturedPolygon_Norm_ClipWithPositiveY; GouraudTexturedPolygon_ClipWithNegativeY = GouraudTexturedPolygon_Norm_ClipWithNegativeY; GouraudTexturedPolygon_ClipWithPositiveX = GouraudTexturedPolygon_Norm_ClipWithPositiveX; /* FRUSTRUM TESTS */ TestVerticesWithFrustrum = TestVerticesWith_Norm_Frustrum; ObjectWithinFrustrum = ObjectWithin_Norm_Frustrum; ObjectCompletelyWithinFrustrum = ObjectCompletelyWithin_Norm_Frustrum; VertexWithinFrustrum = VertexWithin_Norm_Frustrum; break; } case FRUSTRUM_TYPE_WIDE: { /* GOURAUD POLYGON CLIPPING */ GouraudPolygon_ClipWithNegativeX = GouraudPolygon_Wide_ClipWithNegativeX; GouraudPolygon_ClipWithPositiveY = GouraudPolygon_Wide_ClipWithPositiveY; GouraudPolygon_ClipWithNegativeY = GouraudPolygon_Wide_ClipWithNegativeY; GouraudPolygon_ClipWithPositiveX = GouraudPolygon_Wide_ClipWithPositiveX; /* TEXTURED POLYGON CLIPPING */ TexturedPolygon_ClipWithNegativeX = TexturedPolygon_Wide_ClipWithNegativeX; TexturedPolygon_ClipWithPositiveY = TexturedPolygon_Wide_ClipWithPositiveY; TexturedPolygon_ClipWithNegativeY = TexturedPolygon_Wide_ClipWithNegativeY; TexturedPolygon_ClipWithPositiveX = TexturedPolygon_Wide_ClipWithPositiveX; /* GOURAUD TEXTURED POLYGON CLIPPING */ GouraudTexturedPolygon_ClipWithNegativeX = GouraudTexturedPolygon_Wide_ClipWithNegativeX; GouraudTexturedPolygon_ClipWithPositiveY = GouraudTexturedPolygon_Wide_ClipWithPositiveY; GouraudTexturedPolygon_ClipWithNegativeY = GouraudTexturedPolygon_Wide_ClipWithNegativeY; GouraudTexturedPolygon_ClipWithPositiveX = GouraudTexturedPolygon_Wide_ClipWithPositiveX; /* FRUSTRUM TESTS */ TestVerticesWithFrustrum = TestVerticesWith_Wide_Frustrum; ObjectWithinFrustrum = ObjectWithin_Wide_Frustrum; ObjectCompletelyWithinFrustrum = ObjectCompletelyWithin_Wide_Frustrum; VertexWithinFrustrum = VertexWithin_Wide_Frustrum; break; } } } /* clipping code macros - these are used as building blocks to assemble clipping fns for different polygon types with the minimum of fuss */ #define ZCLIPPINGVALUE 4 //64 #define Clip_Z_Test(v) (ZCLIPPINGVALUE <= (v)->Z) #define Clip_NX_Test(v) (-(v)->X <= (v)->Z) #define Clip_PX_Test(v) ((v)->X <= (v)->Z) #define Clip_NY_Test(v) (-(v)->Y <= (v)->Z) #define Clip_PY_Test(v) ((v)->Y <= (v)->Z) #define Clip_LoopStart(b) \ do \ { \ RENDERVERTEX *nextVertexPtr; \ int nextVertexInside; \ \ /* setup pointer to next vertex, wrapping round if necessary */ \ if (!--verticesLeft) \ { \ nextVertexPtr = (b); \ } \ else \ { \ nextVertexPtr = curVertexPtr+1; \ } \ \ /* if current vertex is inside the plane, output it */ \ if (curVertexInside) \ { \ numberOfPointsOutputted++; \ *outputVerticesPtr++ = *curVertexPtr; \ } \ \ /* test if next vertex is inside the plane */ \ nextVertexInside = #define Clip_Z_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (ZCLIPPINGVALUE - curVertexPtr->Z), \ (nextVertexPtr->Z - curVertexPtr->Z) \ ); \ \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); \ outputVerticesPtr->Y = curVertexPtr->Y + MUL_FIXED(lambda,nextVertexPtr->Y-curVertexPtr->Y); \ outputVerticesPtr->Z = ZCLIPPINGVALUE; #define Clip_NX_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (curVertexPtr->Z + curVertexPtr->X), \ -(nextVertexPtr->X-curVertexPtr->X) - (nextVertexPtr->Z-curVertexPtr->Z) \ ); \ \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); \ outputVerticesPtr->Z = -outputVerticesPtr->X; \ outputVerticesPtr->Y = curVertexPtr->Y + MUL_FIXED(lambda,nextVertexPtr->Y-curVertexPtr->Y); #define Clip_PX_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (curVertexPtr->Z - curVertexPtr->X), \ (nextVertexPtr->X-curVertexPtr->X) - (nextVertexPtr->Z-curVertexPtr->Z) \ ); \ \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); \ outputVerticesPtr->Z = outputVerticesPtr->X; \ outputVerticesPtr->Y = curVertexPtr->Y + MUL_FIXED(lambda,nextVertexPtr->Y-curVertexPtr->Y); #define Clip_NY_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (curVertexPtr->Z + curVertexPtr->Y), \ -(nextVertexPtr->Y-curVertexPtr->Y) - (nextVertexPtr->Z-curVertexPtr->Z) \ ); \ \ outputVerticesPtr->Z = curVertexPtr->Z + MUL_FIXED(lambda,nextVertexPtr->Z-curVertexPtr->Z); \ outputVerticesPtr->Y = -(outputVerticesPtr->Z); \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); #define Clip_PY_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (curVertexPtr->Z - curVertexPtr->Y), \ (nextVertexPtr->Y-curVertexPtr->Y) - (nextVertexPtr->Z-curVertexPtr->Z) \ ); \ \ outputVerticesPtr->Z = curVertexPtr->Z + MUL_FIXED(lambda,nextVertexPtr->Z-curVertexPtr->Z); \ outputVerticesPtr->Y = (outputVerticesPtr->Z); \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); #define Clip_OutputUV \ outputVerticesPtr->U = curVertexPtr->U + MUL_FIXED(lambda,nextVertexPtr->U-curVertexPtr->U); \ outputVerticesPtr->V = curVertexPtr->V + MUL_FIXED(lambda,nextVertexPtr->V-curVertexPtr->V); #define Clip_OutputI \ outputVerticesPtr->A = curVertexPtr->A + MUL_FIXED(lambda,nextVertexPtr->A-curVertexPtr->A); \ outputVerticesPtr->R = curVertexPtr->R + MUL_FIXED(lambda,nextVertexPtr->R-curVertexPtr->R); \ outputVerticesPtr->G = curVertexPtr->G + MUL_FIXED(lambda,nextVertexPtr->G-curVertexPtr->G); \ outputVerticesPtr->B = curVertexPtr->B + MUL_FIXED(lambda,nextVertexPtr->B-curVertexPtr->B); \ outputVerticesPtr->SpecularR = curVertexPtr->SpecularR + MUL_FIXED(lambda,nextVertexPtr->SpecularR-curVertexPtr->SpecularR); \ outputVerticesPtr->SpecularG = curVertexPtr->SpecularG + MUL_FIXED(lambda,nextVertexPtr->SpecularG-curVertexPtr->SpecularG); \ outputVerticesPtr->SpecularB = curVertexPtr->SpecularB + MUL_FIXED(lambda,nextVertexPtr->SpecularB-curVertexPtr->SpecularB); #define Clip_LoopEnd(b) \ numberOfPointsOutputted++; \ outputVerticesPtr++; \ } \ \ /* okay, now the current vertex becomes what was the next vertex */ \ curVertexPtr = nextVertexPtr; \ curVertexInside = nextVertexInside; \ } \ while(verticesLeft); \ \ RenderPolygon.NumberOfVertices = numberOfPointsOutputted; /* Wide screen versions of clip macros */ #define Clip_Wide_NX_Test(v) (-(v)->X <= (v)->Z*2) #define Clip_Wide_PX_Test(v) ((v)->X <= (v)->Z*2) #define Clip_Wide_NY_Test(v) (-(v)->Y <= (v)->Z*2) #define Clip_Wide_PY_Test(v) ((v)->Y <= (v)->Z*2) #define Clip_Wide_NX_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (-2*curVertexPtr->Z - curVertexPtr->X), \ (nextVertexPtr->X-curVertexPtr->X) - (-2)*(nextVertexPtr->Z-curVertexPtr->Z) \ ); \ \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); \ outputVerticesPtr->Z = -outputVerticesPtr->X/2; \ outputVerticesPtr->Y = curVertexPtr->Y + MUL_FIXED(lambda,nextVertexPtr->Y-curVertexPtr->Y); #define Clip_Wide_PX_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (2*curVertexPtr->Z - curVertexPtr->X), \ (nextVertexPtr->X-curVertexPtr->X) - 2*(nextVertexPtr->Z-curVertexPtr->Z) \ ); \ \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); \ outputVerticesPtr->Z = outputVerticesPtr->X/2; \ outputVerticesPtr->Y = curVertexPtr->Y + MUL_FIXED(lambda,nextVertexPtr->Y-curVertexPtr->Y); #define Clip_Wide_NY_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (2*curVertexPtr->Z + curVertexPtr->Y), \ -(nextVertexPtr->Y-curVertexPtr->Y) - 2*(nextVertexPtr->Z-curVertexPtr->Z) \ ); \ \ outputVerticesPtr->Z = curVertexPtr->Z + MUL_FIXED(lambda,nextVertexPtr->Z-curVertexPtr->Z); \ outputVerticesPtr->Y = -(outputVerticesPtr->Z*2); \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); #define Clip_Wide_PY_OutputXYZ \ /* if one is in, and the other is out, output a clipped vertex */ \ if (nextVertexInside != curVertexInside) \ { \ int lambda; \ \ lambda = DIV_FIXED \ ( \ (2*curVertexPtr->Z - curVertexPtr->Y), \ (nextVertexPtr->Y-curVertexPtr->Y) - 2*(nextVertexPtr->Z-curVertexPtr->Z) \ ); \ \ outputVerticesPtr->Z = curVertexPtr->Z + MUL_FIXED(lambda,nextVertexPtr->Z-curVertexPtr->Z); \ outputVerticesPtr->Y = (outputVerticesPtr->Z*2); \ outputVerticesPtr->X = curVertexPtr->X + MUL_FIXED(lambda,nextVertexPtr->X-curVertexPtr->X); /*KJL************** * GOURAUD POLYGON * **************KJL*/ /* Clip against Z plane */ void GouraudPolygon_ClipWithZ(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Z_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Z_Test(nextVertexPtr); Clip_Z_OutputXYZ Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } /* Clip against negative X plane */ static void GouraudPolygon_Norm_ClipWithNegativeX(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_NX_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_NX_Test(nextVertexPtr); Clip_NX_OutputXYZ Clip_OutputI Clip_LoopEnd(VerticesBuffer) } static void GouraudPolygon_Wide_ClipWithNegativeX(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_NX_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_Wide_NX_Test(nextVertexPtr); Clip_Wide_NX_OutputXYZ Clip_OutputI Clip_LoopEnd(VerticesBuffer) } /* Clip against positive Y plane*/ static void GouraudPolygon_Norm_ClipWithPositiveY(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_PY_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_PY_Test(nextVertexPtr); Clip_PY_OutputXYZ Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } static void GouraudPolygon_Wide_ClipWithPositiveY(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_PY_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Wide_PY_Test(nextVertexPtr); Clip_Wide_PY_OutputXYZ Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } /* Clip against negative Y plane*/ static void GouraudPolygon_Norm_ClipWithNegativeY(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_NY_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_NY_Test(nextVertexPtr); Clip_NY_OutputXYZ Clip_OutputI Clip_LoopEnd(VerticesBuffer) } static void GouraudPolygon_Wide_ClipWithNegativeY(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_NY_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_Wide_NY_Test(nextVertexPtr); Clip_Wide_NY_OutputXYZ Clip_OutputI Clip_LoopEnd(VerticesBuffer) } /* Clip against positive X plane */ static void GouraudPolygon_Norm_ClipWithPositiveX(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_PX_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_PX_Test(nextVertexPtr); Clip_PX_OutputXYZ Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } static void GouraudPolygon_Wide_ClipWithPositiveX(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_PX_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Wide_PX_Test(nextVertexPtr); Clip_Wide_PX_OutputXYZ Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } /*KJL*************** * TEXTURED POLYGON * ***************KJL*/ /* Clip against Z plane */ void TexturedPolygon_ClipWithZ(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Z_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Z_Test(nextVertexPtr); Clip_Z_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } /* Clip against negative X plane */ static void TexturedPolygon_Norm_ClipWithNegativeX(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_NX_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_NX_Test(nextVertexPtr); Clip_NX_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd(VerticesBuffer) } static void TexturedPolygon_Wide_ClipWithNegativeX(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_NX_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_Wide_NX_Test(nextVertexPtr); Clip_Wide_NX_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd(VerticesBuffer) } /* Clip against positive Y plane*/ static void TexturedPolygon_Norm_ClipWithPositiveY(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_PY_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_PY_Test(nextVertexPtr); Clip_PY_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } static void TexturedPolygon_Wide_ClipWithPositiveY(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_PY_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Wide_PY_Test(nextVertexPtr); Clip_Wide_PY_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } /* Clip against negative Y plane*/ static void TexturedPolygon_Norm_ClipWithNegativeY(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_NY_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_NY_Test(nextVertexPtr); Clip_NY_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd(VerticesBuffer) } static void TexturedPolygon_Wide_ClipWithNegativeY(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_NY_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_Wide_NY_Test(nextVertexPtr); Clip_Wide_NY_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd(VerticesBuffer) } /* Clip against positive X plane */ static void TexturedPolygon_Norm_ClipWithPositiveX(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_PX_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_PX_Test(nextVertexPtr); Clip_PX_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } static void TexturedPolygon_Wide_ClipWithPositiveX(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_PX_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Wide_PX_Test(nextVertexPtr); Clip_Wide_PX_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } /*KJL************************ * GOURAUD TEXTURED POLYGONS * ************************KJL*/ /* Clip against Z plane */ void GouraudTexturedPolygon_ClipWithZ(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Z_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Z_Test(nextVertexPtr); Clip_Z_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } /* Clip against negative X plane */ static void GouraudTexturedPolygon_Norm_ClipWithNegativeX(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_NX_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_NX_Test(nextVertexPtr); Clip_NX_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd(VerticesBuffer) } static void GouraudTexturedPolygon_Wide_ClipWithNegativeX(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_NX_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_Wide_NX_Test(nextVertexPtr); Clip_Wide_NX_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd(VerticesBuffer) } /* Clip against positive Y plane*/ static void GouraudTexturedPolygon_Norm_ClipWithPositiveY(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_PY_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_PY_Test(nextVertexPtr); Clip_PY_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } static void GouraudTexturedPolygon_Wide_ClipWithPositiveY(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_PY_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Wide_PY_Test(nextVertexPtr); Clip_Wide_PY_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } /* Clip against negative Y plane*/ static void GouraudTexturedPolygon_Norm_ClipWithNegativeY(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_NY_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_NY_Test(nextVertexPtr); Clip_NY_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd(VerticesBuffer) } static void GouraudTexturedPolygon_Wide_ClipWithNegativeY(void) { RENDERVERTEX *curVertexPtr = (RenderPolygon.Vertices); RENDERVERTEX *outputVerticesPtr = VerticesBuffer; int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_NY_Test(curVertexPtr); Clip_LoopStart((RenderPolygon.Vertices)) Clip_Wide_NY_Test(nextVertexPtr); Clip_Wide_NY_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd(VerticesBuffer) } /* Clip against positive X plane */ static void GouraudTexturedPolygon_Norm_ClipWithPositiveX(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_PX_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_PX_Test(nextVertexPtr); Clip_PX_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } static void GouraudTexturedPolygon_Wide_ClipWithPositiveX(void) { RENDERVERTEX *curVertexPtr = VerticesBuffer; RENDERVERTEX *outputVerticesPtr = (RenderPolygon.Vertices); int verticesLeft = RenderPolygon.NumberOfVertices; int numberOfPointsOutputted=0; int curVertexInside = Clip_Wide_PX_Test(curVertexPtr); Clip_LoopStart(VerticesBuffer) Clip_Wide_PX_Test(nextVertexPtr); Clip_Wide_PX_OutputXYZ Clip_OutputUV Clip_OutputI Clip_LoopEnd((RenderPolygon.Vertices)) } int PolygonWithinFrustrum(POLYHEADER *polyPtr) { char inFrustrumFlag=0; char noClippingFlag=INSIDE_FRUSTRUM; int *vertexNumberPtr = &polyPtr->Poly1stPt; if (polyPtr->PolyFlags & iflag_notvis) return 0; RenderPolygon.NumberOfVertices=0; while(*vertexNumberPtr != Term) { int vertexNumber = *vertexNumberPtr++; inFrustrumFlag |= FrustrumFlagForVertex[vertexNumber]; noClippingFlag &= FrustrumFlagForVertex[vertexNumber]; /* count the number of points in the polygon; this is used for all the loops that follow */ RenderPolygon.NumberOfVertices++; } if (inFrustrumFlag != INSIDE_FRUSTRUM) return 0; /* at this point we know that the poly is inside the view frustrum */ /* if not a sprite, test direction of poly */ if (!( (Global_ShapeHeaderPtr->shapeflags&ShapeFlag_Sprite) || (polyPtr->PolyFlags & iflag_no_bfc) )) { VECTORCH pop; VECTORCH *normalPtr = (VECTORCH*)(Global_ShapeNormals + polyPtr->PolyNormalIndex); #if 1 if(Global_ODB_Ptr->ObMorphCtrl) { extern MORPHDISPLAY MorphDisplay; SHAPEHEADER *shape1Ptr; VECTORCH *shape1PointsPtr; VECTORCH *shape2PointsPtr; /* Set up the morph data */ GetMorphDisplay(&MorphDisplay, Global_ODB_Ptr); shape1Ptr = MorphDisplay.md_sptr1; if(MorphDisplay.md_lerp == 0x0000) { shape1PointsPtr = (VECTORCH *)*shape1Ptr->points; pop = shape1PointsPtr[polyPtr->Poly1stPt]; } else if(MorphDisplay.md_lerp == 0xffff) { SHAPEHEADER *shape2Ptr = MorphDisplay.md_sptr2; shape2PointsPtr = (VECTORCH *)*shape2Ptr->points; pop = shape2PointsPtr[polyPtr->Poly1stPt]; } else { SHAPEHEADER *shape2Ptr = MorphDisplay.md_sptr2; shape1PointsPtr = (VECTORCH *)(*shape1Ptr->points); shape2PointsPtr = (VECTORCH *)(*shape2Ptr->points); { VECTORCH vertex1 = shape1PointsPtr[polyPtr->Poly1stPt]; VECTORCH vertex2 = shape2PointsPtr[polyPtr->Poly1stPt]; if( (vertex1.vx == vertex2.vx && vertex1.vy == vertex2.vy && vertex1.vz == vertex2.vz) ) { pop = vertex1; } else { /* KJL 15:27:20 05/22/97 - I've changed this to speed things up, If a vertex component has a magnitude greater than 32768 things will go wrong. */ pop.vx = vertex1.vx + (((vertex2.vx-vertex1.vx)*MorphDisplay.md_lerp)>>16); pop.vy = vertex1.vy + (((vertex2.vy-vertex1.vy)*MorphDisplay.md_lerp)>>16); pop.vz = vertex1.vz + (((vertex2.vz-vertex1.vz)*MorphDisplay.md_lerp)>>16); } } } } else #endif { /* Get the 1st polygon point as the POP */ VECTORCH *pointsArray = (VECTORCH*)(Global_ShapePoints); pop = pointsArray[polyPtr->Poly1stPt]; } pop.vx -= LocalView.vx; pop.vy -= LocalView.vy; pop.vz -= LocalView.vz; if (Dot(&pop, normalPtr)>0) return 0; } if (noClippingFlag == INSIDE_FRUSTRUM) return 2; /* yes, we need to draw poly */ return 1; } int PolygonShouldBeDrawn(POLYHEADER *polyPtr) { /* at this point we know that the poly is inside the view frustrum */ if (polyPtr->PolyFlags & iflag_notvis) return 0; #if 1 /* if not a sprite, test direction of poly */ if (!( (Global_ShapeHeaderPtr->shapeflags&ShapeFlag_Sprite) || (polyPtr->PolyFlags & iflag_no_bfc) )) { /* KJL 16:49:14 7/10/97 - ***** MORPHED NORMALS SUPPORT NOT YET ADDED ***** */ VECTORCH pop; VECTORCH *normalPtr = (VECTORCH*)(Global_ShapeNormals + polyPtr->PolyNormalIndex); VECTORCH *pointsArray = (VECTORCH*)(Global_ShapePoints); /* Get the 1st polygon point as the POP */ pop.vx = pointsArray[polyPtr->Poly1stPt].vx - LocalView.vx; pop.vy = pointsArray[polyPtr->Poly1stPt].vy - LocalView.vy; pop.vz = pointsArray[polyPtr->Poly1stPt].vz - LocalView.vz; if (Dot(&pop, normalPtr)>0) return 0; } #endif #if 0 { int *vertexNumberPtr = &polyPtr->Poly1stPt; RenderPolygon.NumberOfVertices=0; while(*vertexNumberPtr++ != Term) { /* count the number of points in the polygon; this is used for all the loops that follow */ RenderPolygon.NumberOfVertices++; } } #elif 0 RenderPolygon.NumberOfVertices = 3; #else { int *vertexNumberPtr = &polyPtr->Poly1stPt; if (vertexNumberPtr[3] == Term) { RenderPolygon.NumberOfVertices = 3; } else { RenderPolygon.NumberOfVertices = 4; } } #endif return 2; } /* KJL 16:18:59 7/7/97 - simple vertex test to be used in first pass of subdividing code */ static int VertexWithin_Norm_Frustrum(RENDERVERTEX *vertexPtr) { int vertexFlag = 0; if(Clip_Z_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_Z_PLANE; if(Clip_PX_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_PX_PLANE; if(Clip_NX_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_NX_PLANE; if(Clip_PY_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_PY_PLANE; if(Clip_NY_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_NY_PLANE; return vertexFlag; } static int VertexWithin_Wide_Frustrum(RENDERVERTEX *vertexPtr) { int vertexFlag = 0; if(Clip_Z_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_Z_PLANE; if(Clip_Wide_PX_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_PX_PLANE; if(Clip_Wide_NX_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_NX_PLANE; if(Clip_Wide_PY_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_PY_PLANE; if(Clip_Wide_NY_Test(vertexPtr)) vertexFlag |= INSIDE_FRUSTRUM_NY_PLANE; return vertexFlag; } /* KJL 15:32:52 7/17/97 - Test to see if an object is in the view frustrum */ static int ObjectWithin_Norm_Frustrum(DISPLAYBLOCK *dbPtr) { // LOCALASSERT(dbPtr->ObShapeData->shaperadius); #if FAR_Z_CLIP if(dbPtr->ObView.vz-dbPtr->ObShapeData->shaperadius<=FAR_Z_CLIP_RANGE) #endif if (dbPtr->ObView.vz+dbPtr->ObShapeData->shaperadius>=ZCLIPPINGVALUE) { /* scale radius by square root of 2 */ int radius = MUL_FIXED(92682,dbPtr->ObShapeData->shaperadius); if ((dbPtr->ObView.vx-dbPtr->ObView.vz)<=radius) if ((-dbPtr->ObView.vx-dbPtr->ObView.vz)<=radius) if ((dbPtr->ObView.vy-dbPtr->ObView.vz)<=radius) if ((-dbPtr->ObView.vy-dbPtr->ObView.vz)<=radius) return 1; } return 0; } static int ObjectCompletelyWithin_Norm_Frustrum(DISPLAYBLOCK *dbPtr) { // LOCALASSERT(dbPtr->ObShapeData->shaperadius); if (dbPtr->ObView.vz-dbPtr->ObShapeData->shaperadius>=ZCLIPPINGVALUE) { /* scale radius by square root of 2 */ int radius = MUL_FIXED(92682,dbPtr->ObShapeData->shaperadius); if ((dbPtr->ObView.vz-dbPtr->ObView.vx)>=radius) if ((dbPtr->ObView.vz+dbPtr->ObView.vx)>=radius) if ((dbPtr->ObView.vz-dbPtr->ObView.vy)>=radius) if ((dbPtr->ObView.vz+dbPtr->ObView.vy)>=radius) return 1; } return 0; } static int ObjectCompletelyWithin_Wide_Frustrum(DISPLAYBLOCK *dbPtr) { return 0; } static int ObjectWithin_Wide_Frustrum(DISPLAYBLOCK *dbPtr) { if (dbPtr->ObView.vz+dbPtr->ObShapeData->shaperadius>=ZCLIPPINGVALUE) { /* scale radius by square root of 5 */ int radius = MUL_FIXED(146543,dbPtr->ObShapeData->shaperadius); if ((dbPtr->ObView.vx-2*dbPtr->ObView.vz)<=radius) if ((-dbPtr->ObView.vx-2*dbPtr->ObView.vz)<=radius) if ((dbPtr->ObView.vy-2*dbPtr->ObView.vz)<=radius) if ((-dbPtr->ObView.vy-2*dbPtr->ObView.vz)<=radius) return 1; } return 0; } char FrustrumFlagForVertex[maxrotpts]; void TestVerticesWith_Norm_Frustrum(void) { int v = Global_ShapeHeaderPtr->numpoints; GLOBALASSERT(v>0); while(v--) { char vertexFlag = 0; #if FAR_Z_CLIP if(ZCLIPPINGVALUE <= RotatedPts[v].vz && RotatedPts[v].vz<=FAR_Z_CLIP_RANGE) #else if(ZCLIPPINGVALUE <= RotatedPts[v].vz) #endif vertexFlag |= INSIDE_FRUSTRUM_Z_PLANE; if(-RotatedPts[v].vx <= RotatedPts[v].vz) vertexFlag |= INSIDE_FRUSTRUM_PX_PLANE; if(RotatedPts[v].vx <= RotatedPts[v].vz) vertexFlag |= INSIDE_FRUSTRUM_NX_PLANE; if(-RotatedPts[v].vy <= RotatedPts[v].vz) vertexFlag |= INSIDE_FRUSTRUM_PY_PLANE; if(RotatedPts[v].vy <= RotatedPts[v].vz) vertexFlag |= INSIDE_FRUSTRUM_NY_PLANE; FrustrumFlagForVertex[v] = vertexFlag; } } void TestVerticesWith_Wide_Frustrum(void) { int v = Global_ShapeHeaderPtr->numpoints; GLOBALASSERT(v>0); while(v--) { char vertexFlag = 0; if(ZCLIPPINGVALUE <= RotatedPts[v].vz) vertexFlag |= INSIDE_FRUSTRUM_Z_PLANE; if(-RotatedPts[v].vx <= RotatedPts[v].vz*2) vertexFlag |= INSIDE_FRUSTRUM_PX_PLANE; if(RotatedPts[v].vx <= RotatedPts[v].vz*2) vertexFlag |= INSIDE_FRUSTRUM_NX_PLANE; if(-RotatedPts[v].vy <= RotatedPts[v].vz*2) vertexFlag |= INSIDE_FRUSTRUM_PY_PLANE; if(RotatedPts[v].vy <= RotatedPts[v].vz*2) vertexFlag |= INSIDE_FRUSTRUM_NY_PLANE; FrustrumFlagForVertex[v] = vertexFlag; } } int DecalWithinFrustrum(DECAL *decalPtr) { char inFrustrumFlag; char noClippingFlag; if(ModuleCurrVisArray[decalPtr->ModuleIndex] != 2) return 0; inFrustrumFlag=0; noClippingFlag=INSIDE_FRUSTRUM; { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[0]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[1]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[2]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[3]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } if (inFrustrumFlag != INSIDE_FRUSTRUM) return 0; if (noClippingFlag == INSIDE_FRUSTRUM) return 2; /* yes, we need to draw poly */ return 1; } int QuadWithinFrustrum(void) { char inFrustrumFlag; char noClippingFlag; inFrustrumFlag=0; noClippingFlag=INSIDE_FRUSTRUM; { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[0]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[1]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[2]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[3]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } if (inFrustrumFlag != INSIDE_FRUSTRUM) return 0; if (noClippingFlag == INSIDE_FRUSTRUM) return 2; /* yes, we need to draw poly */ return 1; } int TriangleWithinFrustrum(void) { char inFrustrumFlag; char noClippingFlag; inFrustrumFlag=0; noClippingFlag=INSIDE_FRUSTRUM; { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[0]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[1]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } { int vertexFlag = VertexWithinFrustrum(&VerticesBuffer[2]); inFrustrumFlag |= vertexFlag; noClippingFlag &= vertexFlag; } if (inFrustrumFlag != INSIDE_FRUSTRUM) return 0; if (noClippingFlag == INSIDE_FRUSTRUM) return 2; /* yes, we need to draw poly */ return 1; }