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