00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #include <assert.h>
00068 #include <string.h>
00069
00070 #include "TClip.h"
00071 #include "engine.h"
00072 #include "bitmap._h"
00073
00074 #include "list.h"
00075 #include "ram.h"
00076
00077 #include "timer.h"
00078
00079 TIMER_VARS(TClip_Triangle);
00080
00081
00082
00083 typedef enum
00084 {
00085 BACK_CLIPPING_PLANE = 0,
00086 LEFT_CLIPPING_PLANE,
00087 RIGHT_CLIPPING_PLANE,
00088 TOP_CLIPPING_PLANE,
00089 BOTTOM_CLIPPING_PLANE,
00090 NUM_CLIPPING_PLANES
00091 } geTClip_ClippingPlane;
00092
00093
00094 #define V_ALL_IN (0)
00095 #define V0_OUT (1)
00096 #define V1_OUT (2)
00097 #define V2_OUT (4)
00098
00099
00100 #define LINEAR_INTERPOLATE(a,l,h) ((l)+(((h)-(l))*(a)))
00101
00102 #define RASTERIZECC
00103 typedef void (RASTERIZECC *geTClip_Rasterize_FuncPtr) (const GE_LVertex * TriVtx);
00104
00105 typedef struct geTClip_StaticsType
00106 {
00107 geFloat LeftEdge;
00108 geFloat RightEdge;
00109 geFloat TopEdge;
00110 geFloat BottomEdge;
00111 geFloat BackEdge;
00112
00113 DRV_Driver * Driver;
00114 geEngine *Engine;
00115 const geBitmap *Bitmap;
00116 geRDriver_THandle * THandle;
00117
00118 geTClip_Rasterize_FuncPtr RasterizeFunc;
00119
00120 uint32 RenderFlags;
00121
00122 } geTClip_StaticsType;
00123
00124
00125
00126 static void RASTERIZECC geTClip_Rasterize_Tex(const GE_LVertex * TriVtx);
00127 static void RASTERIZECC geTClip_Rasterize_Gou(const GE_LVertex * TriVtx);
00128 static void GENESISCC geTClip_Split(GE_LVertex *NewVertex,const GE_LVertex *V1,const GE_LVertex *V2,int ClippingPlane);
00129 static void GENESISCC geTClip_TrianglePlane(const GE_LVertex * zTriVertex,geTClip_ClippingPlane ClippingPlane);
00130 static void GENESISCC geTClip_TrianglePlane_Old(const GE_LVertex * zTriVertex,geTClip_ClippingPlane ClippingPlane);
00131
00132
00133
00134 static Link * geTClip_Link = NULL;
00135 static geTClip_StaticsType geTClip_Statics;
00136 static uint32 ActiveRenderFlags = 0;
00137
00138
00139
00140
00141 void GENESISCC geTClip_SetRenderFlags(uint32 newflags)
00142 {
00143 geTClip_Statics.RenderFlags = newflags;
00144 ActiveRenderFlags = newflags;
00145 return;
00146 }
00147
00148 geBoolean GENESISCC geTClip_Push(void)
00149 {
00150 geTClip_StaticsType * TCI;
00151
00152 geTClip_Statics.RenderFlags = ActiveRenderFlags;
00153
00154 if ( ! geTClip_Link )
00155 {
00156 List_Start();
00157 geTClip_Link = Link_Create();
00158 if ( ! geTClip_Link )
00159 return GE_FALSE;
00160 }
00161
00162 TCI = geRam_Allocate(sizeof(geTClip_StaticsType));
00163 if ( ! TCI )
00164 return GE_FALSE;
00165 memcpy(TCI,&geTClip_Statics,sizeof(geTClip_StaticsType));
00166
00167 Link_Push( geTClip_Link , TCI );
00168
00169 geTClip_Statics.RenderFlags = 0;
00170
00171 return GE_TRUE;
00172 }
00173
00174 geBoolean GENESISCC geTClip_Pop(void)
00175 {
00176 geTClip_StaticsType * TCI;
00177 if ( ! geTClip_Link )
00178 return GE_FALSE;
00179 TCI = Link_Pop( geTClip_Link );
00180 if ( ! TCI )
00181 return GE_FALSE;
00182 memcpy(&geTClip_Statics,TCI,sizeof(geTClip_StaticsType));
00183 geRam_Free(TCI);
00184
00185 if ( ! Link_Peek(geTClip_Link) )
00186 {
00187 Link_Destroy(geTClip_Link);
00188 geTClip_Link = NULL;
00189 List_Stop();
00190 }
00191
00192 ActiveRenderFlags = geTClip_Statics.RenderFlags;
00193
00194 return GE_TRUE;
00195 }
00196
00197 geBoolean GENESISCC geTClip_SetTexture(const geBitmap * Bitmap)
00198 {
00199 geTClip_Statics.Bitmap = Bitmap;
00200 if ( Bitmap )
00201 {
00202 geTClip_Statics.THandle = geBitmap_GetTHandle(Bitmap);
00203 assert(geTClip_Statics.THandle);
00204 geTClip_Statics.RasterizeFunc = geTClip_Rasterize_Tex;
00205 }
00206 else
00207 {
00208 geTClip_Statics.THandle = NULL;
00209 geTClip_Statics.RasterizeFunc = geTClip_Rasterize_Gou;
00210 }
00211 return GE_TRUE;
00212 }
00213
00214 void GENESISCC geTClip_SetupEdges(
00215 geEngine *Engine,
00216 geFloat LeftEdge,
00217 geFloat RightEdge,
00218 geFloat TopEdge ,
00219 geFloat BottomEdge,
00220 geFloat BackEdge)
00221 {
00222 assert(Engine);
00223 memset(&geTClip_Statics,0,sizeof(geTClip_Statics));
00224 geTClip_Statics.Engine = Engine;
00225 geTClip_Statics.Driver = Engine->DriverInfo.RDriver;
00226 geTClip_Statics.LeftEdge = LeftEdge;
00227 geTClip_Statics.RightEdge = RightEdge;
00228 geTClip_Statics.TopEdge = TopEdge;
00229 geTClip_Statics.BottomEdge = BottomEdge;
00230 geTClip_Statics.BackEdge = BackEdge;
00231 }
00232
00233 void geTClip_Done(void)
00234 {
00235 TIMER_REPORT(TClip_Triangle);
00236 }
00237
00238 void GENESISCC geTClip_Triangle(const GE_LVertex TriVertex[3])
00239 {
00240
00241 TIMER_P(TClip_Triangle);
00242
00243 #if 1
00244 geTClip_TrianglePlane(TriVertex,BACK_CLIPPING_PLANE);
00245
00246 #else
00247 geTClip_TrianglePlane_Old(TriVertex,BACK_CLIPPING_PLANE);
00248 #endif
00249
00250 TIMER_Q(TClip_Triangle);
00251 }
00252
00253
00254
00255 static void RASTERIZECC geTClip_Rasterize_Tex(const GE_LVertex * TriVtx)
00256 {
00257 geTClip_Statics.Driver->RenderMiscTexturePoly((DRV_TLVertex *)TriVtx,
00258 3,geTClip_Statics.THandle, ActiveRenderFlags);
00259 }
00260
00261 static void RASTERIZECC geTClip_Rasterize_Gou(const GE_LVertex * TriVtx)
00262 {
00263 geTClip_Statics.Driver->RenderGouraudPoly((DRV_TLVertex *)TriVtx,3,ActiveRenderFlags);
00264 }
00265
00266 static void GENESISCC geTClip_Rasterize(const GE_LVertex * TriVtx)
00267 {
00268
00269
00270
00271
00272 if ( geTClip_Statics.THandle )
00273 {
00274 geTClip_Statics.Driver->RenderMiscTexturePoly((DRV_TLVertex *)TriVtx,
00275 3,geTClip_Statics.THandle,ActiveRenderFlags);
00276 }
00277 else
00278 {
00279 geTClip_Statics.Driver->RenderGouraudPoly((DRV_TLVertex *)TriVtx,
00280 3,ActiveRenderFlags);
00281 }
00282 }
00283
00284
00285
00286 static void GENESISCC geTClip_Split(GE_LVertex *NewVertex,const GE_LVertex *V1,const GE_LVertex *V2,int ClippingPlane)
00287 {
00288 geFloat Ratio=0.0f;
00289 geFloat OneOverZ1,OneOverZ2;
00290
00291 #ifdef ONE_OVER_Z_PIPELINE
00292
00293 OneOverZ1 = V1->Z;
00294 OneOverZ2 = V2->Z;
00295 #else
00296 OneOverZ1 = 1.0f/V1->Z;
00297 OneOverZ2 = 1.0f/V2->Z;
00298 #endif
00299
00300 switch (ClippingPlane)
00301 {
00302 case (BACK_CLIPPING_PLANE):
00303 assert((V2->Z - V1->Z)!=0.0f);
00304 Ratio = ((1.0f/geTClip_Statics.BackEdge) - OneOverZ2)/( OneOverZ1 - OneOverZ2 );
00305
00306 NewVertex->X = LINEAR_INTERPOLATE(Ratio,(V2->X),(V1->X));
00307 NewVertex->Y = LINEAR_INTERPOLATE(Ratio,(V2->Y),(V1->Y));
00308 #ifdef ONE_OVER_Z_PIPELINE
00309 NewVertex->Z = 1.0f/ geTClip_Statics.BackEdge;
00310 #else
00311 NewVertex->Z = geTClip_Statics.BackEdge;
00312 #endif
00313
00314 break;
00315 case (LEFT_CLIPPING_PLANE):
00316 assert((V2->X - V1->X)!=0.0f);
00317 Ratio = (geTClip_Statics.LeftEdge - V2->X)/( V1->X - V2->X);
00318
00319 NewVertex->X = geTClip_Statics.LeftEdge;
00320 NewVertex->Y = LINEAR_INTERPOLATE(Ratio,(V2->Y),(V1->Y));
00321 #ifdef ONE_OVER_Z_PIPELINE
00322 NewVertex->Z = LINEAR_INTERPOLATE(Ratio,OneOverZ2,OneOverZ1);
00323 #else
00324 NewVertex->Z = 1.0f/LINEAR_INTERPOLATE(Ratio,OneOverZ2,OneOverZ1);
00325 #endif
00326
00327 break;
00328 case (RIGHT_CLIPPING_PLANE):
00329 assert((V2->X - V1->X)!=0.0f);
00330 Ratio = (geTClip_Statics.RightEdge - V2->X)/( V1->X - V2->X);
00331
00332 NewVertex->X = geTClip_Statics.RightEdge;
00333 NewVertex->Y = LINEAR_INTERPOLATE(Ratio,(V2->Y),(V1->Y));
00334 #ifdef ONE_OVER_Z_PIPELINE
00335 NewVertex->Z = LINEAR_INTERPOLATE(Ratio,OneOverZ2,OneOverZ1);
00336 #else
00337 NewVertex->Z = 1.0f/LINEAR_INTERPOLATE(Ratio,OneOverZ2,OneOverZ1);
00338 #endif
00339
00340 break;
00341 case (TOP_CLIPPING_PLANE):
00342 assert((V2->Y - V1->Y)!=0.0f);
00343 Ratio = (geTClip_Statics.TopEdge - V2->Y)/( V1->Y - V2->Y);
00344
00345 NewVertex->X = LINEAR_INTERPOLATE(Ratio,(V2->X),(V1->X));
00346 NewVertex->Y = geTClip_Statics.TopEdge;
00347 #ifdef ONE_OVER_Z_PIPELINE
00348 NewVertex->Z = LINEAR_INTERPOLATE(Ratio,OneOverZ2,OneOverZ1);
00349 #else
00350 NewVertex->Z = 1.0f/LINEAR_INTERPOLATE(Ratio,OneOverZ2,OneOverZ1);
00351 #endif
00352
00353 break;
00354 case (BOTTOM_CLIPPING_PLANE):
00355 assert((V2->Y - V1->Y)!=0.0f);
00356 Ratio = (geTClip_Statics.BottomEdge - V2->Y)/( V1->Y - V2->Y);
00357
00358 NewVertex->X = LINEAR_INTERPOLATE(Ratio,(V2->X),(V1->X));
00359 NewVertex->Y = geTClip_Statics.BottomEdge;
00360 #ifdef ONE_OVER_Z_PIPELINE
00361 NewVertex->Z = LINEAR_INTERPOLATE(Ratio,OneOverZ2,OneOverZ1);
00362 #else
00363 NewVertex->Z = 1.0f/LINEAR_INTERPOLATE(Ratio,OneOverZ2,OneOverZ1);
00364 #endif
00365
00366 break;
00367 }
00368
00369
00370 {
00371 geFloat OneOverZ1_Ratio;
00372 geFloat OneOverZ2_Ratio;
00373 #ifdef ONE_OVER_Z_PIPELINE
00374 OneOverZ1 *= 1.0f / NewVertex->Z;
00375 OneOverZ2 *= 1.0f / NewVertex->Z;
00376 #else
00377 OneOverZ1 *= NewVertex->Z;
00378 OneOverZ2 *= NewVertex->Z;
00379 #endif
00380 OneOverZ1_Ratio = OneOverZ1 * Ratio;
00381 OneOverZ2_Ratio = OneOverZ2 * Ratio;
00382
00383
00384
00385
00386 NewVertex->r =(V2->r * OneOverZ2) + (V1->r * OneOverZ1_Ratio) - (V2->r * OneOverZ2_Ratio);
00387 NewVertex->g =(V2->g * OneOverZ2) + (V1->g * OneOverZ1_Ratio) - (V2->g * OneOverZ2_Ratio);
00388 NewVertex->b =(V2->b * OneOverZ2) + (V1->b * OneOverZ1_Ratio) - (V2->b * OneOverZ2_Ratio);
00389 NewVertex->a =(V2->a * OneOverZ2) + (V1->a * OneOverZ1_Ratio) - (V2->a * OneOverZ2_Ratio);
00390 NewVertex->u =(V2->u * OneOverZ2) + (V1->u * OneOverZ1_Ratio) - (V2->u * OneOverZ2_Ratio);
00391 NewVertex->v =(V2->v * OneOverZ2) + (V1->v * OneOverZ1_Ratio) - (V2->v * OneOverZ2_Ratio);
00392 }
00393
00394 }
00395
00396
00397
00398
00399 static void GENESISCC geTClip_TrianglePlane(const GE_LVertex * TriVertex,
00400 geTClip_ClippingPlane ClippingPlane)
00401 {
00402 uint32 OutBits = 0;
00403
00404 switch(ClippingPlane)
00405 {
00406 case BACK_CLIPPING_PLANE:
00407
00408 OutBits |= (TriVertex[0].Z < geTClip_Statics.BackEdge) ? V0_OUT : 0;
00409 OutBits |= (TriVertex[1].Z < geTClip_Statics.BackEdge) ? V1_OUT : 0;
00410 OutBits |= (TriVertex[2].Z < geTClip_Statics.BackEdge) ? V2_OUT : 0;
00411
00412 case LEFT_CLIPPING_PLANE:
00413
00414 OutBits |= (TriVertex[0].X < geTClip_Statics.LeftEdge) ? (V0_OUT<<3) : 0;
00415 OutBits |= (TriVertex[1].X < geTClip_Statics.LeftEdge) ? (V1_OUT<<3) : 0;
00416 OutBits |= (TriVertex[2].X < geTClip_Statics.LeftEdge) ? (V2_OUT<<3) : 0;
00417
00418 case RIGHT_CLIPPING_PLANE:
00419
00420 OutBits |= (TriVertex[0].X > geTClip_Statics.RightEdge) ? (V0_OUT<<6) : 0;
00421 OutBits |= (TriVertex[1].X > geTClip_Statics.RightEdge) ? (V1_OUT<<6) : 0;
00422 OutBits |= (TriVertex[2].X > geTClip_Statics.RightEdge) ? (V2_OUT<<6) : 0;
00423
00424 case TOP_CLIPPING_PLANE:
00425
00426 OutBits |= (TriVertex[0].Y < geTClip_Statics.TopEdge) ? (V0_OUT<<9) : 0;
00427 OutBits |= (TriVertex[1].Y < geTClip_Statics.TopEdge) ? (V1_OUT<<9) : 0;
00428 OutBits |= (TriVertex[2].Y < geTClip_Statics.TopEdge) ? (V2_OUT<<9) : 0;
00429
00430 case BOTTOM_CLIPPING_PLANE:
00431
00432 OutBits |= (TriVertex[0].Y > geTClip_Statics.BottomEdge) ? (V0_OUT<<12) : 0;
00433 OutBits |= (TriVertex[1].Y > geTClip_Statics.BottomEdge) ? (V1_OUT<<12) : 0;
00434 OutBits |= (TriVertex[2].Y > geTClip_Statics.BottomEdge) ? (V2_OUT<<12) : 0;
00435
00436 case NUM_CLIPPING_PLANES:
00437 break;
00438 }
00439
00440 if ( OutBits )
00441 {
00442 GE_LVertex NewTriVertex[3];
00443
00444 memset(NewTriVertex, '\0',sizeof(GE_LVertex)*(3));
00445
00446 ClippingPlane = 0;
00447 for(;;)
00448 {
00449 assert(ClippingPlane < NUM_CLIPPING_PLANES);
00450
00451 switch ( OutBits & 7 )
00452 {
00453 case (V_ALL_IN):
00454 OutBits >>= 3;
00455 ClippingPlane ++;
00456 continue;
00457
00458
00459
00460 case (V0_OUT):
00461 NewTriVertex[0] = TriVertex[2];
00462 geTClip_Split(&(NewTriVertex[1]),TriVertex+0,TriVertex+2,ClippingPlane);
00463 NewTriVertex[2] = TriVertex[1];
00464
00465 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00466
00467 NewTriVertex[0] = NewTriVertex[1];
00468 geTClip_Split(&(NewTriVertex[1]),TriVertex+0,TriVertex+1,ClippingPlane);
00469
00470
00471
00472
00473
00474 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00475 return;
00476
00477 case (V1_OUT):
00478 NewTriVertex[0] = TriVertex[0];
00479 geTClip_Split(&(NewTriVertex[1]),TriVertex+0,TriVertex+1,ClippingPlane);
00480 NewTriVertex[2] = TriVertex[2];
00481
00482 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00483
00484 NewTriVertex[0] = NewTriVertex[1];
00485 geTClip_Split(&(NewTriVertex[1]),TriVertex+1,TriVertex+2,ClippingPlane);
00486
00487 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00488 return;
00489
00490 case (V0_OUT + V1_OUT):
00491 NewTriVertex[0] = TriVertex[2];
00492 geTClip_Split(&(NewTriVertex[1]),TriVertex+0,TriVertex+2,ClippingPlane);
00493 geTClip_Split(&(NewTriVertex[2]),TriVertex+1,TriVertex+2,ClippingPlane);
00494
00495 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00496 return;
00497
00498 case (V2_OUT):
00499 NewTriVertex[0] = TriVertex[1];
00500 geTClip_Split(&(NewTriVertex[1]),TriVertex+1,TriVertex+2,ClippingPlane);
00501 NewTriVertex[2] = TriVertex[0];
00502
00503 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00504
00505 NewTriVertex[0] = NewTriVertex[1];
00506 geTClip_Split(&(NewTriVertex[1]),TriVertex+0,TriVertex+2,ClippingPlane);
00507
00508 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00509 return;
00510
00511 case (V2_OUT + V0_OUT):
00512 NewTriVertex[0] = TriVertex[1];
00513 geTClip_Split(&(NewTriVertex[1]),TriVertex+1,TriVertex+2,ClippingPlane);
00514 geTClip_Split(&(NewTriVertex[2]),TriVertex+0,TriVertex+1,ClippingPlane);
00515
00516 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00517 return;
00518
00519 case (V2_OUT + V1_OUT):
00520 NewTriVertex[0] = TriVertex[0];
00521 geTClip_Split(&(NewTriVertex[1]),TriVertex+0,TriVertex+1,ClippingPlane);
00522 geTClip_Split(&(NewTriVertex[2]),TriVertex+0,TriVertex+2,ClippingPlane);
00523
00524 geTClip_TrianglePlane(NewTriVertex,ClippingPlane+1);
00525 return;
00526
00527 case (V2_OUT + V1_OUT + V0_OUT):
00528
00529 return;
00530 }
00531 }
00532 }
00533
00534 #if 0 // {
00535
00536
00537
00538 geTClip_Statics.RasterizeFunc(TriVertex);
00539
00540 #else //}{
00541
00542 if ( geTClip_Statics.THandle )
00543 {
00544 geTClip_Statics.Driver->RenderMiscTexturePoly((DRV_TLVertex *)TriVertex,
00545 3,geTClip_Statics.THandle,ActiveRenderFlags);
00546 }
00547 else
00548 {
00549 geTClip_Statics.Driver->RenderGouraudPoly((DRV_TLVertex *)TriVertex,3,ActiveRenderFlags);
00550 }
00551
00552 #endif //}
00553
00554 }
00555
00556
00557 void GENESISCC geTClip_UnclippedTriangle(const GE_LVertex TriVertex[3])
00558 {
00559 if ( geTClip_Statics.THandle )
00560 {
00561 geTClip_Statics.Driver->RenderMiscTexturePoly((DRV_TLVertex *)TriVertex,
00562 3,geTClip_Statics.THandle,ActiveRenderFlags);
00563 }
00564 else
00565 {
00566 geTClip_Statics.Driver->RenderGouraudPoly((DRV_TLVertex *)TriVertex,3,ActiveRenderFlags);
00567 }
00568 return;
00569 }
00570
00571