00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <Windows.h>
00023 #include <stdio.h>
00024
00025 #include "D3DCache.h"
00026 #include "D3D_Fx.h"
00027
00028 #include "PCache.h"
00029 #include "D3DDrv.h"
00030 #include "THandle.h"
00031 #include "D3D_Err.h"
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 DRV_CacheInfo CacheInfo;
00042
00043
00044
00045
00046
00047 #if 1
00048
00049 #define MAX_WORLD_POLYS 512
00050 #define MAX_WORLD_POLY_VERTS 2048
00051
00052 #define MAX_MISC_POLYS 512
00053 #define MAX_MISC_POLY_VERTS 2048
00054
00055 #else
00056
00057 #define MAX_WORLD_POLYS 256
00058 #define MAX_WORLD_POLY_VERTS 4096
00059
00060 #define MAX_MISC_POLYS 256
00061 #define MAX_MISC_POLY_VERTS 4096
00062
00063 #endif
00064
00065 typedef struct
00066 {
00067 geFloat u;
00068 geFloat v;
00069
00070 uint32 Color;
00071 } PCache_TVert;
00072
00073 typedef struct
00074 {
00075 geRDriver_THandle *THandle;
00076
00077 DRV_LInfo *LInfo;
00078 uint32 Flags;
00079 geFloat ShiftU;
00080 geFloat ShiftV;
00081 geFloat ScaleU;
00082 geFloat ScaleV;
00083 int32 MipLevel;
00084 uint32 SortKey;
00085 int32 FirstVert;
00086 int32 NumVerts;
00087 } World_Poly;
00088
00089 #define MAX_TEXTURE_STAGES 2 // Up to 2 tmu's (stages)
00090
00091
00092
00093 typedef struct
00094 {
00095 geFloat u,v;
00096 } PCache_UVSet;
00097
00098 typedef struct
00099 {
00100 geFloat x,y,z;
00101 geFloat rhw;
00102 DWORD color;
00103 DWORD specular;
00104 PCache_UVSet uv[MAX_TEXTURE_STAGES];
00105 } PCache_Vert;
00106
00107 typedef struct
00108 {
00109 World_Poly Polys[MAX_WORLD_POLYS];
00110 World_Poly *SortedPolys[MAX_WORLD_POLYS];
00111 World_Poly *SortedPolys2[MAX_WORLD_POLYS];
00112 PCache_Vert Verts[MAX_WORLD_POLY_VERTS];
00113
00114 PCache_TVert TVerts[MAX_WORLD_POLY_VERTS];
00115
00116 int32 NumPolys;
00117 int32 NumPolys2;
00118 int32 NumVerts;
00119 } World_Cache;
00120
00121 static World_Cache WorldCache;
00122
00123 #define PREP_WORLD_VERTS_NORMAL 1 // Prep verts as normal
00124 #define PREP_WORLD_VERTS_LMAP 2 // Prep verts as lightmaps
00125 #define PREP_WORLD_VERTS_SINGLE_PASS 3 // Prep verts for a single pass
00126
00127 #define RENDER_WORLD_POLYS_NORMAL 1 // Render polys as normal
00128 #define RENDER_WORLD_POLYS_LMAP 2 // Render polys as lightmaps
00129 #define RENDER_WORLD_POLYS_SINGLE_PASS 3
00130
00131
00132
00133
00134
00135 typedef struct
00136 {
00137 geRDriver_THandle *THandle;
00138 uint32 Flags;
00139 int32 MipLevel;
00140 int32 FirstVert;
00141 int32 NumVerts;
00142
00143 uint32 SortKey;
00144 } Misc_Poly;
00145
00146 typedef struct
00147 {
00148 Misc_Poly Polys[MAX_MISC_POLYS];
00149 Misc_Poly *SortedPolys[MAX_MISC_POLYS];
00150 PCache_Vert Verts[MAX_MISC_POLY_VERTS];
00151
00152
00153 int32 NumPolys;
00154 int32 NumVerts;
00155 } Misc_Cache;
00156
00157 static Misc_Cache MiscCache;
00158
00159
00160
00161
00162 geBoolean World_PolyPrepVerts(World_Poly *pPoly, int32 PrepMode, int32 Stage1, int32 Stage2);
00163
00164 static BOOL RenderWorldPolys(int32 RenderMode);
00165 static BOOL ClearWorldCache(void);
00166 static int32 GetMipLevel(DRV_TLVertex *Verts, int32 NumVerts, geFloat ScaleU, geFloat ScaleV, int32 MaxMipLevel);
00167
00168 #include <Math.h>
00169
00170
00171
00172
00173 BOOL PCache_InsertWorldPoly(DRV_TLVertex *Verts, int32 NumVerts, geRDriver_THandle *THandle, DRV_TexInfo *TexInfo, DRV_LInfo *LInfo, uint32 Flags)
00174 {
00175 int32 Mip;
00176 geFloat ZRecip, DrawScaleU, DrawScaleV;
00177 World_Poly *pCachePoly;
00178 DRV_TLVertex *pVerts;
00179 PCache_TVert *pTVerts;
00180 PCache_Vert *pD3DVerts;
00181 int32 i;
00182 uint32 Alpha;
00183
00184 #ifdef _DEBUG
00185 if (LInfo)
00186 {
00187 assert(LInfo->THandle);
00188 }
00189 #endif
00190
00191 if ((WorldCache.NumVerts + NumVerts) >= MAX_WORLD_POLY_VERTS)
00192 {
00193
00194 if (!PCache_FlushWorldPolys())
00195 return GE_FALSE;
00196 }
00197 else if (WorldCache.NumPolys+1 >= MAX_WORLD_POLYS)
00198 {
00199
00200 if (!PCache_FlushWorldPolys())
00201 return GE_FALSE;
00202 }
00203
00204 DrawScaleU = 1.0f / TexInfo->DrawScaleU;
00205 DrawScaleV = 1.0f / TexInfo->DrawScaleV;
00206
00207 Mip = GetMipLevel(Verts, NumVerts, DrawScaleU, DrawScaleV, THandle->NumMipLevels-1);
00208
00209
00210 pVerts = Verts;
00211
00212
00213 pCachePoly = &WorldCache.Polys[WorldCache.NumPolys];
00214
00215 pCachePoly->THandle = THandle;
00216 pCachePoly->LInfo = LInfo;
00217 pCachePoly->Flags = Flags;
00218 pCachePoly->FirstVert = WorldCache.NumVerts;
00219 pCachePoly->NumVerts = NumVerts;
00220 pCachePoly->ShiftU = TexInfo->ShiftU;
00221 pCachePoly->ShiftV = TexInfo->ShiftV;
00222 pCachePoly->ScaleU = DrawScaleU;
00223 pCachePoly->ScaleV = DrawScaleV;
00224 pCachePoly->MipLevel = Mip;
00225
00226
00227 pCachePoly->SortKey = ((THandle - TextureHandles)<<4)+Mip;
00228
00229
00230 pD3DVerts = &WorldCache.Verts[WorldCache.NumVerts];
00231 pTVerts = &WorldCache.TVerts[WorldCache.NumVerts];
00232
00233 if (Flags & DRV_RENDER_ALPHA)
00234 Alpha = (uint32)pVerts->a<<24;
00235 else
00236 Alpha = (uint32)(255<<24);
00237
00238 for (i=0; i< NumVerts; i++)
00239 {
00240 ZRecip = 1.0f/(pVerts->z);
00241
00242 pD3DVerts->x = pVerts->x;
00243 pD3DVerts->y = pVerts->y;
00244
00245 pD3DVerts->z = (1.0f - ZRecip);
00246 pD3DVerts->rhw = ZRecip;
00247
00248 if (AppInfo.FogEnable && !(Flags & DRV_RENDER_POLY_NO_FOG))
00249 {
00250 DWORD FogVal;
00251 geFloat Val;
00252
00253 Val = pVerts->z;
00254
00255 if (Val > AppInfo.FogEnd)
00256 Val = AppInfo.FogEnd;
00257
00258 FogVal = (DWORD)((AppInfo.FogEnd-Val)/(AppInfo.FogEnd-AppInfo.FogStart)*255.0f);
00259
00260 if (FogVal < 0)
00261 FogVal = 0;
00262 else if (FogVal > 255)
00263 FogVal = 255;
00264
00265 pD3DVerts->specular = (FogVal<<24);
00266 }
00267 else
00268 pD3DVerts->specular = 0;
00269
00270
00271 pTVerts->u = pVerts->u;
00272 pTVerts->v = pVerts->v;
00273
00274 pTVerts->Color = Alpha | ((uint32)pVerts->r<<16) | ((uint32)pVerts->g<<8) | (uint32)pVerts->b;
00275
00276 pTVerts++;
00277 pVerts++;
00278 pD3DVerts++;
00279
00280 }
00281
00282
00283 WorldCache.NumVerts += NumVerts;
00284 WorldCache.NumPolys++;
00285
00286 return TRUE;
00287 }
00288
00289
00290
00291
00292 BOOL PCache_FlushWorldPolys(void)
00293 {
00294 if (!WorldCache.NumPolys)
00295 return TRUE;
00296
00297 if (!THandle_CheckCache())
00298 return GE_FALSE;
00299
00300 if (AppInfo.CanDoMultiTexture)
00301 {
00302 RenderWorldPolys(RENDER_WORLD_POLYS_SINGLE_PASS);
00303 }
00304 else
00305 {
00306
00307 if (!RenderWorldPolys(RENDER_WORLD_POLYS_NORMAL))
00308 return GE_FALSE;
00309
00310
00311 RenderWorldPolys(RENDER_WORLD_POLYS_LMAP);
00312 }
00313
00314 ClearWorldCache();
00315
00316 return TRUE;
00317 }
00318
00319
00320
00321 static int MiscBitmapHandleComp(const void *a, const void *b)
00322 {
00323 uint32 Id1, Id2;
00324
00325 Id1 = (uint32)(*(Misc_Poly**)a)->SortKey;
00326 Id2 = (uint32)(*(Misc_Poly**)b)->SortKey;
00327
00328 if ( Id1 == Id2)
00329 return 0;
00330
00331 if (Id1 < Id2)
00332 return -1;
00333
00334 return 1;
00335 }
00336
00337
00338
00339 static void SortMiscPolysByHandle(void)
00340 {
00341 Misc_Poly *pPoly;
00342 int32 i;
00343
00344 pPoly = MiscCache.Polys;
00345
00346 for (i=0; i<MiscCache.NumPolys; i++)
00347 {
00348 MiscCache.SortedPolys[i] = pPoly;
00349 pPoly++;
00350 }
00351
00352
00353 qsort(&MiscCache.SortedPolys, MiscCache.NumPolys, sizeof(MiscCache.SortedPolys[0]), MiscBitmapHandleComp);
00354 }
00355
00356
00357
00358
00359 static void FillLMapSurface(DRV_LInfo *LInfo, int32 LNum)
00360 {
00361 U16 *pTempBits;
00362 int32 w, h, Width, Height, Size;
00363 U8 *pBitPtr;
00364 RGB_LUT *Lut;
00365 geRDriver_THandle *THandle;
00366 int32 Extra;
00367
00368 THandle = LInfo->THandle;
00369
00370 pBitPtr = (U8*)LInfo->RGBLight[LNum];
00371
00372 Width = LInfo->Width;
00373 Height = LInfo->Height;
00374 Size = 1<<THandle->Log;
00375
00376 Lut = &AppInfo.Lut1;
00377
00378 THandle_Lock(THandle, 0, (void**)&pTempBits);
00379
00380 Extra = Size - Width;
00381 U8 R, G, B;
00382 U16 Color;
00383
00384 for (h=0; h< Height; h++)
00385 {
00386 for (w=0; w< Width; w++)
00387 {
00388 R = *pBitPtr++;
00389 G = *pBitPtr++;
00390 B = *pBitPtr++;
00391
00392 Color = (U16)(Lut->R[R] | Lut->G[G] | Lut->B[B]);
00393
00394 *pTempBits++ = Color;
00395 }
00396 pTempBits += Extra;
00397 }
00398
00399 THandle_UnLock(THandle, 0);
00400 }
00401
00402 #ifdef USE_TPAGES
00403
00404
00405
00406 static void FillLMapSurface2(DRV_LInfo *LInfo, int32 LNum)
00407 {
00408 U16 *pTempBits;
00409 int32 w, h, Width, Height, Stride;
00410 U8 *pBitPtr;
00411 RGB_LUT *Lut;
00412 geRDriver_THandle *THandle;
00413 HRESULT Result;
00414 const RECT *pRect;
00415 DDSURFACEDESC2 SurfDesc;
00416 LPDIRECTDRAWSURFACE4 Surface;
00417 int32 Extra;
00418
00419 THandle = LInfo->THandle;
00420
00421 pBitPtr = (U8*)LInfo->RGBLight[LNum];
00422
00423 Width = LInfo->Width;
00424 Height = LInfo->Height;
00425
00426 Lut = &AppInfo.Lut1;
00427
00428 pRect = TPage_BlockGetRect(THandle->Block);
00429 Surface = TPage_BlockGetSurface(THandle->Block);
00430
00431 memset(&SurfDesc, 0, sizeof(DDSURFACEDESC2));
00432 SurfDesc.dwSize = sizeof(DDSURFACEDESC2);
00433
00434 Result = Surface->Lock((RECT*)pRect, &SurfDesc, DDLOCK_WAIT, NULL);
00435
00436 assert(Result == DD_OK);
00437
00438 Stride = SurfDesc.dwWidth;
00439
00440 pTempBits = (U16*)SurfDesc.lpSurface;
00441
00442 Extra = Stride - Width;
00443
00444 for (h=0; h< Height; h++)
00445 {
00446 for (w=0; w< Width; w++)
00447 {
00448 U8 R, G, B;
00449 U16 Color;
00450 R = *pBitPtr++;
00451 G = *pBitPtr++;
00452 B = *pBitPtr++;
00453
00454 Color = (U16)(Lut->R[R] | Lut->G[G] | Lut->B[B]);
00455
00456 *pTempBits++ = Color;
00457 }
00458 pTempBits += Extra;
00459 }
00460
00461 Result = Surface->Unlock((RECT*)pRect);
00462
00463 assert(Result == DD_OK);
00464 }
00465 #endif
00466
00467
00468
00469
00470 static void LoadLMapFromSystem(DRV_LInfo *LInfo, int32 Log, int32 LNum)
00471 {
00472 U16 *pTempBits;
00473 int32 w, h, Width, Height, Size, Extra;
00474 U8 *pBitPtr;
00475 LPDIRECTDRAWSURFACE4 Surface;
00476 RGB_LUT *Lut;
00477 DDSURFACEDESC2 ddsd;
00478 HRESULT ddrval;
00479
00480 pBitPtr = (U8*)LInfo->RGBLight[LNum];
00481
00482 Width = LInfo->Width;
00483 Height = LInfo->Height;
00484 Size = 1<<Log;
00485
00486 Extra = Size - Width;
00487
00488 Lut = &AppInfo.Lut1;
00489
00490 Surface = SystemToVideo[Log].Surface;
00491
00492 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00493 ddsd.dwSize = sizeof(DDSURFACEDESC2);
00494 ddrval = Surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
00495
00496 assert(ddrval == DD_OK);
00497 U8 R, G, B;
00498 U16 Color;
00499
00500 pTempBits = (USHORT*)ddsd.lpSurface;
00501
00502 for (h=0; h< Height; h++)
00503 {
00504 for (w=0; w< Width; w++)
00505 {
00506 R = *pBitPtr++;
00507 G = *pBitPtr++;
00508 B = *pBitPtr++;
00509
00510 Color = (U16)(Lut->R[R] | Lut->G[G] | Lut->B[B]);
00511
00512 *pTempBits++ = Color;
00513 }
00514 pTempBits += Extra;
00515 }
00516
00517 ddrval = Surface->Unlock(NULL);
00518 assert(ddrval == DD_OK);
00519 }
00520
00521 static BOOL IsKeyDown(int KeyCode)
00522 {
00523 if (GetAsyncKeyState(KeyCode) & 0x8000)
00524 return TRUE;
00525
00526 return FALSE;
00527 }
00528
00529 extern uint32 CurrentLRU;
00530
00531
00532
00533
00534 geBoolean SetupMipData(THandle_MipData *MipData)
00535 {
00536 if (!MipData->Slot || D3DCache_SlotGetUserData(MipData->Slot) != MipData)
00537 {
00538 MipData->Slot = D3DCache_TypeFindSlot(MipData->CacheType);
00539 assert(MipData->Slot);
00540
00541 D3DCache_SlotSetUserData(MipData->Slot, MipData);
00542
00543 #ifdef SUPER_FLUSH
00544 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FLUSHBATCH, 0);
00545 #endif
00546
00547 return GE_FALSE;
00548 }
00549
00550 return GE_TRUE;
00551 }
00552
00553
00554
00555
00556 geBoolean SetupLMap(int32 Stage, DRV_LInfo *LInfo, int32 LNum, geBoolean Dynamic)
00557 {
00558 #ifdef D3D_MANAGE_TEXTURES
00559 #ifdef USE_TPAGES
00560 {
00561 geRDriver_THandle *THandle;
00562
00563 THandle = LInfo->THandle;
00564
00565 if (Dynamic)
00566 THandle->Flags |= THANDLE_UPDATE;
00567
00568 if (!THandle->Block)
00569 {
00570 THandle->Block = TPage_MgrFindOptimalBlock(TPageMgr, CurrentLRU);
00571 THandle->Flags |= THANDLE_UPDATE;
00572 TPage_BlockSetUserData(THandle->Block, THandle);
00573 assert(THandle->Block);
00574 }
00575 else if (TPage_BlockGetUserData(THandle->Block) != THandle)
00576 {
00577
00578 THandle->Block = TPage_MgrFindOptimalBlock(TPageMgr, CurrentLRU);
00579 assert(THandle->Block);
00580
00581 THandle->Flags |= THANDLE_UPDATE;
00582 TPage_BlockSetUserData(THandle->Block, THandle);
00583 }
00584
00585 if (THandle->Flags & THANDLE_UPDATE)
00586 FillLMapSurface2(LInfo, LNum);
00587
00588 TPage_BlockSetLRU(THandle->Block, CurrentLRU);
00589 D3DSetTexture(Stage, TPage_BlockGetTexture(THandle->Block));
00590
00591 if (Dynamic)
00592 THandle->Flags |= THANDLE_UPDATE;
00593 else
00594 THandle->Flags &= ~THANDLE_UPDATE;
00595
00596 return GE_TRUE;
00597 }
00598 #else
00599 {
00600 geRDriver_THandle *THandle;
00601
00602 THandle = LInfo->THandle;
00603
00604 if (Dynamic)
00605 THandle->MipData[0].Flags |= THANDLE_UPDATE;
00606
00607 if (THandle->MipData[0].Flags & THANDLE_UPDATE)
00608 FillLMapSurface(LInfo, LNum);
00609
00610 D3DSetTexture(Stage, THandle->MipData[0].Texture);
00611
00612 if (Dynamic)
00613 THandle->MipData[0].Flags |= THANDLE_UPDATE;
00614 else
00615 THandle->MipData[0].Flags &= ~THANDLE_UPDATE;
00616
00617 return GE_TRUE;
00618 }
00619 #endif
00620
00621 #else
00622 geRDriver_THandle *THandle;
00623 THandle_MipData *MipData;
00624
00625 THandle = LInfo->THandle;
00626 MipData = &THandle->MipData[0];
00627
00628 if (Dynamic)
00629 MipData->Flags |= THANDLE_UPDATE;
00630
00631 if (!SetupMipData(MipData))
00632 {
00633 MipData->Flags |= THANDLE_UPDATE;
00634 CacheInfo.LMapMisses++;
00635 }
00636
00637 if (MipData->Flags & THANDLE_UPDATE)
00638 {
00639 HRESULT Error;
00640 LPDIRECTDRAWSURFACE4 Surface;
00641
00642 assert(MipData->Slot);
00643
00644 Surface = D3DCache_SlotGetSurface(MipData->Slot);
00645
00646 assert(Surface);
00647 assert(THandle->Log < MAX_LMAP_LOG_SIZE);
00648 assert(SystemToVideo[THandle->Log].Surface);
00649
00650 LoadLMapFromSystem(LInfo, THandle->Log, LNum);
00651
00652 Error = Surface->BltFast(0, 0, SystemToVideo[THandle->Log].Surface, NULL, DDBLTFAST_WAIT);
00653
00654
00655
00656
00657 if (Error != DD_OK)
00658 {
00659 if(Error==DDERR_SURFACELOST)
00660 {
00661 if (!D3DMain_RestoreAllSurfaces())
00662 return GE_FALSE;
00663 }
00664 else
00665 {
00666 D3DMain_Log("SetupTexture: System to Video cache Blt failed.\n %s", D3DErrorToString(Error));
00667 return GE_FALSE;
00668 }
00669 }
00670 }
00671
00672 if (Dynamic)
00673 MipData->Flags |= THANDLE_UPDATE;
00674 else
00675 MipData->Flags &= ~THANDLE_UPDATE;
00676
00677 D3DCache_SlotSetLRU(MipData->Slot, CurrentLRU);
00678 D3DSetTexture(Stage, D3DCache_SlotGetTexture(MipData->Slot));
00679
00680 return GE_TRUE;
00681 #endif
00682 }
00683
00684
00685
00686
00687 geBoolean SetupTexture(int32 Stage, geRDriver_THandle *THandle, int32 MipLevel)
00688 {
00689 #ifdef D3D_MANAGE_TEXTURES
00690 D3DSetTexture(Stage, THandle->MipData[MipLevel].Texture);
00691 return GE_TRUE;
00692 #else
00693 THandle_MipData *MipData;
00694
00695 MipData = &THandle->MipData[MipLevel];
00696
00697 if (!SetupMipData(MipData))
00698 {
00699 MipData->Flags |= THANDLE_UPDATE;
00700 CacheInfo.TexMisses++;
00701 }
00702
00703 if (MipData->Flags & THANDLE_UPDATE)
00704 {
00705 HRESULT Error;
00706 LPDIRECTDRAWSURFACE4 Surface;
00707
00708 Surface = D3DCache_SlotGetSurface(MipData->Slot);
00709
00710 Error = Surface->BltFast(0, 0, MipData->Surface, NULL, DDBLTFAST_WAIT);
00711
00712 if (Error != DD_OK)
00713 {
00714 if(Error==DDERR_SURFACELOST)
00715 {
00716 if (!D3DMain_RestoreAllSurfaces())
00717 return FALSE;
00718 }
00719 else
00720 {
00721 D3DMain_Log("SetupTexture: System to Video cache Blt failed.\n %s", D3DErrorToString(Error));
00722 return GE_FALSE;
00723 }
00724 }
00725 }
00726
00727 MipData->Flags &= ~THANDLE_UPDATE;
00728
00729 D3DCache_SlotSetLRU(MipData->Slot, CurrentLRU);
00730 D3DSetTexture(Stage, D3DCache_SlotGetTexture(MipData->Slot));
00731
00732 return GE_TRUE;
00733 #endif
00734 }
00735
00736
00737
00738
00739 BOOL PCache_FlushMiscPolys(void)
00740 {
00741 int32 i;
00742 Misc_Poly *pPoly;
00743
00744 if (!MiscCache.NumPolys)
00745 return TRUE;
00746
00747 if (!THandle_CheckCache())
00748 return GE_FALSE;
00749
00750
00751 if (AppInfo.CanDoMultiTexture)
00752 {
00753 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
00754 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
00755 D3DSetTexture(1, NULL);
00756 }
00757
00758 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
00759 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
00760 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
00761 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
00762 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
00763 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
00764 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
00765 D3DBlendFunc (D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
00766 D3DBlendEnable(TRUE);
00767
00768
00769 SortMiscPolysByHandle();
00770
00771 for (i=0; i< MiscCache.NumPolys; i++)
00772 {
00773 pPoly = MiscCache.SortedPolys[i];
00774
00775 if (pPoly->Flags & DRV_RENDER_NO_ZMASK)
00776 D3DZEnable(FALSE);
00777 else
00778 D3DZEnable(TRUE);
00779
00780 if (pPoly->Flags & DRV_RENDER_NO_ZWRITE)
00781 D3DZWriteEnable(FALSE);
00782 else
00783 D3DZWriteEnable(TRUE);
00784
00785 if (pPoly->Flags & DRV_RENDER_CLAMP_UV)
00786 D3DTexWrap(0, FALSE);
00787 else
00788 D3DTexWrap(0, TRUE);
00789
00790 if (!SetupTexture(0, pPoly->THandle, pPoly->MipLevel))
00791 return GE_FALSE;
00792
00793 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable)
00794 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , FALSE);
00795
00796 D3DTexturedPoly(&MiscCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
00797
00798 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable)
00799 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , TRUE);
00800 }
00801
00802
00803 D3DZWriteEnable (TRUE);
00804 D3DZEnable(TRUE);
00805
00806 MiscCache.NumPolys = 0;
00807 MiscCache.NumVerts = 0;
00808
00809 #ifdef SUPER_FLUSH
00810 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FLUSHBATCH, 0);
00811 AppInfo.lpD3DDevice->EndScene();
00812 AppInfo.lpD3DDevice->BeginScene();
00813 #endif
00814
00815 return TRUE;
00816 }
00817
00818
00819
00820
00821 BOOL PCache_InsertMiscPoly(DRV_TLVertex *Verts, int32 NumVerts, geRDriver_THandle *THandle, uint32 Flags)
00822 {
00823 int32 Mip;
00824 geFloat ZRecip, u, v, ScaleU, ScaleV, InvScale;
00825 Misc_Poly *pCachePoly;
00826 DRV_TLVertex *pVerts;
00827 PCache_Vert *pD3DVerts;
00828 int32 i, SAlpha;
00829
00830 if ((MiscCache.NumVerts + NumVerts) >= MAX_MISC_POLY_VERTS)
00831 {
00832
00833 PCache_FlushMiscPolys();
00834 }
00835 else if (MiscCache.NumPolys+1 >= MAX_MISC_POLYS)
00836 {
00837
00838 PCache_FlushMiscPolys();
00839 }
00840
00841 Mip = GetMipLevel(Verts, NumVerts, (geFloat)THandle->Width, (geFloat)THandle->Height, THandle->NumMipLevels-1);
00842
00843
00844 pCachePoly = &MiscCache.Polys[MiscCache.NumPolys];
00845
00846 pCachePoly->THandle = THandle;
00847 pCachePoly->Flags = Flags;
00848 pCachePoly->FirstVert = MiscCache.NumVerts;
00849 pCachePoly->NumVerts = NumVerts;
00850 pCachePoly->MipLevel = Mip;
00851 pCachePoly->SortKey = ((THandle - TextureHandles)<<4)+Mip;
00852
00853
00854
00855 InvScale = 1.0f / (geFloat)((1<<THandle->Log));
00856
00857
00858 ScaleU = (geFloat)THandle->Width * InvScale;
00859 ScaleV = (geFloat)THandle->Height * InvScale;
00860
00861
00862 SAlpha = ((int32)Verts->a)<<24;
00863
00864
00865 pVerts = Verts;
00866
00867 pD3DVerts = &MiscCache.Verts[MiscCache.NumVerts];
00868
00869 for (i=0; i< NumVerts; i++)
00870 {
00871 ZRecip = 1/(pVerts->z);
00872
00873 pD3DVerts->x = pVerts->x;
00874 pD3DVerts->y = pVerts->y;
00875
00876 pD3DVerts->z = (1.0f - ZRecip);
00877 pD3DVerts->rhw = ZRecip;
00878
00879 u = pVerts->u * ScaleU;
00880 v = pVerts->v * ScaleV;
00881
00882 pD3DVerts->uv[0].u = u;
00883 pD3DVerts->uv[0].v = v;
00884
00885 pD3DVerts->color = SAlpha | ((int32)pVerts->r<<16) | ((int32)pVerts->g<<8) | (int32)pVerts->b;
00886
00887 if (AppInfo.FogEnable && !(Flags & DRV_RENDER_POLY_NO_FOG) )
00888 {
00889 DWORD FogVal;
00890 geFloat Val;
00891
00892 Val = pVerts->z;
00893
00894 if (Val > AppInfo.FogEnd)
00895 Val = AppInfo.FogEnd;
00896
00897 FogVal = (DWORD)((AppInfo.FogEnd-Val)/(AppInfo.FogEnd-AppInfo.FogStart)*255.0f);
00898
00899 if (FogVal < 0)
00900 FogVal = 0;
00901 else if (FogVal > 255)
00902 FogVal = 255;
00903
00904 pD3DVerts->specular = (FogVal<<24);
00905 }
00906 else
00907 pD3DVerts->specular = 0;
00908
00909 pVerts++;
00910 pD3DVerts++;
00911 }
00912
00913
00914 MiscCache.NumVerts += NumVerts;
00915 MiscCache.NumPolys++;
00916
00917 return TRUE;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927 geBoolean World_PolyPrepVerts(World_Poly *pPoly, int32 PrepMode, int32 Stage1, int32 Stage2)
00928 {
00929 geFloat InvScale, u, v;
00930 PCache_TVert *pTVerts;
00931 PCache_Vert *pVerts;
00932 geFloat ShiftU, ShiftV, ScaleU, ScaleV;
00933 geFloat InvScale2, ShiftU2, ShiftV2;
00934 int32 j;
00935
00936 switch (PrepMode)
00937 {
00938 case PREP_WORLD_VERTS_NORMAL:
00939 {
00940 pTVerts = &WorldCache.TVerts[pPoly->FirstVert];
00941
00942 ShiftU = pPoly->ShiftU;
00943 ShiftV = pPoly->ShiftV;
00944 ScaleU = pPoly->ScaleU;
00945 ScaleV = pPoly->ScaleV;
00946
00947
00948 InvScale = 1.0f / (geFloat)((1<<pPoly->THandle->Log));
00949
00950 pVerts = &WorldCache.Verts[pPoly->FirstVert];
00951
00952 for (j=0; j< pPoly->NumVerts; j++)
00953 {
00954 u = pTVerts->u*ScaleU+ShiftU;
00955 v = pTVerts->v*ScaleV+ShiftV;
00956
00957 pVerts->uv[Stage1].u = u * InvScale;
00958 pVerts->uv[Stage1].v = v * InvScale;
00959
00960 pVerts->color = pTVerts->Color;
00961
00962 pTVerts++;
00963 pVerts++;
00964 }
00965
00966 break;
00967 }
00968
00969 case PREP_WORLD_VERTS_LMAP:
00970 {
00971 if (!pPoly->LInfo)
00972 return GE_TRUE;
00973
00974 ShiftU = (geFloat)-pPoly->LInfo->MinU + 8.0f;
00975 ShiftV = (geFloat)-pPoly->LInfo->MinV + 8.0f;
00976
00977
00978 InvScale = 1.0f/(geFloat)((1<<pPoly->LInfo->THandle->Log)<<4);
00979
00980 pTVerts = &WorldCache.TVerts[pPoly->FirstVert];
00981 pVerts = &WorldCache.Verts[pPoly->FirstVert];
00982
00983 for (j=0; j< pPoly->NumVerts; j++)
00984 {
00985 u = pTVerts->u + ShiftU;
00986 v = pTVerts->v + ShiftV;
00987
00988 pVerts->uv[Stage1].u = u * InvScale;
00989 pVerts->uv[Stage1].v = v * InvScale;
00990
00991 pVerts->color = 0xffffffff;
00992
00993 pTVerts++;
00994 pVerts++;
00995 }
00996 break;
00997 }
00998
00999 case PREP_WORLD_VERTS_SINGLE_PASS:
01000 {
01001
01002 assert(pPoly->LInfo);
01003
01004 pTVerts = &WorldCache.TVerts[pPoly->FirstVert];
01005
01006
01007 ShiftU = pPoly->ShiftU;
01008 ShiftV = pPoly->ShiftV;
01009 ScaleU = pPoly->ScaleU;
01010 ScaleV = pPoly->ScaleV;
01011
01012
01013 InvScale = 1.0f / (geFloat)((1<<pPoly->THandle->Log));
01014
01015
01016 ShiftU2 = (geFloat)-pPoly->LInfo->MinU + 8.0f;
01017 ShiftV2 = (geFloat)-pPoly->LInfo->MinV + 8.0f;
01018 InvScale2 = 1.0f/(geFloat)((1<<pPoly->LInfo->THandle->Log)<<4);
01019
01020 pVerts = &WorldCache.Verts[pPoly->FirstVert];
01021
01022 for (j=0; j< pPoly->NumVerts; j++)
01023 {
01024 u = pTVerts->u*ScaleU+ShiftU;
01025 v = pTVerts->v*ScaleV+ShiftV;
01026
01027 pVerts->uv[Stage1].u = u * InvScale;
01028 pVerts->uv[Stage1].v = v * InvScale;
01029
01030 u = pTVerts->u + ShiftU2;
01031 v = pTVerts->v + ShiftV2;
01032
01033 pVerts->uv[Stage2].u = u * InvScale2;
01034 pVerts->uv[Stage2].v = v * InvScale2;
01035
01036 pVerts->color = pTVerts->Color;
01037
01038 pTVerts++;
01039 pVerts++;
01040 }
01041
01042 break;
01043 }
01044
01045 default:
01046 return FALSE;
01047 }
01048
01049 return TRUE;
01050 }
01051
01052
01053
01054 static int BitmapHandleComp(const void *a, const void *b)
01055 {
01056 int32 Id1, Id2;
01057
01058 Id1 = (*(World_Poly**)a)->SortKey;
01059 Id2 = (*(World_Poly**)b)->SortKey;
01060
01061 if ( Id1 == Id2)
01062 return 0;
01063
01064 if (Id1 < Id2)
01065 return -1;
01066
01067 return 1;
01068 }
01069
01070
01071
01072 static void SortWorldPolysByHandle(void)
01073 {
01074 World_Poly *pPoly;
01075 int32 i;
01076
01077 pPoly = WorldCache.Polys;
01078
01079 for (i=0; i<WorldCache.NumPolys; i++)
01080 {
01081 WorldCache.SortedPolys[i] = pPoly;
01082 pPoly++;
01083 }
01084
01085
01086 qsort(&WorldCache.SortedPolys, WorldCache.NumPolys, sizeof(WorldCache.SortedPolys[0]), BitmapHandleComp);
01087 }
01088
01089 #define TSTAGE_0 0
01090 #define TSTAGE_1 1
01091
01092 D3DTEXTUREHANDLE OldId;
01093 LPDIRECT3DTEXTURE2 OldTexture[8];
01094
01095
01096
01097 static BOOL RenderWorldPolys(int32 RenderMode)
01098 {
01099 World_Poly *pPoly;
01100 int32 i;
01101
01102 if(!AppInfo.RenderingIsOK)
01103 {
01104 return TRUE;
01105 }
01106 switch (RenderMode)
01107 {
01108 case RENDER_WORLD_POLYS_NORMAL:
01109 {
01110 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
01111
01112
01113 D3DBlendEnable(TRUE);
01114 D3DBlendFunc (D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
01115
01116
01117 SortWorldPolysByHandle();
01118
01119 for (i=0; i< WorldCache.NumPolys; i++)
01120 {
01121 pPoly = WorldCache.SortedPolys[i];
01122
01123 if (pPoly->Flags & DRV_RENDER_CLAMP_UV)
01124 D3DTexWrap(0, FALSE);
01125 else
01126 D3DTexWrap(0, TRUE);
01127
01128 if (!SetupTexture(0, pPoly->THandle, pPoly->MipLevel))
01129 return GE_FALSE;
01130
01131 World_PolyPrepVerts(pPoly, PREP_WORLD_VERTS_NORMAL, 0, 0);
01132
01133 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01134 }
01135
01136 break;
01137 }
01138
01139 case RENDER_WORLD_POLYS_LMAP:
01140 {
01141 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
01142
01143 D3DTexWrap(0, FALSE);
01144
01145 D3DBlendEnable(TRUE);
01146 D3DBlendFunc (D3DBLEND_DESTCOLOR, D3DBLEND_ZERO);
01147
01148 pPoly = WorldCache.Polys;
01149 BOOL Dynamic = 0;
01150
01151 for (i=0; i< WorldCache.NumPolys; i++, pPoly++)
01152 {
01153
01154 if (!pPoly->LInfo)
01155 continue;
01156
01157
01158 D3DDRV.SetupLightmap(pPoly->LInfo, &Dynamic);
01159
01160 if (!SetupLMap(0, pPoly->LInfo, 0, Dynamic))
01161 return GE_FALSE;
01162
01163 World_PolyPrepVerts(pPoly, PREP_WORLD_VERTS_LMAP, 0, 0);
01164
01165 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01166
01167 if (pPoly->LInfo->RGBLight[1])
01168 {
01169 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE);
01170
01171 D3DBlendFunc (D3DBLEND_ONE, D3DBLEND_ONE);
01172
01173
01174
01175 pPoly->LInfo->THandle->MipData[0].Slot = NULL;
01176
01177 if (!SetupLMap(0, pPoly->LInfo, 1, 1))
01178 return GE_FALSE;
01179
01180 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01181
01182 D3DBlendFunc (D3DBLEND_DESTCOLOR, D3DBLEND_ZERO);
01183
01184 if (AppInfo.FogEnable)
01185 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , TRUE);
01186 }
01187 }
01188 break;
01189 }
01190
01191 case RENDER_WORLD_POLYS_SINGLE_PASS:
01192 {
01193
01194 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
01195 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
01196 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
01197 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
01198 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
01199 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
01200 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
01201
01202 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1 );
01203 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
01204 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
01205 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
01206 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
01207 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
01208
01209 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
01210
01211
01212 D3DBlendEnable(TRUE);
01213 D3DBlendFunc (D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
01214
01215
01216 D3DTexWrap(TSTAGE_0, TRUE);
01217 D3DTexWrap(TSTAGE_1, FALSE);
01218
01219
01220 SortWorldPolysByHandle();
01221
01222
01223 WorldCache.NumPolys2 = 0;
01224
01225 for (i=0; i< WorldCache.NumPolys; i++)
01226 {
01227 BOOL Dynamic = 0;
01228
01229 pPoly = WorldCache.SortedPolys[i];
01230
01231 if (!pPoly->LInfo)
01232 {
01233
01234 WorldCache.SortedPolys2[WorldCache.NumPolys2++] = pPoly;
01235 continue;
01236 }
01237
01238 if (pPoly->Flags & DRV_RENDER_CLAMP_UV)
01239 D3DTexWrap(TSTAGE_0, FALSE);
01240 else
01241 D3DTexWrap(TSTAGE_0, TRUE);
01242
01243 if (!SetupTexture(TSTAGE_0, pPoly->THandle, pPoly->MipLevel))
01244 return GE_FALSE;
01245
01246
01247 D3DDRV.SetupLightmap(pPoly->LInfo, &Dynamic);
01248
01249 if (!SetupLMap(TSTAGE_1, pPoly->LInfo, 0, Dynamic))
01250 return GE_FALSE;
01251
01252
01253 World_PolyPrepVerts(pPoly, PREP_WORLD_VERTS_SINGLE_PASS, TSTAGE_0, TSTAGE_1);
01254
01255 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable)
01256 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , FALSE);
01257
01258
01259 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01260
01261 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable)
01262 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , TRUE);
01263
01264
01265 if (pPoly->LInfo->RGBLight[1])
01266 {
01267 D3DBlendFunc (D3DBLEND_ONE, D3DBLEND_ONE);
01268
01269 #if (TSTAGE_0 == 0)
01270 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
01271 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
01272
01273 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
01274 #else
01275 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
01276 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
01277 #endif
01278
01279
01280
01281 pPoly->LInfo->THandle->MipData[0].Slot = NULL;
01282
01283 if (!SetupLMap(TSTAGE_1, pPoly->LInfo, 1, 1))
01284 return GE_FALSE;
01285
01286 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01287
01288
01289 #if (TSTAGE_0 == 0)
01290 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
01291 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
01292
01293 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
01294 #else
01295 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
01296 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
01297 #endif
01298
01299 D3DBlendFunc (D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
01300 }
01301
01302
01303 }
01304
01305
01306 #if (TSTAGE_0 == 0)
01307 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
01308 AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
01309 #else
01310 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
01311 AppInfo.lpD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
01312 #endif
01313
01314
01315 for (i=0; i< WorldCache.NumPolys2; i++)
01316 {
01317 BOOL Dynamic = 0;
01318
01319 pPoly = WorldCache.SortedPolys2[i];
01320
01321 if (pPoly->Flags & DRV_RENDER_CLAMP_UV)
01322 D3DTexWrap(TSTAGE_0, FALSE);
01323 else
01324 D3DTexWrap(TSTAGE_0, TRUE);
01325
01326 if (!SetupTexture(TSTAGE_0, pPoly->THandle, pPoly->MipLevel))
01327 return GE_FALSE;
01328
01329
01330 World_PolyPrepVerts(pPoly, PREP_WORLD_VERTS_NORMAL, TSTAGE_0, TSTAGE_1);
01331
01332 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable)
01333 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , FALSE);
01334
01335
01336 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01337
01338 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable)
01339 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , TRUE);
01340 }
01341
01342 break;
01343 }
01344
01345 default:
01346 return FALSE;
01347 }
01348
01349
01350 return TRUE;
01351 }
01352
01353
01354
01355
01356 static BOOL ClearWorldCache(void)
01357 {
01358 WorldCache.NumPolys = 0;
01359 WorldCache.NumVerts = 0;
01360
01361 return TRUE;
01362 }
01363
01364
01365
01366 BOOL PCache_Reset(void)
01367 {
01368 WorldCache.NumPolys = 0;
01369 WorldCache.NumVerts = 0;
01370
01371 MiscCache.NumPolys = 0;
01372 MiscCache.NumVerts = 0;
01373
01374 return TRUE;
01375 }
01376
01377
01378
01379
01380 static int32 GetMipLevel(DRV_TLVertex *Verts, int32 NumVerts, geFloat ScaleU, geFloat ScaleV, int32 MaxMipLevel)
01381 {
01382 int32 Mip;
01383
01384 if (MaxMipLevel == 0)
01385 return 0;
01386
01387
01388
01389
01390 {
01391 geFloat du, dv, dx, dy, MipScale;
01392
01393 #if 1 // WAY slower, but more accurate
01394 int32 i;
01395
01396 MipScale = 999999.0f;
01397
01398 geFloat MipScaleT;
01399 DRV_TLVertex *pVert0, *pVert1;
01400 int32 i2;
01401
01402 for (i=0; i< NumVerts; i++)
01403 {
01404
01405 i2 = i+1;
01406
01407 if (i2 >= NumVerts)
01408 i2=0;
01409
01410 pVert0 = &Verts[i];
01411 pVert1 = &Verts[i2];
01412
01413 du = pVert1->u - pVert0->u;
01414 dv = pVert1->v - pVert0->v;
01415 dx = pVert1->x - pVert0->x;
01416 dy = pVert1->y - pVert0->y;
01417
01418 du *= ScaleU;
01419 dv *= ScaleV;
01420
01421 MipScaleT = ((du*du)+(dv*dv)) / ((dx*dx)+(dy*dy));
01422
01423 if (MipScaleT < MipScale)
01424 MipScale = MipScaleT;
01425 }
01426 #else // Faster, less accurate
01427 du = Verts[1].u - Verts[0].u;
01428 dv = Verts[1].v - Verts[0].v;
01429 dx = Verts[1].x - Verts[0].x;
01430 dy = Verts[1].y - Verts[0].y;
01431
01432 du *= ScaleU;
01433 dv *= ScaleV;
01434
01435 MipScale = ((du*du)+(dv*dv)) / ((dx*dx)+(dy*dy));
01436 #endif
01437
01438 #if 0
01439 if (MipScale <= 5)
01440 Mip = 0;
01441 else if (MipScale <= 20)
01442 Mip = 1;
01443 else if (MipScale <= 45)
01444 Mip = 2;
01445 else
01446 Mip = 3;
01447 #else
01448 if (MipScale <= 4)
01449 Mip = 0;
01450 else if (MipScale <= 15)
01451 Mip = 1;
01452 else if (MipScale <= 40)
01453 Mip = 2;
01454 else
01455 Mip = 3;
01456 #endif
01457 }
01458
01459 if (Mip > MaxMipLevel)
01460 Mip = MaxMipLevel;
01461
01462 return Mip;
01463 }