Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

Pcache.cpp

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  PCache.cpp                                                                          */
00003 /*                                                                                      */
00004 /*  Author: John Pollard                                                                */
00005 /*  Description: D3D poly cache                                                         */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
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 //#define D3D_MANAGE_TEXTURES
00035 //#define SUPER_FLUSH
00036 
00037 //====================================================================================
00038 //      Local static variables
00039 //====================================================================================
00040 
00041 DRV_CacheInfo                                           CacheInfo;
00042 
00043 //
00044 //      World Cache
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         //geFloat               a;
00070         uint32          Color;
00071 } PCache_TVert;
00072 
00073 typedef struct
00074 {
00075         geRDriver_THandle       *THandle;
00076 
00077         DRV_LInfo       *LInfo;                                         // Original pointer to linfo
00078         uint32          Flags;                                          // Flags for this poly
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 // Verts we defined in the D3D flexible vertex format (FVF)
00092 // This is a transformed and lit vertex definition, with up to 8 sets of uvs
00093 typedef struct
00094 {
00095         geFloat                 u,v;
00096 } PCache_UVSet;
00097 
00098 typedef struct
00099 {
00100         geFloat                 x,y,z;                                  // Screen x, y, z
00101         geFloat                 rhw;                                    // homogenous w
00102         DWORD                   color;                                  // color
00103         DWORD                   specular;
00104         PCache_UVSet    uv[MAX_TEXTURE_STAGES]; // uv sets for each stage
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];           // Original uv
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 //      Misc cache
00133 //
00134 
00135 typedef struct
00136 {
00137         geRDriver_THandle       *THandle;
00138         uint32          Flags;                                          // Flags for this poly
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         //geFloat                       ZVert[MAX_MISC_POLY_VERTS];
00152 
00153         int32                   NumPolys;
00154         int32                   NumVerts;
00155 } Misc_Cache;
00156 
00157 static Misc_Cache               MiscCache;
00158 
00159 //====================================================================================
00160 //      Local static functions prototypes
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 //      PCache_InsertWorldPoly
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                 // If the cache is full, we must flush it before going on...
00194                 if (!PCache_FlushWorldPolys())
00195                         return GE_FALSE;
00196         }
00197         else if (WorldCache.NumPolys+1 >= MAX_WORLD_POLYS)
00198         {
00199                 // If the cache is full, we must flush it before going on...
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         // Get a pointer to the original polys verts
00210         pVerts = Verts;
00211         
00212         // Store info about this poly in the cache
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         // Don't forget the sort key:
00227         pCachePoly->SortKey = ((THandle - TextureHandles)<<4)+Mip;
00228 
00229         // Get a pointer into the world verts
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); // ZBUFFER
00246                 pD3DVerts->rhw = ZRecip;
00247 
00248                 if (AppInfo.FogEnable && !(Flags & DRV_RENDER_POLY_NO_FOG)) // poly 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);             // Alpha component in specular is the fog value (0...255)
00266                 }
00267                 else
00268                         pD3DVerts->specular = 0;
00269                 
00270                 // Store the uv's so the prep pass can use them...
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         // Update globals about the world poly cache
00283         WorldCache.NumVerts += NumVerts;
00284         WorldCache.NumPolys++;
00285 
00286         return TRUE;
00287 }
00288 
00289 //====================================================================================
00290 //      PCache_FlushWorldPolys
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                 // Render them as normal
00307                 if (!RenderWorldPolys(RENDER_WORLD_POLYS_NORMAL))
00308                         return GE_FALSE;
00309 
00310                 // Render them as lmaps
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         // Sort the polys
00353         qsort(&MiscCache.SortedPolys, MiscCache.NumPolys, sizeof(MiscCache.SortedPolys[0]), MiscBitmapHandleComp);
00354 }
00355 
00356 //=====================================================================================
00357 //      FillLMapSurface
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 //      FillLMapSurface
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 //      LoadLMapFromSystem
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 //      SetupMipData
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 //      SetupLMap
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                         // Find another block
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;               // Force an upload
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                 //Error = Surface->BltFast(0, 0, SystemToVideo[THandle->Log].Surface, NULL, 0);
00654                 //Error = Surface->Blt(NULL, SystemToVideo[THandle->Log].Surface, NULL, DDBLT_WAIT, NULL);
00655                 //Error = Surface->Blt(NULL, SystemToVideo[THandle->Log].Surface, NULL, 0, NULL);
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)            // If it was dynmamic, force an update for one more frame
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 //      SetupTexture
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;               // Force an upload
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 //      PCache_FlushMiscPolys
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         // Set the render states
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);         // Reset texture stage 1
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         // Sort the polys by handle
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)         // We are assuming that this is not going to change all that much
00776                         D3DZEnable(FALSE);
00777                 else
00778                         D3DZEnable(TRUE);
00779 
00780                 if (pPoly->Flags & DRV_RENDER_NO_ZWRITE)        // We are assuming that this is not going to change all that much
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) // poly fog
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) // poly fog
00799                         AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , TRUE);
00800         }
00801 
00802         // Turn z stuff back on...
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 //      PCache_InsertMiscPoly
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                 // If the cache is full, we must flush it before going on...
00833                 PCache_FlushMiscPolys();
00834         }
00835         else if (MiscCache.NumPolys+1 >= MAX_MISC_POLYS)
00836         {
00837                 // If the cache is full, we must flush it before going on...
00838                 PCache_FlushMiscPolys();
00839         }
00840 
00841         Mip = GetMipLevel(Verts, NumVerts, (geFloat)THandle->Width, (geFloat)THandle->Height, THandle->NumMipLevels-1);
00842 
00843         // Store info about this poly in the cache
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         // Get scale value for vertices
00854         //TCache_GetUVInvScale(Bitmap, Mip, &InvScale);
00855         InvScale = 1.0f / (geFloat)((1<<THandle->Log));
00856 
00857         // Convert them to take account that the vertices are allready from 0 to 1
00858         ScaleU = (geFloat)THandle->Width * InvScale;
00859         ScaleV = (geFloat)THandle->Height * InvScale;
00860 
00861         // Precompute the alpha value...
00862         SAlpha = ((int32)Verts->a)<<24;
00863 
00864         // Get a pointer to the original polys verts
00865         pVerts = Verts;
00866         // Get a pointer into the world verts
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);         // ZBUFFER
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) ) // poly 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);             // Alpha component in specular is the fog value (0...255)
00905                 }
00906                 else
00907                         pD3DVerts->specular = 0;
00908 
00909                 pVerts++;
00910                 pD3DVerts++;
00911         }
00912         
00913         // Update globals about the misc poly cache
00914         MiscCache.NumVerts += NumVerts;
00915         MiscCache.NumPolys++;
00916 
00917         return TRUE;
00918 }
00919 
00920 //====================================================================================
00921 //      **** LOCAL STATIC FUNCTIONS *****
00922 //====================================================================================
00923 
00924 //====================================================================================
00925 //      World_PolyPrepVerts
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                         // Get scale value for vertices
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                         // Get scale value for vertices
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                         // Set up shifts and scaled for texture uv's
01007                         ShiftU = pPoly->ShiftU;
01008                         ShiftV = pPoly->ShiftV;
01009                         ScaleU = pPoly->ScaleU;
01010                         ScaleV = pPoly->ScaleV;
01011 
01012                         // Get scale value for vertices
01013                         InvScale = 1.0f / (geFloat)((1<<pPoly->THandle->Log));
01014 
01015                         // Set up shifts and scaled for lightmap uv's
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         // Sort the polys
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 //      RenderWorldPolys
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                         // Set the default state for the normal poly render mode for the world
01113                         D3DBlendEnable(TRUE);
01114                         D3DBlendFunc (D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
01115                         
01116                         // Get the first poly in the sorted list
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                                 // Call the engine to set this sucker up, because it's visible...
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);                              // Change to a fog state
01172 
01173                                         // For some reason, some cards can't upload data to the same texture twice, and have it take.
01174                                         // So we force Fog maps to use a different slot than the lightmap was using...
01175                                         pPoly->LInfo->THandle->MipData[0].Slot = NULL;
01176 
01177                                         if (!SetupLMap(0, pPoly->LInfo, 1, 1))  // Dynamic is 1, because fog is always dynamic
01178                                                 return GE_FALSE;
01179 
01180                                         D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01181                 
01182                                         D3DBlendFunc (D3DBLEND_DESTCOLOR, D3DBLEND_ZERO);               // Restore state
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                         // Setup texture stage states
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                         //AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2 );
01209                         AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
01210 
01211                         // Setup frame buffer blend modes
01212                         D3DBlendEnable(TRUE);
01213                         D3DBlendFunc (D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
01214 
01215                         // Set the default state for the normal poly render mode for the world
01216                         D3DTexWrap(TSTAGE_0, TRUE);
01217                         D3DTexWrap(TSTAGE_1, FALSE);
01218 
01219                         // Sort the list for front back operation to get the least number of world texture misses
01220                         SortWorldPolysByHandle();
01221                         
01222                         // Reset non lightmaps faces to 0
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                                         // Put gouraud only polys in a seperate list, and render last
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                                 // Call the engine to set this sucker up, because it's visible...
01247                                 D3DDRV.SetupLightmap(pPoly->LInfo, &Dynamic);
01248 
01249                                 if (!SetupLMap(TSTAGE_1, pPoly->LInfo, 0, Dynamic))
01250                                         return GE_FALSE;
01251                                         
01252                                 // Prep the verts for a lightmap and texture map
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) // poly fog
01256                                                 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , FALSE);
01257 
01258                                 // Draw the texture
01259                                 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01260 
01261                                 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable) // poly fog
01262                                                 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , TRUE);
01263 
01264                                 // Render any fog maps
01265                                 if (pPoly->LInfo->RGBLight[1])
01266                                 {
01267                                         D3DBlendFunc (D3DBLEND_ONE, D3DBLEND_ONE);                              // Change to a fog state
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                                         // For some reason, some cards can't upload data to the same texture twice, and have it take.
01280                                         // So we force Fog maps to use a different slot other than what the lightmap was using...
01281                                         pPoly->LInfo->THandle->MipData[0].Slot = NULL;
01282 
01283                                         if (!SetupLMap(TSTAGE_1, pPoly->LInfo, 1, 1))   // Dynamic is 1, because fog is always dynamic
01284                                                 return GE_FALSE;
01285 
01286                                         D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01287         
01288                                         // Restore states to the last state before fag map
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                         // Setup for any non-lightmaped faces faces, turn tmu1 off
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                         // Render all the faces without lightmaps
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                                 // Prep verts as if there was no lightmap
01330                                 World_PolyPrepVerts(pPoly, PREP_WORLD_VERTS_NORMAL, TSTAGE_0, TSTAGE_1);
01331 
01332                                 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable) // poly fog
01333                                                 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , FALSE);
01334 
01335                                 // Draw the texture
01336                                 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01337 
01338                                 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable) // poly fog
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 //      ClearWorldCache
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 //      GetMipLevel
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         //      Get the MipLevel
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;           // Record the best MipScale (the one closest to the the eye)
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)              // 2, 6, 12
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)              // 2, 6, 12
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 }

Generated on Tue Sep 30 12:36:07 2003 for GTestAndEngine by doxygen 1.3.2