00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <Assert.h>
00023 #include <Windows.h>
00024 #include <Math.h>
00025
00026 #include "Camera.h"
00027 #include "Frustum.h"
00028 #include "Surface.h"
00029
00030 #include "Vec3d.h"
00031
00032
00033
00034
00035
00036
00037 static void SetWorldspaceClipPlane(const GFX_Plane *In, const geCamera *Camera, GFX_Plane *Out);
00038 static void BackRotateVector(const geVec3d *In, geVec3d *Out, const geXForm3d *XForm);
00039 static void SetUpFrustumBBox(Frustum_Info *Info);
00040 int Frustum_Seed1=1768710981;
00041 int Frustum_Seed2=560296816;
00042
00043
00044
00045 void Frustum_SetFromCamera(Frustum_Info *Info, geCamera *Camera)
00046 {
00047 geFloat s, c, ZFar;
00048 geBoolean ZFarEnable;
00049 geVec3d Normal;
00050 int32 i;
00051
00052 geCamera_GetViewAngleXSinCos(Camera,&s,&c);
00053
00054
00055 Normal.X = s;
00056 Normal.Y = 0.0f;
00057 Normal.Z = -c;
00058 geVec3d_Normalize(&Normal);
00059 Info->Planes[0].Normal = Normal;
00060
00061
00062 Normal.X = -s;
00063 geVec3d_Normalize(&Normal);
00064 Info->Planes[1].Normal = Normal;
00065
00066 geCamera_GetViewAngleYSinCos(Camera,&s,&c);
00067
00068
00069 Normal.X = 0.0f;
00070 Normal.Y = s;
00071 Normal.Z = -c;
00072 geVec3d_Normalize(&Normal);
00073 Info->Planes[2].Normal = Normal;
00074
00075
00076 Normal.Y = -s;
00077 geVec3d_Normalize(&Normal);
00078 Info->Planes[3].Normal = Normal;
00079
00080 Info->NumPlanes = 4;
00081
00082
00083 for (i=0; i<Info->NumPlanes; i++)
00084 {
00085 Info->Planes[i].Dist = 0.0f;
00086 Info->Planes[i].Type = PLANE_ANY;
00087 }
00088
00089
00090 geCamera_GetFarClipPlane(Camera, &ZFarEnable, &ZFar);
00091
00092 if (ZFarEnable)
00093 {
00094 geFloat ZScale;
00095
00096 ZScale = geCamera_GetZScale(Camera);
00097
00098
00099 Normal.X = 0.0f;
00100 Normal.Y = 0.0f;
00101 Normal.Z = 1.0f;
00102 geVec3d_Normalize(&Normal);
00103 Info->Planes[4].Normal = Normal;
00104
00105 Info->Planes[4].Dist = -(ZFar/ZScale);
00106 Info->Planes[4].Type = PLANE_ANY;
00107
00108 Info->NumPlanes = 5;
00109 }
00110
00111
00112 SetUpFrustumBBox(Info);
00113 }
00114
00115
00116
00117
00118
00119 geBoolean Frustum_SetFromPoly(Frustum_Info *Info, geVec3d *Verts, int32 NumVerts, geBoolean Flip)
00120 {
00121 int32 NextVert;
00122 geVec3d *pVert1, *pVert2, Vect;
00123 GFX_Plane *Planes;
00124 int32 i;
00125
00126 if (NumVerts >= MAX_FCP)
00127 return GE_FALSE;
00128
00129 Planes = Info->Planes;
00130
00131 Info->NumPlanes = 0;
00132
00133 for (i=0; i< NumVerts; i++)
00134 {
00135 NextVert = ((i+1) < NumVerts) ? (i+1) : 0;
00136
00137 pVert1 = &Verts[i];
00138 pVert2 = &Verts[NextVert];
00139
00140 if (geVec3d_Compare(pVert1, pVert2, 0.1f))
00141 continue;
00142
00143
00144 geVec3d_Subtract(pVert1, pVert2, &Vect);
00145
00146 if (Flip)
00147 geVec3d_CrossProduct(pVert2, &Vect, &Planes->Normal);
00148 else
00149 geVec3d_CrossProduct(&Vect, pVert2, &Planes->Normal);
00150
00151 geVec3d_Normalize(&Planes->Normal);
00152
00153 Planes->Dist = 0.0f;
00154 Planes->Type = PLANE_ANY;
00155
00156 Planes++;
00157 Info->NumPlanes++;
00158 }
00159
00160
00161 SetUpFrustumBBox(Info);
00162 return GE_TRUE;
00163 }
00164
00165
00166
00167
00168 void Frustum_RotateToWorldSpace(Frustum_Info *In, geCamera *Camera, Frustum_Info *Out)
00169 {
00170 int32 i;
00171 GFX_Plane *pPlane1, *pPlane2;
00172
00173 assert(In != Out);
00174
00175 pPlane1 = In->Planes;
00176 pPlane2 = Out->Planes;
00177
00178
00179 for (i=0; i<In->NumPlanes; i++, pPlane1++, pPlane2++)
00180 {
00181 pPlane2->Type = pPlane1->Type;
00182
00183 SetWorldspaceClipPlane(pPlane1, Camera, pPlane2);
00184 pPlane2->Dist = 0.0f;
00185
00186 if (pPlane1->Dist)
00187 {
00188 geVec3d Vect;
00189
00190 geVec3d_Clear(&Vect);
00191 geVec3d_AddScaled(&Vect, &pPlane1->Normal, pPlane1->Dist, &Vect);
00192
00193 BackRotateVector(&Vect, &Vect, geCamera_GetCameraSpaceXForm(Camera));
00194
00195 pPlane2->Dist += geVec3d_DotProduct(&pPlane2->Normal, &Vect);
00196 }
00197 }
00198
00199 Out->NumPlanes = In->NumPlanes;
00200
00201
00202 SetUpFrustumBBox(Out);
00203 }
00204
00205
00206
00207
00208 void Frustum_TransformToWorldSpace(const Frustum_Info *In, const geCamera *Camera, Frustum_Info *Out)
00209 {
00210 int32 i;
00211 GFX_Plane *pPlane1, *pPlane2;
00212
00213 assert(In != Out);
00214
00215 pPlane1 = (GFX_Plane*)In->Planes;
00216 pPlane2 = Out->Planes;
00217
00218
00219 for (i=0; i<In->NumPlanes; i++, pPlane1++, pPlane2++)
00220 {
00221 pPlane2->Type = pPlane1->Type;
00222
00223 SetWorldspaceClipPlane(pPlane1, Camera, pPlane2);
00224 pPlane2->Dist = geVec3d_DotProduct(geCamera_GetPov(Camera), &pPlane2->Normal) - CLIP_PLANE_EPSILON;
00225
00226 if (pPlane1->Dist)
00227 {
00228 geVec3d Vect;
00229
00230 geVec3d_Clear(&Vect);
00231 geVec3d_AddScaled(&Vect, &pPlane1->Normal, pPlane1->Dist, &Vect);
00232
00233 BackRotateVector(&Vect, &Vect, geCamera_GetCameraSpaceXForm(Camera));
00234
00235 pPlane2->Dist += geVec3d_DotProduct(&pPlane2->Normal, &Vect);
00236 }
00237 }
00238 Out->NumPlanes = In->NumPlanes;
00239
00240
00241 SetUpFrustumBBox(Out);
00242 }
00243
00244
00245
00246
00247 static void SetWorldspaceClipPlane(const GFX_Plane *In, const geCamera *Camera, GFX_Plane *Out)
00248 {
00249
00250 BackRotateVector(&In->Normal, &Out->Normal, geCamera_GetCameraSpaceXForm(Camera));
00251 }
00252
00253
00254
00255
00256
00257 static void BackRotateVector(const geVec3d *In, geVec3d *Out, const geXForm3d *XForm)
00258 {
00259 geVec3d VRight, VUp, VIn, InCopy;
00260
00261 InCopy = *In;
00262
00263
00264 VRight.X = XForm->AX; VRight.Y = XForm->AY; VRight.Z = XForm->AZ;
00265 VUp.X = XForm->BX; VUp.Y = XForm->BY; VUp.Z = XForm->BZ;
00266 VIn.X = XForm->CX; VIn.Y = XForm->CY; VIn.Z = XForm->CZ;
00267
00268 Out->X = (InCopy.X * VRight.X) + (InCopy.Y * VUp.X) + (InCopy.Z * VIn.X);
00269 Out->Y = (InCopy.X * VRight.Y) + (InCopy.Y * VUp.Y) + (InCopy.Z * VIn.Y);
00270 Out->Z = (InCopy.X * VRight.Z) + (InCopy.Y * VUp.Z) + (InCopy.Z * VIn.Z);
00271 }
00272
00273
00274
00275
00276
00277 static void SetUpFrustumBBox(Frustum_Info *Info)
00278 {
00279 int32 i, *Index;
00280
00281 Index = Info->FrustumBBoxIndexes;
00282
00283 for (i=0 ; i<Info->NumPlanes ; i++)
00284 {
00285 if (Info->Planes[i].Normal.X < 0)
00286 {
00287 Index[0] = 0;
00288 Index[3] = 3;
00289 }
00290 else
00291 {
00292 Index[0] = 3;
00293 Index[3] = 0;
00294 }
00295 if (Info->Planes[i].Normal.Y < 0)
00296 {
00297 Index[1] = 1;
00298 Index[4] = 4;
00299 }
00300 else
00301 {
00302 Index[1] = 4;
00303 Index[4] = 1;
00304 }
00305 if (Info->Planes[i].Normal.Z < 0)
00306 {
00307 Index[2] = 2;
00308 Index[5] = 5;
00309 }
00310 else
00311 {
00312 Index[2] = 5;
00313 Index[5] = 2;
00314 }
00315
00316 Info->pFrustumBBoxIndexes[i] = Index;
00317 Index += 6;
00318 }
00319 }
00320
00321
00322
00323
00324
00325 geBoolean gePlane_ClipVertsFanned( const geVec3d *In, int32 NumIn,
00326 const GFX_Plane *Plane,
00327 geVec3d *Out, int32 *NumOut)
00328 {
00329 #define MAX_VERT 128
00330
00331 geVec3d *pIn, *pOut, *pFirst;
00332 int32 i, Count[2], NextVert;
00333 geFloat Dist[MAX_VERT];
00334 int32 CurIn, NextIn, FirstIn;
00335 geFloat CurDist, FirstDist, PlaneDist, NextDist;
00336
00337 assert(NumIn < MAX_VERT);
00338
00339 PlaneDist = Plane->Dist;
00340
00341 pIn = (geVec3d*)In;
00342
00343 Count[0] = Count[1] = 0;
00344
00345
00346 for (i=0; i< NumIn; i++, pIn++)
00347 {
00348 Dist[i] = geVec3d_DotProduct(&Plane->Normal, pIn) - PlaneDist;
00349
00350 if (Dist[i] >= 0.0f)
00351 Count[0]++;
00352 else
00353 Count[1]++;
00354 }
00355
00356 if (!Count[0])
00357 return GE_FALSE;
00358 else if (!Count[1])
00359 {
00360
00361
00362 memcpy((void*)In, Out, sizeof(geVec3d)*NumIn);
00363 *NumOut = NumIn;
00364 return GE_TRUE;
00365 }
00366
00367 FirstDist = Dist[0];
00368 FirstIn = (FirstDist >= 0.0f);
00369
00370 CurDist = FirstDist;
00371 CurIn = FirstIn;
00372
00373 pFirst = pIn = (geVec3d*)In;
00374 pOut = Out;
00375
00376
00377 for (i=0; i< NumIn; i++, pIn++)
00378 {
00379 geVec3d *pNext;
00380
00381 NextVert = ((i+1)<NumIn) ? (i+1): 0;
00382
00383 if (CurIn)
00384 *pOut++ = *pIn;
00385
00386 pNext = (geVec3d*)&In[NextVert];
00387
00388 NextDist = Dist[NextVert];
00389 NextIn = (NextDist >= 0.0f);
00390
00391
00392 if (CurIn != NextIn)
00393 {
00394 geFloat Scale;
00395
00396 Scale = (PlaneDist - CurDist) / (NextDist - CurDist);
00397
00398 pOut->X = pIn->X + (pNext->X - pIn->X) * Scale;
00399 pOut->Y = pIn->Y + (pNext->Y - pIn->Y) * Scale;
00400 pOut->Z = pIn->Z + (pNext->Z - pIn->Z) * Scale;
00401
00402 pOut++;
00403 }
00404
00405
00406 if (NextVert >= 2)
00407 {
00408 if (FirstIn != NextIn)
00409 {
00410 geFloat Scale;
00411
00412 Scale = (Plane->Dist - FirstDist) / (NextDist - FirstDist);
00413
00414 pOut->X = pFirst->X + (pNext->X - pFirst->X) * Scale;
00415 pOut->Y = pFirst->Y + (pNext->Y - pFirst->Y) * Scale;
00416 pOut->Z = pFirst->Z + (pNext->Z - pFirst->Z) * Scale;
00417
00418 pOut++;
00419 }
00420 }
00421
00422 CurIn = NextIn;
00423 CurDist = NextDist;
00424 }
00425
00426 *NumOut = (pOut - Out);
00427
00428 return (*NumOut >= 3);
00429 }
00430
00431
00432
00433
00434
00435 geBoolean gePlane_ClipVertsFannedUVRGB( const geVec3d *In, const Surf_TexVert *TIn, int32 NumIn,
00436 const GFX_Plane *Plane,
00437 geVec3d *Out, Surf_TexVert *TOut, int32 *NumOut)
00438 {
00439 #define MAX_VERT 128
00440
00441 geVec3d *pIn, *pOut, *pFirst;
00442 Surf_TexVert *pTIn, *pTOut, *pTFirst;
00443 int32 i=0, Count[2], FirstVert=0, NextVert=0;
00444 geFloat Dist[MAX_VERT];
00445 int32 CurIn, NextIn, FirstIn;
00446 geFloat CurDist, FirstDist, PlaneDist, NextDist;
00447 int32 Temp;
00448
00449 assert(NumIn < MAX_VERT);
00450
00451 PlaneDist = Plane->Dist;
00452
00453 pIn = (geVec3d*)In;
00454
00455 Count[0] = Count[1] = 0;
00456
00457
00458 for (i=0; i< NumIn; i++, pIn++)
00459 {
00460 Dist[i] = geVec3d_DotProduct(&Plane->Normal, pIn);
00461
00462 if (Dist[i] >= PlaneDist)
00463 {
00464 Count[0]++;
00465 FirstVert = i;
00466 }
00467 else
00468 Count[1]++;
00469
00470 }
00471
00472 if (!Count[0])
00473 return GE_FALSE;
00474 else if (!Count[1])
00475 {
00476
00477
00478 memcpy(Out, In, sizeof(geVec3d)*NumIn);
00479 memcpy(TOut, TIn, sizeof(Surf_TexVert)*NumIn);
00480 *NumOut = NumIn;
00481 return GE_TRUE;
00482 }
00483
00484 FirstDist = Dist[FirstVert];
00485 FirstIn = (FirstDist >= PlaneDist);
00486
00487 CurDist = FirstDist;
00488 CurIn = FirstIn;
00489
00490 pFirst = pIn = (geVec3d*)&In[FirstVert];
00491 pTFirst = pTIn = (Surf_TexVert*)&TIn[FirstVert];
00492
00493 pOut = Out;
00494 pTOut = TOut;
00495
00496 Temp = 0;
00497
00498
00499 for (i=FirstVert; i< FirstVert+NumIn; i++, Temp++)
00500 {
00501 geVec3d *pNext;
00502 Surf_TexVert *pTNext;
00503 int32 ThisVert;
00504
00505 ThisVert = i%NumIn;
00506 NextVert = (i+1)%NumIn;
00507
00508 pIn = (geVec3d*)&In[ThisVert];
00509 pTIn = (Surf_TexVert*)&TIn[ThisVert];
00510
00511 if (CurIn)
00512 {
00513 *pOut++ = *pIn;
00514 *pTOut++ = *pTIn;
00515 }
00516
00517 pNext = (geVec3d*)&In[NextVert];
00518 pTNext = (Surf_TexVert*)&TIn[NextVert];
00519
00520 NextDist = Dist[NextVert];
00521 NextIn = (NextDist >= PlaneDist);
00522
00523
00524 if (CurIn != NextIn)
00525 {
00526 geFloat Scale;
00527
00528 Scale = (PlaneDist - CurDist) / (NextDist - CurDist);
00529
00530 pOut->X = pIn->X + (pNext->X - pIn->X) * Scale;
00531 pOut->Y = pIn->Y + (pNext->Y - pIn->Y) * Scale;
00532 pOut->Z = pIn->Z + (pNext->Z - pIn->Z) * Scale;
00533
00534 pTOut->u = pTIn->u + (pTNext->u - pTIn->u) * Scale;
00535 pTOut->v = pTIn->v + (pTNext->v - pTIn->v) * Scale;
00536
00537 pTOut->r = pTIn->r + (pTNext->r - pTIn->r) * Scale;
00538 pTOut->g = pTIn->g + (pTNext->g - pTIn->g) * Scale;
00539 pTOut->b = pTIn->b + (pTNext->b - pTIn->b) * Scale;
00540
00541 pOut++;
00542 pTOut++;
00543 }
00544
00545
00546 if (Temp >= 1 && Temp+2 < NumIn)
00547 {
00548 if (FirstIn != NextIn)
00549 {
00550 geFloat Scale;
00551
00552 Scale = (PlaneDist - FirstDist) / (NextDist - FirstDist);
00553
00554 pOut->X = pFirst->X + (pNext->X - pFirst->X) * Scale;
00555 pOut->Y = pFirst->Y + (pNext->Y - pFirst->Y) * Scale;
00556 pOut->Z = pFirst->Z + (pNext->Z - pFirst->Z) * Scale;
00557
00558 pTOut->u = pTFirst->u + (pTNext->u - pTFirst->u) * Scale;
00559 pTOut->v = pTFirst->v + (pTNext->v - pTFirst->v) * Scale;
00560
00561 pTOut->r = pTFirst->r + (pTNext->r - pTFirst->r) * Scale;
00562 pTOut->g = pTFirst->g + (pTNext->g - pTFirst->g) * Scale;
00563 pTOut->b = pTFirst->b + (pTNext->b - pTFirst->b) * Scale;
00564
00565 pOut++;
00566 pTOut++;
00567 }
00568 }
00569
00570 CurIn = NextIn;
00571 CurDist = NextDist;
00572 }
00573
00574 *NumOut = (pOut - Out);
00575
00576 return (*NumOut >= 3);
00577 }
00578
00579
00580
00581
00582
00583 geBoolean Frustum_ClipToPlane( GFX_Plane *pPlane,
00584 geVec3d *pIn, geVec3d *pOut,
00585 int32 NumVerts, int32 *OutVerts)
00586 {
00587 int32 i, NextVert, CurIn, NextIn;
00588 geFloat CurDot, NextDot, Scale;
00589 geVec3d *pInVert, *pOutVert, *pNext;
00590 geVec3d *pNormal;
00591
00592 pNormal = &pPlane->Normal;
00593 pInVert = pIn;
00594 pOutVert = pOut;
00595
00596 CurDot = (pInVert->X * pNormal->X) + (pInVert->Y * pNormal->Y) + (pInVert->Z * pNormal->Z);
00597 CurIn = (CurDot >= pPlane->Dist);
00598
00599 for (i=0 ; i<NumVerts ; i++)
00600 {
00601 NextVert = (i + 1);
00602 if (NextVert == NumVerts)
00603 NextVert = 0;
00604
00605
00606 if (CurIn)
00607 *pOutVert++ = *pInVert;
00608
00609 pNext = &pIn[NextVert];
00610
00611 NextDot = (pNext->X * pNormal->X) + (pNext->Y * pNormal->Y) + (pNext->Z * pNormal->Z);
00612 NextIn = (NextDot >= pPlane->Dist);
00613
00614
00615
00616 if (CurIn != NextIn)
00617 {
00618 Scale = (pPlane->Dist - CurDot) / (NextDot - CurDot);
00619
00620 pOutVert->X = pInVert->X + (pNext->X - pInVert->X) * Scale;
00621 pOutVert->Y = pInVert->Y + (pNext->Y - pInVert->Y) * Scale;
00622 pOutVert->Z = pInVert->Z + (pNext->Z - pInVert->Z) * Scale;
00623
00624 pOutVert++;
00625 }
00626
00627 CurDot = NextDot;
00628 CurIn = NextIn;
00629 pInVert++;
00630 }
00631
00632 *OutVerts = pOutVert - pOut;
00633
00634 if (*OutVerts < 3)
00635 return GE_FALSE;
00636
00637 return GE_TRUE;
00638 }
00639
00640
00641
00642
00643
00644 geBoolean Frustum_ClipToPlaneUV( GFX_Plane *pPlane,
00645 geVec3d *pIn, geVec3d *pOut,
00646 Surf_TexVert *pTIn, Surf_TexVert *pTOut,
00647 int32 NumVerts, int32 *OutVerts)
00648 {
00649 int32 i, NextVert, CurIn, NextIn;
00650 geFloat CurDot, NextDot, Scale;
00651 geVec3d *pInVert, *pOutVert, *pNext;
00652 Surf_TexVert *pTInVert, *pTOutVert, *pTNext;
00653 geVec3d *pNormal;
00654
00655 pNormal = &pPlane->Normal;
00656 pInVert = pIn;
00657 pOutVert = pOut;
00658 pTInVert = pTIn;
00659 pTOutVert = pTOut;
00660
00661 CurDot = (pInVert->X * pNormal->X) + (pInVert->Y * pNormal->Y) + (pInVert->Z * pNormal->Z);
00662 CurIn = (CurDot >= pPlane->Dist);
00663
00664 for (i=0 ; i<NumVerts ; i++)
00665 {
00666 NextVert = (i + 1);
00667 if (NextVert == NumVerts)
00668 NextVert = 0;
00669
00670
00671 if (CurIn)
00672 {
00673 *pOutVert++ = *pInVert;
00674
00675
00676 pTOutVert->u = pTInVert->u;
00677 pTOutVert->v = pTInVert->v;
00678 pTOutVert++;
00679 }
00680
00681 pNext = &pIn[NextVert];
00682 pTNext = &pTIn[NextVert];
00683
00684 NextDot = (pNext->X * pNormal->X) + (pNext->Y * pNormal->Y) + (pNext->Z * pNormal->Z);
00685 NextIn = (NextDot >= pPlane->Dist);
00686
00687
00688
00689 if (CurIn != NextIn)
00690 {
00691 Scale = (pPlane->Dist - CurDot) / (NextDot - CurDot);
00692
00693 pOutVert->X = pInVert->X + (pNext->X - pInVert->X) * Scale;
00694 pOutVert->Y = pInVert->Y + (pNext->Y - pInVert->Y) * Scale;
00695 pOutVert->Z = pInVert->Z + (pNext->Z - pInVert->Z) * Scale;
00696
00697 pTOutVert->u = pTInVert->u + (pTNext->u - pTInVert->u) * Scale;
00698 pTOutVert->v = pTInVert->v + (pTNext->v - pTInVert->v) * Scale;
00699
00700 pOutVert++;
00701 pTOutVert++;
00702 }
00703
00704 CurDot = NextDot;
00705 CurIn = NextIn;
00706 pInVert++;
00707 pTInVert++;
00708 }
00709
00710 *OutVerts = pOutVert - pOut;
00711
00712 if (*OutVerts < 3)
00713 return GE_FALSE;
00714
00715 return GE_TRUE;
00716 }
00717
00718
00719
00720
00721
00722 geBoolean Frustum_ClipToPlaneUVRGB(GFX_Plane *pPlane,
00723 geVec3d *pIn, geVec3d *pOut,
00724 Surf_TexVert *pTIn, Surf_TexVert *pTOut,
00725 int32 NumVerts, int32 *OutVerts)
00726 {
00727 int32 i, NextVert, CurIn, NextIn;
00728 geFloat CurDot, NextDot, Scale;
00729 geVec3d *pInVert, *pOutVert, *pNext;
00730 Surf_TexVert *pTInVert, *pTOutVert, *pTNext;
00731 geVec3d *pNormal;
00732
00733 pNormal = &pPlane->Normal;
00734 pInVert = pIn;
00735 pOutVert = pOut;
00736 pTInVert = pTIn;
00737 pTOutVert = pTOut;
00738
00739 CurDot = (pInVert->X * pNormal->X) + (pInVert->Y * pNormal->Y) + (pInVert->Z * pNormal->Z);
00740 CurIn = (CurDot >= pPlane->Dist);
00741
00742 for (i=0 ; i<NumVerts ; i++)
00743 {
00744 NextVert = (i + 1);
00745 if (NextVert == NumVerts)
00746 NextVert = 0;
00747
00748
00749 if (CurIn)
00750 {
00751 *pOutVert++ = *pInVert;
00752 *pTOutVert++ = *pTInVert;
00753 }
00754
00755 pNext = &pIn[NextVert];
00756 pTNext = &pTIn[NextVert];
00757
00758 NextDot = (pNext->X * pNormal->X) + (pNext->Y * pNormal->Y) + (pNext->Z * pNormal->Z);
00759 NextIn = (NextDot >= pPlane->Dist);
00760
00761
00762
00763 if (CurIn != NextIn)
00764 {
00765 Scale = (pPlane->Dist - CurDot) / (NextDot - CurDot);
00766
00767 pOutVert->X = pInVert->X + (pNext->X - pInVert->X) * Scale;
00768 pOutVert->Y = pInVert->Y + (pNext->Y - pInVert->Y) * Scale;
00769 pOutVert->Z = pInVert->Z + (pNext->Z - pInVert->Z) * Scale;
00770
00771 pTOutVert->u = pTInVert->u + (pTNext->u - pTInVert->u) * Scale;
00772 pTOutVert->v = pTInVert->v + (pTNext->v - pTInVert->v) * Scale;
00773
00774 pTOutVert->r = pTInVert->r + (pTNext->r - pTInVert->r) * Scale;
00775 pTOutVert->g = pTInVert->g + (pTNext->g - pTInVert->g) * Scale;
00776 pTOutVert->b = pTInVert->b + (pTNext->b - pTInVert->b) * Scale;
00777
00778 pOutVert++;
00779 pTOutVert++;
00780 }
00781
00782 CurDot = NextDot;
00783 CurIn = NextIn;
00784 pInVert++;
00785 pTInVert++;
00786 }
00787
00788 *OutVerts = pOutVert - pOut;
00789
00790 if (*OutVerts < 3)
00791 return GE_FALSE;
00792
00793 return GE_TRUE;
00794 }
00795
00796
00797
00798
00799
00800 geBoolean Frustum_ClipToPlaneUVRGBA(GFX_Plane *pPlane,
00801 geVec3d *pIn, geVec3d *pOut,
00802 Surf_TexVert *pTIn, Surf_TexVert *pTOut,
00803 int32 NumVerts, int32 *OutVerts)
00804 {
00805 int32 i, NextVert, CurIn, NextIn;
00806 geFloat CurDot, NextDot, Scale;
00807 geVec3d *pInVert, *pOutVert, *pNext;
00808 Surf_TexVert *pTInVert, *pTOutVert, *pTNext;
00809 geVec3d *pNormal;
00810
00811 pNormal = &pPlane->Normal;
00812 pInVert = pIn;
00813 pOutVert = pOut;
00814 pTInVert = pTIn;
00815 pTOutVert = pTOut;
00816
00817 CurDot = (pInVert->X * pNormal->X) + (pInVert->Y * pNormal->Y) + (pInVert->Z * pNormal->Z);
00818 CurIn = (CurDot >= pPlane->Dist);
00819
00820 for (i=0 ; i<NumVerts ; i++)
00821 {
00822 NextVert = (i + 1);
00823 if (NextVert == NumVerts)
00824 NextVert = 0;
00825
00826
00827 if (CurIn)
00828 {
00829 *pOutVert++ = *pInVert;
00830 *pTOutVert++ = *pTInVert;
00831 }
00832
00833 pNext = &pIn[NextVert];
00834 pTNext = &pTIn[NextVert];
00835
00836 NextDot = (pNext->X * pNormal->X) + (pNext->Y * pNormal->Y) + (pNext->Z * pNormal->Z);
00837 NextIn = (NextDot >= pPlane->Dist);
00838
00839
00840
00841 if (CurIn != NextIn)
00842 {
00843 Scale = (pPlane->Dist - CurDot) / (NextDot - CurDot);
00844
00845 pOutVert->X = pInVert->X + (pNext->X - pInVert->X) * Scale;
00846 pOutVert->Y = pInVert->Y + (pNext->Y - pInVert->Y) * Scale;
00847 pOutVert->Z = pInVert->Z + (pNext->Z - pInVert->Z) * Scale;
00848
00849 pTOutVert->u = pTInVert->u + (pTNext->u - pTInVert->u) * Scale;
00850 pTOutVert->v = pTInVert->v + (pTNext->v - pTInVert->v) * Scale;
00851
00852 pTOutVert->r = pTInVert->r + (pTNext->r - pTInVert->r) * Scale;
00853 pTOutVert->g = pTInVert->g + (pTNext->g - pTInVert->g) * Scale;
00854 pTOutVert->b = pTInVert->b + (pTNext->b - pTInVert->b) * Scale;
00855 pTOutVert->a = pTInVert->a + (pTNext->a - pTInVert->a) * Scale;
00856
00857 pOutVert++;
00858 pTOutVert++;
00859 }
00860
00861 CurDot = NextDot;
00862 CurIn = NextIn;
00863 pInVert++;
00864 pTInVert++;
00865 }
00866
00867 *OutVerts = pOutVert - pOut;
00868
00869 if (*OutVerts < 3)
00870 return GE_FALSE;
00871
00872 return GE_TRUE;
00873 }
00874
00875
00876
00877
00878
00879 geBoolean Frustum_ClipToPlaneRGB( GFX_Plane *pPlane,
00880 geVec3d *pIn, geVec3d *pOut,
00881 Surf_TexVert *pTIn, Surf_TexVert *pTOut,
00882 int32 NumVerts, int32 *OutVerts)
00883 {
00884 int32 i, NextVert, CurIn, NextIn;
00885 geFloat CurDot, NextDot, Scale;
00886 geVec3d *pInVert, *pOutVert, *pNext;
00887 Surf_TexVert *pTInVert, *pTOutVert, *pTNext;
00888 geVec3d *pNormal;
00889
00890 pNormal = &pPlane->Normal;
00891 pInVert = pIn;
00892 pOutVert = pOut;
00893 pTInVert = pTIn;
00894 pTOutVert = pTOut;
00895
00896 CurDot = (pInVert->X * pNormal->X) + (pInVert->Y * pNormal->Y) + (pInVert->Z * pNormal->Z);
00897 CurIn = (CurDot >= pPlane->Dist);
00898
00899 for (i=0 ; i<NumVerts ; i++)
00900 {
00901 NextVert = (i + 1);
00902 if (NextVert == NumVerts)
00903 NextVert = 0;
00904
00905
00906 if (CurIn)
00907 {
00908 *pOutVert++ = *pInVert;
00909 *pTOutVert++ = *pTInVert;
00910 }
00911
00912 pNext = &pIn[NextVert];
00913 pTNext = &pTIn[NextVert];
00914
00915 NextDot = (pNext->X * pNormal->X) + (pNext->Y * pNormal->Y) + (pNext->Z * pNormal->Z);
00916 NextIn = (NextDot >= pPlane->Dist);
00917
00918
00919
00920 if (CurIn != NextIn)
00921 {
00922 Scale = (pPlane->Dist - CurDot) / (NextDot - CurDot);
00923
00924 pOutVert->X = pInVert->X + (pNext->X - pInVert->X) * Scale;
00925 pOutVert->Y = pInVert->Y + (pNext->Y - pInVert->Y) * Scale;
00926 pOutVert->Z = pInVert->Z + (pNext->Z - pInVert->Z) * Scale;
00927
00928 pTOutVert->r = pTInVert->r + (pTNext->r - pTInVert->r) * Scale;
00929 pTOutVert->g = pTInVert->g + (pTNext->g - pTInVert->g) * Scale;
00930 pTOutVert->b = pTInVert->b + (pTNext->b - pTInVert->b) * Scale;
00931
00932 pOutVert++;
00933 pTOutVert++;
00934 }
00935
00936 CurDot = NextDot;
00937 CurIn = NextIn;
00938 pInVert++;
00939 pTInVert++;
00940 }
00941
00942 *OutVerts = pOutVert - pOut;
00943
00944 if (*OutVerts < 3)
00945 return GE_FALSE;
00946
00947 return GE_TRUE;
00948 }
00949
00950
00951
00952
00953 void Frustum_Project(geVec3d *pIn, Surf_TexVert *pTIn, DRV_TLVertex *pOut, int32 NumVerts, const geCamera *Camera)
00954 {
00955 int32 i;
00956 geVec3d Out;
00957
00958 assert( pIn != NULL);
00959 assert( pTIn != NULL);
00960 assert( pOut != NULL);
00961 assert( Camera != NULL);
00962
00963 for (i=0; i<NumVerts; i++)
00964 {
00965 geCamera_ProjectAndClamp( Camera, &pIn[i], &Out );
00966 pOut->x = Out.X;
00967 pOut->y = Out.Y;
00968 pOut->z = Out.Z;
00969 pOut->u = pTIn->u;
00970 pOut->v = pTIn->v;
00971
00972 pOut++;
00973 pTIn++;
00974 }
00975 }
00976
00977
00978
00979
00980 void Frustum_ProjectRGB(geVec3d *pIn, Surf_TexVert *pTIn, DRV_TLVertex *pOut, int32 NumVerts, const geCamera *Camera)
00981 {
00982 int32 i;
00983 geVec3d Out;
00984
00985 assert( pIn != NULL);
00986 assert( pTIn != NULL);
00987 assert( pOut != NULL);
00988 assert( Camera != NULL);
00989
00990 for (i=0; i<NumVerts; i++)
00991 {
00992 geCamera_ProjectAndClamp( Camera, &pIn[i], &Out );
00993 pOut->x = Out.X;
00994 pOut->y = Out.Y;
00995 pOut->z = Out.Z;
00996
00997 pOut->u = pTIn->u;
00998 pOut->v = pTIn->v;
00999 pOut->r = pTIn->r;
01000 pOut->g = pTIn->g;
01001 pOut->b = pTIn->b;
01002
01003 pOut++;
01004 pTIn++;
01005 }
01006 }
01007
01008
01009
01010
01011 void Frustum_ProjectRGBA(geVec3d *pIn, Surf_TexVert *pTIn, DRV_TLVertex *pOut, int32 NumVerts, const geCamera *Camera)
01012 {
01013 int32 i;
01014 geVec3d Out;
01015 assert( pIn != NULL);
01016 assert( pTIn != NULL);
01017 assert( pOut != NULL);
01018 assert( Camera != NULL);
01019
01020 for (i=0; i<NumVerts; i++)
01021 {
01022 geCamera_ProjectAndClamp( Camera, &pIn[i], &Out );
01023 pOut->x = Out.X;
01024 pOut->y = Out.Y;
01025 pOut->z = Out.Z;
01026 pOut->u = pTIn->u;
01027 pOut->v = pTIn->v;
01028 pOut->r = pTIn->r;
01029 pOut->g = pTIn->g;
01030 pOut->b = pTIn->b;
01031 pOut->a = pTIn->a;
01032
01033 pOut++;
01034 pTIn++;
01035 }
01036 }
01037
01038
01039
01040
01041 void Frustum_ProjectRGBNoClamp(geVec3d *pIn, Surf_TexVert *pTIn, DRV_TLVertex *pOut, int32 NumVerts, const geCamera *Camera)
01042 {
01043 int32 i;
01044 geVec3d Out;
01045 assert( pIn != NULL);
01046 assert( pTIn != NULL);
01047 assert( pOut != NULL);
01048 assert( Camera != NULL);
01049
01050 for (i=0; i<NumVerts; i++)
01051 {
01052 geCamera_Project( Camera, &pIn[i], &Out );
01053 pOut->x = Out.X;
01054 pOut->y = Out.Y;
01055 pOut->z = Out.Z;
01056
01057 pOut->u = pTIn->u;
01058 pOut->v = pTIn->v;
01059 pOut->r = pTIn->r;
01060 pOut->g = pTIn->g;
01061 pOut->b = pTIn->b;
01062
01063 pOut++;
01064 pTIn++;
01065 }
01066 }
01067
01068
01069
01070
01071 geBoolean Frustum_PointsInFrustum(const geVec3d *Pin, const GFX_Plane *Plane, int32 NumVerts, int32 *c)
01072 {
01073 int32 Count, i;
01074
01075 Count = 0;
01076
01077 for (i=0; i< NumVerts; i++)
01078 {
01079 if (geVec3d_DotProduct(Pin, &Plane->Normal) >= Plane->Dist)
01080 Count++;
01081
01082 Pin++;
01083 }
01084
01085 *c += Count;
01086
01087 return Count;
01088 }
01089
01090
01091
01092
01093 geBoolean Frustum_PointInFrustum(const Frustum_Info *Fi, const geVec3d *Point, geFloat Radius)
01094 {
01095 int32 i;
01096 const GFX_Plane *Plane;
01097 geFloat Dist;
01098
01099 Plane = Fi->Planes;
01100
01101 for (i=0; i< Fi->NumPlanes; i++, Plane++)
01102 {
01103 Dist = geVec3d_DotProduct(Point, &Plane->Normal) - Plane->Dist;
01104
01105 Dist += Radius;
01106
01107 if (Dist < 0)
01108 return GE_FALSE;
01109
01110 }
01111
01112 return GE_TRUE;
01113 }
01114
01115
01116
01117
01118 geBoolean Frustum_ClipAllPlanesL(const Frustum_Info * Fi,uint32 ClipFlags,GE_LVertex *Verts, int32 *pNumVerts)
01119 {
01120 uint32 mask;
01121 GE_LVertex WorkVerts[32];
01122 GE_LVertex *p1,*p2,*p3;
01123 GFX_Plane * FPlane;
01124
01125 p1 = Verts;
01126 p2 = WorkVerts;
01127
01128 FPlane = (GFX_Plane *)Fi->Planes;
01129
01130 for(mask=1; mask <= ClipFlags; mask += mask, FPlane++)
01131 {
01132 if ( ! (ClipFlags & mask) )
01133 continue;
01134
01135 if (!Frustum_ClipToPlaneL(FPlane, p1,p2, *pNumVerts,pNumVerts) )
01136 return GE_FALSE;
01137
01138 if ( (*pNumVerts) < 3 || (*pNumVerts) > 30 )
01139 return GE_FALSE;
01140
01141 p3 = p1;
01142 p1 = p2;
01143 p2 = p3;
01144 }
01145
01146 if ( p1 != Verts )
01147 {
01148 memcpy(Verts,p1,sizeof(GE_LVertex)*(*pNumVerts));
01149 }
01150
01151 return GE_TRUE;
01152 }
01153
01154
01155
01156
01157 geBoolean Frustum_ClipToPlaneL(GFX_Plane *pPlane,
01158 GE_LVertex *pIn, GE_LVertex *pOut,
01159 int32 NumVerts, int32 *NumOutVerts)
01160 {
01161 int32 i, NextVert, CurIn, NextIn;
01162 geFloat CurDot, NextDot, Scale;
01163 GE_LVertex *pInVert, *pOutVert, *pNext;
01164 geVec3d *pNormal;
01165
01166 pNormal = &pPlane->Normal;
01167 pInVert = pIn;
01168 pOutVert = pOut;
01169
01170 CurDot = (pInVert->X * pNormal->X) + (pInVert->Y * pNormal->Y) + (pInVert->Z * pNormal->Z);
01171 CurIn = (CurDot >= pPlane->Dist);
01172
01173 for (i=0 ; i<NumVerts ; i++)
01174 {
01175 NextVert = (i + 1);
01176 if (NextVert == NumVerts)
01177 NextVert = 0;
01178
01179
01180 if (CurIn)
01181 {
01182 *pOutVert++ = *pInVert;
01183 }
01184
01185 pNext = &pIn[NextVert];
01186
01187 NextDot = (pNext->X * pNormal->X) + (pNext->Y * pNormal->Y) + (pNext->Z * pNormal->Z);
01188 NextIn = (NextDot >= pPlane->Dist);
01189
01190
01191
01192 if (CurIn != NextIn)
01193 {
01194 Scale = (pPlane->Dist - CurDot) / (NextDot - CurDot);
01195
01196 pOutVert->X = pInVert->X + (pNext->X - pInVert->X) * Scale;
01197 pOutVert->Y = pInVert->Y + (pNext->Y - pInVert->Y) * Scale;
01198 pOutVert->Z = pInVert->Z + (pNext->Z - pInVert->Z) * Scale;
01199
01200 pOutVert->u = pInVert->u + (pNext->u - pInVert->u) * Scale;
01201 pOutVert->v = pInVert->v + (pNext->v - pInVert->v) * Scale;
01202
01203 pOutVert->r = pInVert->r + (pNext->r - pInVert->r) * Scale;
01204 pOutVert->g = pInVert->g + (pNext->g - pInVert->g) * Scale;
01205 pOutVert->b = pInVert->b + (pNext->b - pInVert->b) * Scale;
01206 pOutVert->a = pInVert->a + (pNext->a - pInVert->a) * Scale;
01207
01208 pOutVert++;
01209 }
01210
01211 CurDot = NextDot;
01212 CurIn = NextIn;
01213 pInVert++;
01214 }
01215
01216 *NumOutVerts = ((uint32)pOutVert - (uint32)pOut)/sizeof(*pOut);
01217
01218 if ( *NumOutVerts < 3)
01219 return GE_FALSE;
01220
01221 return GE_TRUE;
01222 }
01223