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 /*   03/10/2002 Wendell Buckner                                                         */
00008 /*    Procedural Textures                                                               */
00009 /*    if you must lock a texture specify the flags WRITEONLY and DISCARDCONTENTS when   */
00010 /*       01/24/2002 Wendell Buckner                                                         */ 
00011 /*    Change flags for speed...                                                         */ 
00012 /*   02/28/2001 Wendell Buckner                                                         */ 
00013 /*    These render states are unsupported d3d 7.0                                       */ 
00014 /*   02/25/2001 Wendell Buckner                                                         */ 
00015 /*    This texture pointer is no longer valid under directx 7.  Set it to TRUE so there */ 
00016 /*    is something there when  the code does assert checks.                             */ 
00017 /*   07/16/2000 Wendell Buckner                                                         */ 
00018 /*    Convert to Directx7...                                                            */ 
00019 /*                                                                                      */
00020 /*  The contents of this file are subject to the Genesis3D Public License               */
00021 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00022 /*  compliance with the License. You may obtain a copy of the License at                */
00023 /*  http://www.genesis3d.com                                                            */
00024 /*                                                                                      */
00025 /*  Software distributed under the License is distributed on an "AS IS"                 */
00026 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00027 /*  the License for the specific language governing rights and limitations              */
00028 /*  under the License.                                                                  */
00029 /*                                                                                      */
00030 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00031 /*Genesis3D Version 1.1 released November 15, 1999                            */
00032 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
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 /*  07/16/2000 Wendell Buckner
00044 /*   Convert to Directx7...    
00045 #include "D3DDrv.h"              */
00046 #include "D3DDrv7x.h"
00047 
00048 #include "THandle.h"
00049 #include "D3D_Err.h"
00050 
00051 
00052 //#define D3D_MANAGE_TEXTURES
00053 #define SUPER_FLUSH
00054 
00055 //====================================================================================
00056 //      Local static variables
00057 //====================================================================================
00058 
00059 DRV_CacheInfo                                           CacheInfo;
00060 
00061 //
00062 //      World Cache
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         //float         a;
00088         uint32          Color;
00089 } PCache_TVert;
00090 
00091 typedef struct
00092 {
00093         geRDriver_THandle       *THandle;
00094 
00095         DRV_LInfo       *LInfo;                                         // Original pointer to linfo
00096         uint32          Flags;                                          // Flags for this poly
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 // Verts we defined in the D3D flexible vertex format (FVF)
00110 // This is a transformed and lit vertex definition, with up to 8 sets of uvs
00111 typedef struct
00112 {
00113         float                   u,v;
00114 } PCache_UVSet;
00115 
00116 typedef struct
00117 {
00118         float                   x,y,z;                                  // Screen x, y, z
00119         float                   rhw;                                    // homogenous w
00120         DWORD                   color;                                  // color
00121         DWORD                   specular;
00122         PCache_UVSet    uv[MAX_TEXTURE_STAGES]; // uv sets for each stage
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];           // Original uv
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 //      Misc cache
00151 //
00152 
00153 typedef struct
00154 {
00155         geRDriver_THandle       *THandle;
00156         uint32          Flags;                                          // Flags for this poly
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         //float                 ZVert[MAX_MISC_POLY_VERTS];
00170 
00171         int32                   NumPolys;
00172         int32                   NumVerts;
00173 } Misc_Cache;
00174 
00175 static Misc_Cache               MiscCache;
00176 
00177 //====================================================================================
00178 //      Local static functions prototypes
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 //      PCache_InsertWorldPoly
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                 // If the cache is full, we must flush it before going on...
00212                 if (!PCache_FlushWorldPolys())
00213                         return GE_FALSE;
00214         }
00215         else if (WorldCache.NumPolys+1 >= MAX_WORLD_POLYS)
00216         {
00217                 // If the cache is full, we must flush it before going on...
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         // Get a pointer to the original polys verts
00228         pVerts = Verts;
00229         
00230         // Store info about this poly in the cache
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         // Don't forget the sort key:
00245         pCachePoly->SortKey = ((THandle - TextureHandles)<<4)+Mip;
00246 
00247         // Get a pointer into the world verts
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); // ZBUFFER
00264                 pD3DVerts->rhw = ZRecip;
00265 
00266                 if (AppInfo.FogEnable && !(Flags & DRV_RENDER_POLY_NO_FOG)) // poly 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);             // Alpha component in specular is the fog value (0...255)
00284                 }
00285                 else
00286                         pD3DVerts->specular = 0;
00287                 
00288                 // Store the uv's so the prep pass can use them...
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         // Update globals about the world poly cache
00301         WorldCache.NumVerts += NumVerts;
00302         WorldCache.NumPolys++;
00303 
00304         return TRUE;
00305 }
00306 
00307 //====================================================================================
00308 //      PCache_FlushWorldPolys
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                 // Render them as normal
00325                 if (!RenderWorldPolys(RENDER_WORLD_POLYS_NORMAL))
00326                         return GE_FALSE;
00327 
00328                 // Render them as lmaps
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         // Sort the polys
00371         qsort(&MiscCache.SortedPolys, MiscCache.NumPolys, sizeof(MiscCache.SortedPolys[0]), MiscBitmapHandleComp);
00372 }
00373 
00374 //=====================================================================================
00375 //      FillLMapSurface
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 //      FillLMapSurface
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 /* 07/16/2000 Wendell Buckner
00436     Convert to Directx7...    
00437         LPDIRECTDRAWSURFACE4    Surface; */
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 /* 03/10/2002 Wendell Buckner
00458     Procedural Textures
00459     if you must lock a texture specify the flags WRITEONLY and DISCARDCONTENTS when 
00460         Result = Surface->Lock((RECT*)pRect, &SurfDesc, DDLOCK_WAIT, NULL); */
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 //      LoadLMapFromSystem
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 /*   07/16/2000 Wendell Buckner                                                          
00504 /*    Convert to Directx7...                                                             
00505         LPDIRECTDRAWSURFACE4 Surface;                                                       */
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 /* 03/10/2002 Wendell Buckner
00528     Procedural Textures
00529     if you must lock a texture specify the flags WRITEONLY and DISCARDCONTENTS when 
00530     ddrval = Surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);*/
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 //      SetupMipData
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 /* 02/28/2001 Wendell Buckner
00583    These render states are unsupported d3d 7.0
00584                 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FLUSHBATCH, 0);*/            
00585         #endif
00586 
00587                 return GE_FALSE;
00588         }
00589 
00590         return GE_TRUE;
00591 }
00592 
00593 //=====================================================================================
00594 //      SetupLMap
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                         // Find another block
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 /*   02/25/2001 Wendell Buckner
00651 /*    This texture pointer is no longer valid under directx 7.  Set it to TRUE so there is
00652 /*    something there when  the code does assert checks.
00653                 D3DSetTexture(Stage, THandle->MipData[0].Texture);*/
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;               // Force an upload
00678                 CacheInfo.LMapMisses++;
00679         }
00680 
00681         if (MipData->Flags & THANDLE_UPDATE)
00682         {
00683                 HRESULT                                 Error;
00684 
00685 /* 07/16/2000 Wendell Buckner
00686     Convert to Directx7...    
00687         LPDIRECTDRAWSURFACE4    Surface; */
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 /*  03/10/2002 Wendell Buckner
00702      Optimization from GeForce_Optimization2.doc                                        
00703      Procedural Textures
00704      Also, Load is even faster than BLT under Dx7.
00705          Error = AppInfo.lpD3DDevice->Load ( Surface, NULL, SystemToVideo[THandle->Log].Surface, NULL, NULL );  */
00706 
00707 /*      01/24/2002 Wendell Buckner
00708     Change flags for speed...
00709                 Error = Surface->BltFast(0, 0, SystemToVideo[THandle->Log].Surface, NULL, DDBLTFAST_WAIT); */
00710                 Error = Surface->BltFast(0, 0, SystemToVideo[THandle->Log].Surface, NULL, DDBLTFAST_DONOTWAIT );
00711         
00712                 
00713                 //Error = Surface->BltFast(0, 0, SystemToVideo[THandle->Log].Surface, NULL, 0);
00714                 //Error = Surface->Blt(NULL, SystemToVideo[THandle->Log].Surface, NULL, DDBLT_WAIT, NULL);
00715                 //Error = Surface->Blt(NULL, SystemToVideo[THandle->Log].Surface, NULL, 0, NULL);
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)            // If it was dynmamic, force an update for one more frame
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 //      SetupTexture
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;               // Force an upload
00760                 CacheInfo.TexMisses++;
00761         }
00762 
00763         if (MipData->Flags & THANDLE_UPDATE)
00764         {
00765                 HRESULT                                 Error;
00766 
00767 /* 07/16/2000 Wendell Buckner
00768     Convert to Directx7...    
00769         LPDIRECTDRAWSURFACE4    Surface; */
00770                 LPDIRECTDRAWSURFACE7    Surface;
00771                 
00772 
00773                 Surface = D3DCache_SlotGetSurface(MipData->Slot);
00774 
00775 /*  03/10/2002 Wendell Buckner
00776      Optimization from GeForce_Optimization2.doc                                        
00777      Procedural Textures
00778      Also, Load is even faster than BLT under Dx7.
00779      Error = AppInfo.lpD3DDevice->Load ( Surface, NULL, MipData->Surface, NULL, NULL );*/
00780 
00781 /*      01/24/2002 Wendell Buckner
00782     Change flags for speed...
00783                 Error = Surface->BltFast(0, 0, MipData->Surface, NULL, DDBLTFAST_WAIT);*/
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 //      PCache_FlushMiscPolys
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         // Set the render states
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);         // Reset texture stage 1
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         // Sort the polys by handle
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)         // We are assuming that this is not going to change all that much
00853                         D3DZEnable(FALSE);
00854                 else
00855                         D3DZEnable(TRUE);
00856 
00857                 if (pPoly->Flags & DRV_RENDER_NO_ZWRITE)        // We are assuming that this is not going to change all that much
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) // poly fog
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) // poly fog
00876                         AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , TRUE);
00877         }
00878 
00879         // Turn z stuff back on...
00880         D3DZWriteEnable (TRUE);
00881         D3DZEnable(TRUE);
00882         
00883         MiscCache.NumPolys = 0;
00884         MiscCache.NumVerts = 0;
00885 
00886 #ifdef SUPER_FLUSH
00887 /* 02/28/2001 Wendell Buckner
00888    These render states are unsupported d3d 7.0
00889         AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FLUSHBATCH, 0);*/
00890         AppInfo.lpD3DDevice->EndScene();
00891         AppInfo.lpD3DDevice->BeginScene();
00892 #endif
00893 
00894         return TRUE;
00895 }
00896 
00897 //====================================================================================
00898 //      PCache_InsertMiscPoly
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                 // If the cache is full, we must flush it before going on...
00912                 PCache_FlushMiscPolys();
00913         }
00914         else if (MiscCache.NumPolys+1 >= MAX_MISC_POLYS)
00915         {
00916                 // If the cache is full, we must flush it before going on...
00917                 PCache_FlushMiscPolys();
00918         }
00919 
00920         Mip = GetMipLevel(Verts, NumVerts, (float)THandle->Width, (float)THandle->Height, THandle->NumMipLevels-1);
00921 
00922         // Store info about this poly in the cache
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         // Get scale value for vertices
00933         //TCache_GetUVInvScale(Bitmap, Mip, &InvScale);
00934         InvScale = 1.0f / (float)((1<<THandle->Log));
00935 
00936         // Convert them to take account that the vertices are allready from 0 to 1
00937         ScaleU = (float)THandle->Width * InvScale;
00938         ScaleV = (float)THandle->Height * InvScale;
00939 
00940         // Precompute the alpha value...
00941         SAlpha = ((int32)Verts->a)<<24;
00942 
00943         // Get a pointer to the original polys verts
00944         pVerts = Verts;
00945         // Get a pointer into the world verts
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);         // ZBUFFER
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) ) // poly 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);             // Alpha component in specular is the fog value (0...255)
00984                 }
00985                 else
00986                         pD3DVerts->specular = 0;
00987 
00988                 pVerts++;
00989                 pD3DVerts++;
00990         }
00991         
00992         // Update globals about the misc poly cache
00993         MiscCache.NumVerts += NumVerts;
00994         MiscCache.NumPolys++;
00995 
00996         return TRUE;
00997 }
00998 
00999 //====================================================================================
01000 //      **** LOCAL STATIC FUNCTIONS *****
01001 //====================================================================================
01002 
01003 //====================================================================================
01004 //      World_PolyPrepVerts
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                         // Get scale value for vertices
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                         // Get scale value for vertices
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                         // Set up shifts and scaled for texture uv's
01086                         ShiftU = pPoly->ShiftU;
01087                         ShiftV = pPoly->ShiftV;
01088                         ScaleU = pPoly->ScaleU;
01089                         ScaleV = pPoly->ScaleV;
01090 
01091                         // Get scale value for vertices
01092                         InvScale = 1.0f / (float)((1<<pPoly->THandle->Log));
01093 
01094                         // Set up shifts and scaled for lightmap uv's
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         // Sort the polys
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 /*   07/16/2000 Wendell Buckner
01174 /*    Convert to Directx7...    
01175 LPDIRECT3DTEXTURE2              OldTexture[8];*/
01176 LPDIRECTDRAWSURFACE7    OldTexture[8];
01177 
01178 
01179 //====================================================================================
01180 //      RenderWorldPolys
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                         // Set the default state for the normal poly render mode for the world
01198                         D3DBlendEnable(TRUE);
01199                         D3DBlendFunc (D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
01200                         
01201                         // Get the first poly in the sorted list
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                                 // Call the engine to set this sucker up, because it's visible...
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);                              // Change to a fog state
01257 
01258                                         // For some reason, some cards can't upload data to the same texture twice, and have it take.
01259                                         // So we force Fog maps to use a different slot than the lightmap was using...
01260                                         pPoly->LInfo->THandle->MipData[0].Slot = NULL;
01261 
01262                                         if (!SetupLMap(0, pPoly->LInfo, 1, 1))  // Dynamic is 1, because fog is always dynamic
01263                                                 return GE_FALSE;
01264 
01265                                         D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01266                 
01267                                         D3DBlendFunc (D3DBLEND_DESTCOLOR, D3DBLEND_ZERO);               // Restore state
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                         // Setup texture stage states
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                         //AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2 );
01294                         AppInfo.lpD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
01295 
01296                         // Setup frame buffer blend modes
01297                         D3DBlendEnable(TRUE);
01298                         D3DBlendFunc (D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
01299 
01300                         // Set the default state for the normal poly render mode for the world
01301                         D3DTexWrap(TSTAGE_0, TRUE);
01302                         D3DTexWrap(TSTAGE_1, FALSE);
01303 
01304                         // Sort the list for front back operation to get the least number of world texture misses
01305                         SortWorldPolysByHandle();
01306                         
01307                         // Reset non lightmaps faces to 0
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                                         // Put gouraud only polys in a seperate list, and render last
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                                 // Call the engine to set this sucker up, because it's visible...
01332                                 D3DDRV.SetupLightmap(pPoly->LInfo, &Dynamic);
01333 
01334                                 if (!SetupLMap(TSTAGE_1, pPoly->LInfo, 0, Dynamic))
01335                                         return GE_FALSE;
01336                                         
01337                                 // Prep the verts for a lightmap and texture map
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) // poly fog
01341                                                 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , FALSE);
01342 
01343                                 // Draw the texture
01344                                 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01345 
01346                                 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable) // poly fog
01347                                                 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , TRUE);
01348 
01349                                 // Render any fog maps
01350                                 if (pPoly->LInfo->RGBLight[1])
01351                                 {
01352                                         D3DBlendFunc (D3DBLEND_ONE, D3DBLEND_ONE);                              // Change to a fog state
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                                         // For some reason, some cards can't upload data to the same texture twice, and have it take.
01365                                         // So we force Fog maps to use a different slot other than what the lightmap was using...
01366                                         pPoly->LInfo->THandle->MipData[0].Slot = NULL;
01367 
01368                                         if (!SetupLMap(TSTAGE_1, pPoly->LInfo, 1, 1))   // Dynamic is 1, because fog is always dynamic
01369                                                 return GE_FALSE;
01370 
01371                                         D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01372         
01373                                         // Restore states to the last state before fag map
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                         // Setup for any non-lightmaped faces faces, turn tmu1 off
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                         // Render all the faces without lightmaps
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                                 // Prep verts as if there was no lightmap
01415                                 World_PolyPrepVerts(pPoly, PREP_WORLD_VERTS_NORMAL, TSTAGE_0, TSTAGE_1);
01416 
01417                                 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable) // poly fog
01418                                                 AppInfo.lpD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE , FALSE);
01419 
01420                                 // Draw the texture
01421                                 D3DTexturedPoly(&WorldCache.Verts[pPoly->FirstVert], pPoly->NumVerts);
01422 
01423                                 if ( (pPoly->Flags & DRV_RENDER_POLY_NO_FOG) && AppInfo.FogEnable) // poly fog
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 //      ClearWorldCache
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 //      GetMipLevel
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         //      Get the MipLevel
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;           // Record the best MipScale (the one closest to the the eye)
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)              // 2, 6, 12
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)              // 2, 6, 12
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 }

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