# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

patch_render.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "std3d.h"
00027 
00028 
00029 #include "3d/patch.h"
00030 #include "3d/tessellation.h"
00031 #include "3d/bezier_patch.h"
00032 #include "3d/zone.h"
00033 #include "3d/landscape.h"
00034 #include "3d/landscape_profile.h"
00035 #include "3d/patchdlm_context.h"
00036 #include "nel/misc/vector.h"
00037 #include "nel/misc/common.h"
00038 using   namespace       std;
00039 using   namespace       NLMISC;
00040 
00041 
00042 namespace NL3D 
00043 {
00044 
00045 
00046 // ***************************************************************************
00047 // ***************************************************************************
00048 // Patch Texture computation.
00049 // ***************************************************************************
00050 // ***************************************************************************
00051 
00052 
00053 // ***************************************************************************
00054 void                    CPatch::computeNewFar(sint &newFar0, sint &newFar1)
00055 {
00056         // Classify the patch.
00057         //========================
00058         float   r= (CLandscapeGlobals::RefineCenter-BSphere.Center).norm() - BSphere.Radius;
00059         float   rr=0.0;
00060         if(r<CLandscapeGlobals::TileDistNear)
00061                 rr= r-CLandscapeGlobals::TileDistNear, newFar0= 0;
00062         else if(r<CLandscapeGlobals::Far0Dist)
00063                 rr= r-CLandscapeGlobals::Far0Dist, newFar0= 1;
00064         else if(r<CLandscapeGlobals::Far1Dist)
00065                 rr= r-CLandscapeGlobals::Far1Dist, newFar0= 2;
00066         else
00067                 newFar0= 3;
00068         // Transition with the next level.
00069         newFar1=0;
00070         if(newFar0<3 && rr>-(CLandscapeGlobals::FarTransition+2*BSphere.Radius))
00071         {
00072                 newFar1= newFar0+1;
00073         }
00074 
00075 
00076         // Update Texture Info.
00077         //========================
00078         if(newFar0!=Far0 || newFar1!=Far1)
00079         {
00080                 // Backup old pass0
00081                 CPatchRdrPass   *oldPass0=Pass0.PatchRdrPass;
00082                 CPatchRdrPass   *oldPass1=Pass1.PatchRdrPass;
00083 
00084                 // Checks
00085                 if (oldPass0==NULL)
00086                         nlassert (Far0<=0);
00087                 if (oldPass1==NULL)
00088                         nlassert (Far1<=0);
00089 
00090                 float oldFar0UScale=Far0UScale;
00091                 float oldFar0VScale=Far0VScale;
00092                 float oldFar0UBias=Far0UBias;
00093                 float oldFar0VBias=Far0VBias;
00094                 uint8 oldFlags=Flags;
00095 
00096 
00097                 // Don't delete the pass0 if the new newFar1 will use it
00098                 if ((newFar1==Far0)&&(Far0>0))
00099                         Pass0.PatchRdrPass=NULL;
00100 
00101                 // Don't delete the pass1 if the new newFar0 will use it
00102                 if ((newFar0==Far1)&&(Far1>0))
00103                         Pass1.PatchRdrPass=NULL;
00104 
00105                 // Pass0 have changed ?
00106                 if (newFar0!=Far0)
00107                 {
00108                         // Compute / get the texture Far.
00109                         if(newFar0>0)
00110                         {
00111                                 // Free the old pass, don't used any more
00112                                 if (Pass0.PatchRdrPass)
00113                                         Zone->Landscape->freeFarRenderPass (this, Pass0.PatchRdrPass, Far0);
00114 
00115                                 // Can we use the old pass1 ?
00116                                 if (newFar0==Far1)
00117                                 {
00118                                         // Yes, recycle it!
00119                                         Pass0.PatchRdrPass=oldPass1;
00120 
00121                                         // Copy uv coordinates
00122                                         Far0UScale=Far1UScale;
00123                                         Far0VScale=Far1VScale;
00124                                         Far0UBias=Far1UBias;
00125                                         Far0VBias=Far1VBias;
00126 
00127                                         // Copy rotation flag
00128                                         Flags&=~NL_PATCH_FAR0_ROTATED;                  // erase it
00129                                         if (Flags&NL_PATCH_FAR1_ROTATED)
00130                                                 Flags|=NL_PATCH_FAR0_ROTATED;                   // copy it
00131                                 }
00132                                 else    // get a new render pass
00133                                 {
00134                                         // Rotation boolean
00135                                         bool bRot;
00136                                         Pass0.PatchRdrPass=Zone->Landscape->getFarRenderPass(this, newFar0, Far0UScale, Far0VScale, Far0UBias, Far0VBias, bRot);
00137 
00138                                         // Flags is set if the far texture is rotated of 90° to the left
00139                                         if (bRot)
00140                                                 Flags|=NL_PATCH_FAR0_ROTATED;
00141                                         else
00142                                                 Flags&=~NL_PATCH_FAR0_ROTATED;
00143                                 }
00144                         }
00145                         else    // no more far pass0
00146                         {
00147                                 if (Pass0.PatchRdrPass)
00148                                 {
00149                                         Zone->Landscape->freeFarRenderPass (this, Pass0.PatchRdrPass, Far0);
00150                                         Pass0.PatchRdrPass=NULL;
00151                                 }
00152                         }
00153                 }
00154 
00155                 // Pass1 have changed ?
00156                 if (newFar1!=Far1)
00157                 {
00158                         // Now let's go with pass1
00159                         if(newFar1>0)
00160                         {
00161                                 // Delete the pass1 if not used any more
00162                                 if (Pass1.PatchRdrPass)
00163                                         Zone->Landscape->freeFarRenderPass (this, Pass1.PatchRdrPass, Far1);
00164 
00165                                 // Can we use the old pass1 ?
00166                                 if (newFar1==Far0)
00167                                 {
00168                                         // Yes, recycle it!
00169                                         Pass1.PatchRdrPass= oldPass0;
00170                                         nlassert (Pass1.PatchRdrPass);
00171 
00172                                         // Copy uv coordinates
00173                                         Far1UScale=oldFar0UScale;
00174                                         Far1VScale=oldFar0VScale;
00175                                         Far1UBias=oldFar0UBias;
00176                                         Far1VBias=oldFar0VBias;
00177 
00178                                         // Copy rotation flag
00179                                         Flags&=~NL_PATCH_FAR1_ROTATED;                  // erase it
00180                                         if (oldFlags&NL_PATCH_FAR0_ROTATED)
00181                                                 Flags|=NL_PATCH_FAR1_ROTATED;                   // copy it
00182                                 }
00183                                 else    // get a new render pass
00184                                 {
00185                                         // Rotation boolean
00186                                         bool bRot;
00187                                         Pass1.PatchRdrPass=Zone->Landscape->getFarRenderPass(this, newFar1, Far1UScale, Far1VScale, Far1UBias, Far1VBias, bRot);
00188                                         nlassert (Pass1.PatchRdrPass);
00189 
00190                                         // Flags is set if the far texture is rotated of 90° to the left
00191                                         if (bRot)
00192                                                 Flags|=NL_PATCH_FAR1_ROTATED;
00193                                         else
00194                                                 Flags&=~NL_PATCH_FAR1_ROTATED;
00195                                 }
00196 
00197                                 // Compute info for transition.
00198                                 float   farDist;
00199                                 switch(newFar1)
00200                                 {
00201                                         case 1: farDist= CLandscapeGlobals::TileDistNear; break;
00202                                         case 2: farDist= CLandscapeGlobals::Far0Dist; break;
00203                                         case 3: farDist= CLandscapeGlobals::Far1Dist; break;
00204                                         default: nlstop;
00205                                 };
00206                                 TransitionSqrMin= sqr(farDist-CLandscapeGlobals::FarTransition);
00207                                 OOTransitionSqrDelta= 1.0f/(sqr(farDist)-TransitionSqrMin);
00208                         }
00209                         else    // no more far pass1
00210                         {
00211                                 if (Pass1.PatchRdrPass)
00212                                 {
00213                                         Zone->Landscape->freeFarRenderPass (this, Pass1.PatchRdrPass, Far1);
00214                                         Pass1.PatchRdrPass=NULL;
00215                                 }
00216                         }
00217                 }
00218 
00219         }
00220 
00221         // Don't copy Far0 and Far1.
00222 }
00223 
00224 
00225 // ***************************************************************************
00226 void                    CPatch::updateTextureFarOnly()
00227 {
00228         // If visible, don't change Far, because VB must be changed too. preRender() should have been called isntead.
00229         if(!RenderClipped)
00230                 return;
00231 
00232         sint    newFar0,newFar1;
00233         // compute new Far0 and new Far1.
00234         computeNewFar(newFar0, newFar1);
00235 
00236         // Far change.
00237         //------------------
00238         // Set new far values
00239         Far0= newFar0;
00240         Far1= newFar1;
00241 }
00242 
00243 
00244 
00245 // ***************************************************************************
00246 // ***************************************************************************
00247 // Patch / Face rendering.
00248 // ***************************************************************************
00249 // ***************************************************************************
00250 
00251 
00252 // ***************************************************************************
00253 void                    CPatch::preRender()
00254 {
00255         // If not visible, do nothing.
00256         if(RenderClipped)
00257                 return;
00258 
00259 
00260         // 0. Classify the patch, and update TextureInfo.
00261         //=======================
00262         sint    newFar0,newFar1;
00263         // compute new Far0 and new Far1.
00264         computeNewFar(newFar0, newFar1);
00265 
00266 
00267         // 2. Update vertices in VB
00268         //========================
00269         sint    oldFar0= Far0, oldFar1= Far1;
00270 
00271         // Test if go in or go out tileMode.
00272         bool    changeTileMode;
00273         // this is true if a change is made, and if old or current is in TileMode.
00274         changeTileMode= (newFar0!=oldFar0) && (newFar0==0 || oldFar0==0);
00275         // Or this is true if Far0 / Far1 was invalid before.
00276         changeTileMode= changeTileMode || oldFar0==-1 || oldFar1==-1;
00277 
00278         // Pre VB change.
00279         //------------------
00280         // In this case, major change: delete all VB, then recreate after.
00281         if(changeTileMode)
00282         {
00283                 // delete the old VB (NB: RenderClipped==false here). 
00284                 // NB: Far0 and Far1 are still unmodified, so deleteVB() will do the good job.
00285                 deleteVBAndFaceVector();
00286         }
00287         else
00288         {
00289                 // minor change: Far0 UV, or Far1.
00290                 // Far0 UV: do nothing here.
00291                 // If change in Far1, must delete Far1
00292                 if(newFar1!=oldFar1)
00293                 {
00294                         // NB: Far1 is still unmodified, so deleteVB() will do the good job.
00295                         deleteVBAndFaceVectorFar1Only();
00296                 }
00297         }
00298 
00299         // Far change.
00300         //------------------
00301         // Set new far values
00302         Far0= newFar0;
00303         Far1= newFar1;
00304 
00305 
00306         // Post VB change.
00307         //------------------
00308         if(changeTileMode)
00309         {
00310                 // major change: recreate all the VB.
00311                 allocateVBAndFaceVector();
00312                 // Then try to refill if possible.
00313                 fillVB();
00314         }
00315         else
00316         {
00317                 // minor change: Far0 UV, or Far1.
00318                 // If change in Far0
00319                 if(newFar0!=oldFar0)
00320                 {
00321                         // Then must recompute VB with good UVs.
00322                         // An optimisation is to check if UVs had really change (see UScale ...)
00323                         // but the case they don't change is very rare: 1/16.
00324                         fillVBFar0Only();
00325                 }
00326 
00327                 // If change in Far1, must allcoate and recompute UVs.
00328                 if(newFar1!=oldFar1)
00329                 {
00330                         allocateVBAndFaceVectorFar1Only();
00331                         // try to fill if no reallocation problem
00332                         fillVBFar1Only();
00333                 }
00334         }
00335 
00336 
00337         // 3. Append patch to renderList.
00338         //=====================
00339         // This patch is visible. So if good far, append.
00340         if(Far0>0)
00341         {
00342                 Pass0.PatchRdrPass->appendRdrPatchFar0(&Pass0, NumRenderableFaces);
00343         }
00344         // Same for Far1.
00345         if(Far1>0)
00346         {
00347                 Pass1.PatchRdrPass->appendRdrPatchFar1(&Pass1, NumRenderableFaces);
00348         }
00349 
00350 
00351         // 4. Clip tess blocks.
00352         //=====================
00353         // If we are in Tile/FarTransition
00354         bool    doClipFar= Far0==0 && Far1==1;
00355         // Parse all TessBlocks.
00356         uint                    nTessBlock= TessBlocks.size();
00357         CTessBlock              *pTessBlock= nTessBlock>0? &TessBlocks[0]: NULL ;
00358         for(; nTessBlock>0; pTessBlock++, nTessBlock--)
00359         {
00360                 CTessBlock              &tblock= *pTessBlock;
00361 
00362                 // bkup the old result for clipping
00363                 bool    oldVisibleFar0= tblock.visibleFar0();
00364                 bool    oldVisibleTile= tblock.visibleTile();
00365                 bool    oldVisibleFar1= tblock.visibleFar1();
00366 
00367                 // If this TessBlock is empty, do not need to clip
00368                 if(tblock.FaceTileMaterialRefCount==0)
00369                 {
00370                         // Simply force the clip.
00371                         tblock.forceClip();
00372                 }
00373                 else
00374                 {
00375                         // clip the tessBlock.
00376                         tblock.resetClip();
00377                         tblock.clip();
00378                         // If we are in Tile/FarTransition
00379                         if(doClipFar)
00380                                 tblock.clipFar(CLandscapeGlobals::RefineCenter, CLandscapeGlobals::TileDistNear, CLandscapeGlobals::FarTransition);
00381 
00382                         // If TileMode, and if tile visible
00383                         if(Far0==0 && tblock.visibleTile() )
00384                         {
00385                                 // Append all tiles (if any) to the renderPass list!
00386                                 for(uint j=0;j<NL3D_TESSBLOCK_TILESIZE; j++)
00387                                 {
00388                                         // If tile exist
00389                                         if(tblock.RdrTileRoot[j])
00390                                                 // add it to the renderList
00391                                                 tblock.RdrTileRoot[j]->appendTileToEachRenderPass(NumRenderableFaces);
00392                                 }
00393                         }       
00394                 }
00395 
00396                 // If change of clip in tessBlock, must update the tessBlock
00397                 if( Far0> 0 && oldVisibleFar0 != tblock.visibleFar0() )
00398                 {
00399                         if( tblock.visibleFar0() )
00400                         {
00401                                 // allocate
00402                                 updateFar0VBAlloc(tblock.FarVertexList, true);
00403                                 // fill only if possible.
00404                                 if(!CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs())
00405                                         fillFar0VertexListVB(tblock.FarVertexList);
00406                                 // rebuild triangles index list.
00407                                 tblock.refillFaceVectorFar0();
00408                         }
00409                         else
00410                         {
00411                                 // delete
00412                                 updateFar0VBAlloc(tblock.FarVertexList, false);
00413                         }
00414                 }
00415                 if( Far0==0 && oldVisibleTile != tblock.visibleTile() )
00416                 {
00417                         if( tblock.visibleTile() )
00418                         {
00419                                 // allocate
00420                                 updateTileVBAlloc(tblock.NearVertexList, true);
00421                                 // fill only if possible.
00422                                 if(!CLandscapeGlobals::CurrentTileVBAllocator->reallocationOccurs())
00423                                         fillTileVertexListVB(tblock.NearVertexList);
00424                                 // rebuild triangles index list.
00425                                 tblock.refillFaceVectorTile();
00426                         }
00427                         else
00428                         {
00429                                 // delete
00430                                 updateTileVBAlloc(tblock.NearVertexList, false);
00431                         }
00432                 }
00433                 if( Far1> 0 && oldVisibleFar1 != tblock.visibleFar1() )
00434                 {
00435                         if( tblock.visibleFar1() )
00436                         {
00437                                 // allocate
00438                                 updateFar1VBAlloc(tblock.FarVertexList, true);
00439                                 // fill only if possible.
00440                                 if(!CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs())
00441                                         fillFar1VertexListVB(tblock.FarVertexList);
00442                                 // rebuild triangles index list.
00443                                 tblock.refillFaceVectorFar1();
00444                         }
00445                         else
00446                         {
00447                                 // delete
00448                                 updateFar1VBAlloc(tblock.FarVertexList, false);
00449                         }
00450                 }
00451         }
00452 
00453 }
00454 
00455 
00456 // Special profiling.
00457 #ifdef  NL3D_PROFILE_LAND
00458 #define NL3D_PROFILE_LAND_ADD_FACE_VECTOR(_x, _fv)              \
00459         if(_fv)                                                                                 \
00460         {                                                                                               \
00461                 NL3D_PROFILE_LAND_ADD(_x, _fv->NumTri);         \
00462         }
00463 #else
00464 #define NL3D_PROFILE_LAND_ADD_FACE_VECTOR(_x, _fv)
00465 #endif
00466 
00467 
00468 // ***************************************************************************
00469 static  inline  void    renderFaceVector(CLandscapeFaceVector *fv)
00470 {
00471         // If not NULL (ie not empty).
00472         if(fv)
00473         {
00474                 // TestYoyo: Bench.
00475                 /*
00476                 extern  uint    TEMP_NRFV;
00477                 extern  uint    TEMP_NRFVTri;
00478                 extern  float   TEMP_NRFVMeanTri;
00479                 extern  float   TEMP_NRFVDeltaTri;
00480                 TEMP_NRFV++;
00481                 TEMP_NRFVTri+= fv->NumTri;
00482                 TEMP_NRFVDeltaTri+= sqr(fv->NumTri-TEMP_NRFVMeanTri);
00483                 */
00484 
00485                 // here we have NumTri>0, because fv!=NULL.
00486 
00487                 // making lot of render() is slower than copy a block, and render it.
00488                 //CLandscapeGlobals::PatchCurrentDriver->renderSimpleTriangles(fv->TriPtr, fv->NumTri);
00489 
00490 #ifdef  NL_OS_WINDOWS
00491                 __asm
00492                 {
00493                         mov             ebx, fv
00494                         mov             edi, NL3D_LandscapeGlobals_PassTriCurPtr
00495 
00496                         mov             edx, NL3D_LandscapeGlobals_PassNTri
00497                         xor             eax, eax                // Avoid AGI stall.
00498 
00499                         mov             ecx, [ebx]fv.NumTri
00500                         mov             esi, [ebx]fv.TriPtr
00501 
00502                         mov             eax, ecx                                // eax= bkup NumTris
00503                         lea             ecx, [ecx + ecx*2]              // ecx= nTriIndex= NumTris*3
00504 
00505                         // copy tri indices
00506                         rep             movsd
00507 
00508                         add             edx, eax                                // edx= NL3D_LandscapeGlobals_PassNTri + fv->NumTri;
00509 
00510                         // NL3D_LandscapeGlobals_PassTriCurPtr= edi= new ptr after copy
00511                         mov             NL3D_LandscapeGlobals_PassTriCurPtr, edi
00512                         mov             NL3D_LandscapeGlobals_PassNTri, edx
00513                 }
00514 #else
00515                 uint    nTriIndex= fv->NumTri*3;
00516                 // Fill and increment the array.
00517                 memcpy( NL3D_LandscapeGlobals_PassTriCurPtr, fv->TriPtr, nTriIndex * sizeof(uint32) );
00518                 NL3D_LandscapeGlobals_PassTriCurPtr+= nTriIndex;
00519                 NL3D_LandscapeGlobals_PassNTri+= fv->NumTri;
00520 #endif
00521         }
00522 }
00523 
00524 
00525 // ***************************************************************************
00526 void                    CPatch::renderFar0()
00527 {
00528         // Must be visible, and must be called only if the RdrPass is enabled.
00529         nlassert(!RenderClipped && Pass0.PatchRdrPass);
00530 
00531         // Render tris of MasterBlock.
00532         renderFaceVector(MasterBlock.Far0FaceVector);
00533         // profile
00534         NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar0, MasterBlock.Far0FaceVector);
00535 
00536         // Render tris of TessBlocks.
00537         uint                    nTessBlock= TessBlocks.size();
00538         CTessBlock              *pTessBlock= nTessBlock>0? &TessBlocks[0]: NULL ;
00539         for(; nTessBlock>0; pTessBlock++, nTessBlock--)
00540         {
00541                 CTessBlock              &tblock= *pTessBlock;
00542                 // if block visible, render
00543                 if( tblock.visibleFar0() )
00544                 {
00545                         renderFaceVector(tblock.Far0FaceVector);
00546                         // profile
00547                         NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar0, tblock.Far0FaceVector);
00548                 }
00549         }
00550 
00551         // Check the pass is in the set
00552 #ifdef NL_DEBUG
00553         if (Pass0.PatchRdrPass)
00554         {
00555                 nlassert (Zone->Landscape->_FarRdrPassSet.find (Pass0.PatchRdrPass)!=Zone->Landscape->_FarRdrPassSet.end());
00556                 if (Zone->Landscape->_FarRdrPassSet.find (Pass0.PatchRdrPass)==Zone->Landscape->_FarRdrPassSet.end())
00557                 {
00558                         bool bFound=false;
00559                         {
00560                                 for (sint t=0; t<(sint)Zone->Landscape->_FarRdrPassSetVectorFree.size(); t++)
00561                                 {
00562                                         if (Zone->Landscape->_FarRdrPassSetVectorFree[t].find (Pass0.PatchRdrPass)!=Zone->Landscape->_FarRdrPassSetVectorFree[t].end())
00563                                         {
00564                                                 bFound=true;
00565                                                 break;
00566                                         }
00567                                 }
00568                         }
00569                         nlassert (bFound);
00570                 }
00571         }
00572 #endif // NL_DEBUG
00573 }
00574 
00575 
00576 // ***************************************************************************
00577 void                    CPatch::renderFar1()
00578 {
00579         // Must be visible, and must be called only if the RdrPass is enabled.
00580         nlassert(!RenderClipped && Pass1.PatchRdrPass);
00581 
00582         // Render tris of MasterBlock.
00583         renderFaceVector(MasterBlock.Far1FaceVector);
00584         // profile.
00585         NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar1, MasterBlock.Far1FaceVector);
00586 
00587         // Render tris of TessBlocks.
00588         uint                    nTessBlock= TessBlocks.size();
00589         CTessBlock              *pTessBlock= nTessBlock>0? &TessBlocks[0]: NULL ;
00590         for(; nTessBlock>0; pTessBlock++, nTessBlock--)
00591         {
00592                 CTessBlock              &tblock= *pTessBlock;
00593                 // if block visible, render
00594                 if( tblock.visibleFar1() )
00595                 {
00596                         renderFaceVector(tblock.Far1FaceVector);
00597                         // profile.
00598                         NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar1, tblock.Far1FaceVector);
00599                 }
00600         }
00601 
00602         // Check the pass is in the set
00603 #ifdef NL_DEBUG
00604         if (Pass1.PatchRdrPass)
00605         {
00606                 nlassert (Zone->Landscape->_FarRdrPassSet.find (Pass1.PatchRdrPass)!=Zone->Landscape->_FarRdrPassSet.end());
00607                 if (Zone->Landscape->_FarRdrPassSet.find (Pass1.PatchRdrPass)==Zone->Landscape->_FarRdrPassSet.end())
00608                 {
00609                         bool bFound=false;
00610                         {
00611                                 for (sint t=0; t<(sint)Zone->Landscape->_FarRdrPassSetVectorFree.size(); t++)
00612                                 {
00613                                         if (Zone->Landscape->_FarRdrPassSetVectorFree[t].find (Pass1.PatchRdrPass)!=Zone->Landscape->_FarRdrPassSetVectorFree[t].end())
00614                                         {
00615                                                 bFound=true;
00616                                                 break;
00617                                         }
00618                                 }
00619                         }
00620                         nlassert (bFound);
00621                 }
00622         }
00623 #endif // NL_DEBUG
00624 }
00625 
00626 
00627 // ***************************************************************************
00628 void                    CTileMaterial::renderTile(uint pass)
00629 {
00630         // because precisely inserted in preRender(), and correctly tested, this tile is to be rendered,
00631         // If the pass is enabled.
00632         if(Pass[pass].PatchRdrPass)
00633         {
00634                 // render tris of the good faceList.
00635                 renderFaceVector(TileFaceVectors[pass]);
00636 
00637                 // profile.
00638                 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrTile[pass], TileFaceVectors[pass]);
00639         }
00640 }
00641 
00642 // ***************************************************************************
00643 void                    CTileMaterial::renderTilePassRGB0()
00644 {
00645         // because precisely inserted in preRender(), and correctly tested, this tile is to be rendered,
00646         // this pass must be enabled!
00647         nlassert(Pass[NL3D_TILE_PASS_RGB0].PatchRdrPass);
00648         // render tris of the good faceList.
00649         renderFaceVector(TileFaceVectors[NL3D_TILE_PASS_RGB0]);
00650 
00651         // profile.
00652         NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrTile[NL3D_TILE_PASS_RGB0], TileFaceVectors[NL3D_TILE_PASS_RGB0]);
00653 }
00654 
00655 // ***************************************************************************
00656 void                    CTileMaterial::renderTilePassLightmap()
00657 {
00658         // because precisely inserted in preRender(), and correctly tested, this tile is to be rendered,
00659         // this pass must be enabled!
00660         nlassert(Pass[NL3D_TILE_PASS_LIGHTMAP].PatchRdrPass);
00661         // render tris of the good faceList, ie the one of PassRGB0, because vertices are reused.
00662         renderFaceVector(TileFaceVectors[NL3D_TILE_PASS_RGB0]);
00663 
00664         // profile.
00665         NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrTile[NL3D_TILE_PASS_LIGHTMAP], TileFaceVectors[NL3D_TILE_PASS_RGB0]);
00666 }
00667 
00668 
00669 // ***************************************************************************
00670 // ***************************************************************************
00671 // FaceVector Allocation
00672 // ***************************************************************************
00673 // ***************************************************************************
00674 
00675 
00676 // ***************************************************************************
00677 void            CPatch::createFaceVectorFar1()
00678 {
00679         if(Far1>0)
00680         {
00681                 // Create the face for all TessBlocks.
00682                 MasterBlock.createFaceVectorFar1(getLandscape()->_FaceVectorManager);
00683                 for(uint i=0; i<TessBlocks.size(); i++)
00684                         TessBlocks[i].createFaceVectorFar1(getLandscape()->_FaceVectorManager);
00685         }
00686 }
00687 // ***************************************************************************
00688 void            CPatch::deleteFaceVectorFar1()
00689 {
00690         if(Far1>0)
00691         {
00692                 // delete the face for all TessBlocks.
00693                 MasterBlock.deleteFaceVectorFar1(getLandscape()->_FaceVectorManager);
00694                 for(uint i=0; i<TessBlocks.size(); i++)
00695                         TessBlocks[i].deleteFaceVectorFar1(getLandscape()->_FaceVectorManager);
00696         }
00697 }
00698 // ***************************************************************************
00699 void            CPatch::createFaceVectorFar0OrTile()
00700 {
00701         // If Far Mode.
00702         if(Far0>0)
00703         {
00704                 // Create the face for all TessBlocks.
00705                 MasterBlock.createFaceVectorFar0(getLandscape()->_FaceVectorManager);
00706                 for(uint i=0; i<TessBlocks.size(); i++)
00707                         TessBlocks[i].createFaceVectorFar0(getLandscape()->_FaceVectorManager);
00708         }
00709         // Or If Tile Mode.
00710         else if(Far0==0)
00711         {
00712                 // Create the face for all TessBlocks.
00713                 // No tiles in MasterBlock!
00714                 for(uint i=0; i<TessBlocks.size(); i++)
00715                         TessBlocks[i].createFaceVectorTile(getLandscape()->_FaceVectorManager);
00716         }
00717 }
00718 // ***************************************************************************
00719 void            CPatch::deleteFaceVectorFar0OrTile()
00720 {
00721         // If Far Mode.
00722         if(Far0>0)
00723         {
00724                 // delete the face for all TessBlocks.
00725                 MasterBlock.deleteFaceVectorFar0(getLandscape()->_FaceVectorManager);
00726                 for(uint i=0; i<TessBlocks.size(); i++)
00727                         TessBlocks[i].deleteFaceVectorFar0(getLandscape()->_FaceVectorManager);
00728         }
00729         // Or If Tile Mode.
00730         else if(Far0==0)
00731         {
00732                 // delete the face for all TessBlocks.
00733                 // No tiles in MasterBlock!
00734                 for(uint i=0; i<TessBlocks.size(); i++)
00735                         TessBlocks[i].deleteFaceVectorTile(getLandscape()->_FaceVectorManager);
00736         }
00737 }
00738 
00739 
00740 // ***************************************************************************
00741 void            CPatch::recreateTessBlockFaceVector(CTessBlock &block)
00742 {
00743         // Do it Only if patch is visible.
00744         if(!RenderClipped)
00745         {
00746                 // Far0.
00747                 // If Far Mode.
00748                 if(Far0>0)
00749                 {
00750                         // Create the face for this TessBlock only.
00751                         block.createFaceVectorFar0(getLandscape()->_FaceVectorManager);
00752                 }
00753                 // Or If Tile Mode.
00754                 else if(Far0==0)
00755                 {
00756                         // No tiles in MasterBlock! So no need to call createFaceVectorTile(), if this block is the MasterBlock.
00757                         if(&block != &MasterBlock)
00758                                 block.createFaceVectorTile(getLandscape()->_FaceVectorManager);
00759                 }
00760 
00761                 // Far1.
00762                 if(Far1>0)
00763                 {
00764                         // Create the face for this TessBlock only.
00765                         block.createFaceVectorFar1(getLandscape()->_FaceVectorManager);
00766                 }
00767         }
00768 
00769 }
00770 
00771 
00772 // ***************************************************************************
00773 // ***************************************************************************
00774 // VB Allocation
00775 // ***************************************************************************
00776 // ***************************************************************************
00777 
00778 
00779 // ***************************************************************************
00780 void            CPatch::updateFar0VBAlloc(CTessList<CTessFarVertex>  &vertList, bool alloc)
00781 {
00782         // Traverse the vertList.
00783         CTessFarVertex  *pVert;
00784         for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
00785         {
00786                 if(alloc)
00787                         pVert->Index0= CLandscapeGlobals::CurrentFar0VBAllocator->allocateVertex();
00788                 else
00789                         CLandscapeGlobals::CurrentFar0VBAllocator->deleteVertex(pVert->Index0);
00790         }
00791 }
00792 
00793 
00794 // ***************************************************************************
00795 void            CPatch::updateFar1VBAlloc(CTessList<CTessFarVertex>  &vertList, bool alloc)
00796 {
00797         // Traverse the vertList.
00798         CTessFarVertex  *pVert;
00799         for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
00800         {
00801                 if(alloc)
00802                         pVert->Index1= CLandscapeGlobals::CurrentFar1VBAllocator->allocateVertex();
00803                 else
00804                         CLandscapeGlobals::CurrentFar1VBAllocator->deleteVertex(pVert->Index1);
00805         }
00806 }
00807 
00808 
00809 // ***************************************************************************
00810 void            CPatch::updateTileVBAlloc(CTessList<CTessNearVertex>  &vertList, bool alloc)
00811 {
00812         // Traverse the vertList.
00813         CTessNearVertex *pVert;
00814         for(pVert= vertList.begin(); pVert; pVert= (CTessNearVertex*)pVert->Next)
00815         {
00816                 if(alloc)
00817                         pVert->Index= CLandscapeGlobals::CurrentTileVBAllocator->allocateVertex();
00818                 else
00819                         CLandscapeGlobals::CurrentTileVBAllocator->deleteVertex(pVert->Index);
00820         }
00821 }
00822 
00823 
00824 // ***************************************************************************
00825 void                    CPatch::updateVBAlloc(bool alloc)
00826 {
00827         // update Far0.
00828         //=======
00829         if(Far0>0)
00830         {
00831                 // alloc Far0 VB.
00832                 updateFar0VBAlloc(MasterBlock.FarVertexList, alloc);
00833                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
00834                 {
00835                         CTessBlock      &tblock= TessBlocks[i];
00836                         // need update VB only if tessBlock is visible.
00837                         if( tblock.visibleFar0() )
00838                                 updateFar0VBAlloc(tblock.FarVertexList, alloc);
00839                 }
00840         }
00841         else if (Far0==0)
00842         {
00843                 // alloc Tile VB.
00844                 // No Tiles in MasterBlock!!
00845                 // Traverse the TessBlocks to add vertices.
00846                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
00847                 {
00848                         CTessBlock      &tblock= TessBlocks[i];
00849                         // Add the vertices.
00850                         // need update VB only if tessBlock is visible.
00851                         if( tblock.visibleTile() )
00852                                 updateTileVBAlloc(tblock.NearVertexList, alloc);
00853                 }
00854         }
00855 
00856         // update Far1.
00857         //=======
00858         if(Far1>0)
00859         {
00860                 // alloc VB.
00861                 updateFar1VBAlloc(MasterBlock.FarVertexList, alloc);
00862                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
00863                 {
00864                         CTessBlock      &tblock= TessBlocks[i];
00865                         // need update VB only if tessBlock is visible.
00866                         if( tblock.visibleFar1() )
00867                                 updateFar1VBAlloc(tblock.FarVertexList, alloc);
00868                 }
00869         }
00870 }
00871 
00872 // ***************************************************************************
00873 void                    CPatch::deleteVBAndFaceVector()
00874 {
00875         updateVBAlloc(false);
00876         deleteFaceVectorFar1();
00877         deleteFaceVectorFar0OrTile();
00878 }
00879 
00880 // ***************************************************************************
00881 void                    CPatch::allocateVBAndFaceVector()
00882 {
00883         updateVBAlloc(true);
00884         createFaceVectorFar1();
00885         createFaceVectorFar0OrTile();
00886 }
00887 
00888 
00889 // ***************************************************************************
00890 void            CPatch::deleteVBAndFaceVectorFar1Only()
00891 {
00892         if(Far1>0)
00893         {
00894                 // alloc VB.
00895                 updateFar1VBAlloc(MasterBlock.FarVertexList, false);
00896                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
00897                 {
00898                         CTessBlock      &tblock= TessBlocks[i];
00899                         // need update VB only if tessBlock is visible.
00900                         if( tblock.visibleFar1() )
00901                                 updateFar1VBAlloc(tblock.FarVertexList, false);
00902                 }
00903         }
00904 
00905         deleteFaceVectorFar1();
00906 }
00907 
00908 // ***************************************************************************
00909 void            CPatch::allocateVBAndFaceVectorFar1Only()
00910 {
00911         if(Far1>0)
00912         {
00913                 // alloc VB.
00914                 updateFar1VBAlloc(MasterBlock.FarVertexList, true);
00915                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
00916                 {
00917                         CTessBlock      &tblock= TessBlocks[i];
00918                         // need update VB only if tessBlock is visible.
00919                         if( tblock.visibleFar1() )
00920                                 updateFar1VBAlloc(tblock.FarVertexList, true);
00921                 }
00922         }
00923 
00924         createFaceVectorFar1();
00925 }
00926 
00927 
00928 // ***************************************************************************
00929 void            CPatch::debugAllocationMarkIndicesFarList(CTessList<CTessFarVertex>  &vertList, uint marker)
00930 {
00931         // Traverse the vertList.
00932         CTessFarVertex  *pVert;
00933         for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
00934         {
00935                 pVert->Index0= marker;
00936                 pVert->Index1= marker;
00937         }
00938 }
00939 
00940 void            CPatch::debugAllocationMarkIndicesNearList(CTessList<CTessNearVertex>  &vertList, uint marker)
00941 {
00942         // Traverse the vertList.
00943         CTessNearVertex *pVert;
00944         for(pVert= vertList.begin(); pVert; pVert= (CTessNearVertex*)pVert->Next)
00945         {
00946                 pVert->Index= marker;
00947         }
00948 }
00949 
00950 void            CPatch::debugAllocationMarkIndices(uint marker)
00951 {
00952         sint i;
00953 
00954         // Do it For Far.
00955         debugAllocationMarkIndicesFarList(MasterBlock.FarVertexList, marker);
00956         for(i=0; i<(sint)TessBlocks.size(); i++)
00957         {
00958                 CTessBlock      &tblock= TessBlocks[i];
00959                 debugAllocationMarkIndicesFarList(tblock.FarVertexList, marker);
00960         }
00961         // Do it For Near.
00962         // No Tiles in MasterBlock!!
00963         for(i=0; i<(sint)TessBlocks.size(); i++)
00964         {
00965                 CTessBlock      &tblock= TessBlocks[i];
00966                 debugAllocationMarkIndicesNearList(tblock.NearVertexList, marker);
00967         }
00968 
00969 }
00970 
00971 
00972 
00973 // ***************************************************************************
00974 // ***************************************************************************
00975 // VB Filling.
00976 // ***************************************************************************
00977 // ***************************************************************************
00978 
00979 
00980 // ***************************************************************************
00981 // NB: need to be inlined only for fillFar0VB() in this file.
00982 inline void             CPatch::fillFar0VertexVB(CTessFarVertex *pVert)
00983 {
00984         // The Buffers must have been locked
00985         nlassert(CLandscapeGlobals::CurrentFar0VBAllocator);
00986         nlassert(CLandscapeGlobals::CurrentFar0VBAllocator->bufferLocked());
00987         // VBInfo must be OK.
00988         nlassert(!CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs());
00989 
00990         static  uint8   *CurVBPtr;
00991         // Compute/build the new vertex.
00992         CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar0VBInfo.VertexCoordPointer;
00993         CurVBPtr+= pVert->Index0 * CLandscapeGlobals::CurrentFar0VBInfo.VertexSize;
00994 
00995         // NB: the filling order of data is important, for AGP write combiners.
00996 
00997         // compute Uvs.
00998         static CUV      uv;
00999         CParamCoord     pc= pVert->PCoord;
01000         if (Flags&NL_PATCH_FAR0_ROTATED)
01001         {
01002                 uv.U= pc.getT()* Far0UScale + Far0UBias;
01003                 uv.V= (1.f-pc.getS())* Far0VScale + Far0VBias;
01004         }
01005         else
01006         {
01007                 uv.U= pc.getS()* Far0UScale + Far0UBias;
01008                 uv.V= pc.getT()* Far0VScale + Far0VBias;
01009         }
01010 
01011         // compute Dynamic lightmap Uv.
01012         static CUV      uvDLM;
01013         if(_DLMContext)         //  (NB: Suppose BTB kill this test).
01014         {
01015                 // compute UV with DLM context info.
01016                 uvDLM.U= pc.getS()* _DLMContext->DLMUScale + _DLMContext->DLMUBias;
01017                 uvDLM.V= pc.getT()* _DLMContext->DLMVScale + _DLMContext->DLMVBias;
01018         }
01019         else
01020         {
01021                 // just set UV so the vertex point to a black pixel (see CTextureDLM).
01022                 uvDLM.U= 1;
01023                 uvDLM.V= 1;
01024         }
01025 
01026         // If not VertexProgram (NB: Suppose BTB kill this test).
01027         if( !CLandscapeGlobals::VertexProgramEnabled )
01028         {
01029                 // Set Pos. Set it local to the current center of landscape
01030                 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
01031                 // Set Uvs.
01032                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff0)= uv;
01033                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1)= uvDLM;
01034         }
01035         else
01036         {
01037                 // Else must setup Vertex program inputs
01038                 // v[0]== StartPos.
01039                 *(CVector*)CurVBPtr= pVert->Src->StartPos;
01040                 // v[8]== Tex0
01041                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff0)= uv;
01042                 // v[9]== Tex1
01043                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1)= uvDLM;
01044 
01045                 // v[10]== GeomInfo.
01046                 static CUV      geomInfo;
01047                 geomInfo.U= pVert->Src->MaxFaceSize * CLandscapeGlobals::OORefineThreshold;
01048                 geomInfo.V= pVert->Src->MaxNearLimit;
01049                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.GeomInfoOff)= geomInfo;
01050 
01051                 // v[11]== EndPos - StartPos
01052                 *(CVector*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.DeltaPosOff)=
01053                         pVert->Src->EndPos - pVert->Src->StartPos;
01054         }
01055 }
01056 // ***************************************************************************
01057 // NB: need to be inlined only for fillFar1VB() in this file.
01058 inline void             CPatch::fillFar1VertexVB(CTessFarVertex *pVert)
01059 {
01060         // The Buffers must have been locked
01061         nlassert(CLandscapeGlobals::CurrentFar1VBAllocator);
01062         nlassert(CLandscapeGlobals::CurrentFar1VBAllocator->bufferLocked());
01063         // VBInfo must be OK.
01064         nlassert(!CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs());
01065 
01066         static  uint8   *CurVBPtr;
01067         // Compute/build the new vertex.
01068         CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar1VBInfo.VertexCoordPointer;
01069         CurVBPtr+= pVert->Index1 * CLandscapeGlobals::CurrentFar1VBInfo.VertexSize;
01070 
01071         // NB: the filling order of data is important, for AGP write combiners.
01072 
01073         // compute Uvs.
01074         static CUV      uv;
01075         CParamCoord     pc= pVert->PCoord;
01076         if (Flags&NL_PATCH_FAR1_ROTATED)
01077         {
01078                 uv.U= pc.getT()* Far1UScale + Far1UBias;
01079                 uv.V= (1.f-pc.getS())* Far1VScale + Far1VBias;
01080         }
01081         else
01082         {
01083                 uv.U= pc.getS()* Far1UScale + Far1UBias;
01084                 uv.V= pc.getT()* Far1VScale + Far1VBias;
01085         }
01086 
01087         // compute Dynamic lightmap Uv.
01088         static CUV      uvDLM;
01089         if(_DLMContext)         //  (NB: Suppose BTB kill this test).
01090         {
01091                 // compute UV with DLM context info.
01092                 uvDLM.U= pc.getS()* _DLMContext->DLMUScale + _DLMContext->DLMUBias;
01093                 uvDLM.V= pc.getT()* _DLMContext->DLMVScale + _DLMContext->DLMVBias;
01094         }
01095         else
01096         {
01097                 // just set UV so the vertex point to a black pixel (see CTextureDLM).
01098                 uvDLM.U= 1;
01099                 uvDLM.V= 1;
01100         }
01101 
01102         // If not VertexProgram (NB: Suppose BTB kill this test).
01103         if( !CLandscapeGlobals::VertexProgramEnabled )
01104         {
01105                 // Set Pos. Set it local to the current center of landscape
01106                 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
01107                 // Set Uvs.
01108                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff0)= uv;
01109                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1)= uvDLM;
01110                 // Set default color.
01111                 static CRGBA    col(255,255,255,255);
01112                 *(CRGBA*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.ColorOff)= col;
01113         }
01114         else
01115         {
01116                 // Else must setup Vertex program inputs
01117                 // v[0]== StartPos.
01118                 *(CVector*)CurVBPtr= pVert->Src->StartPos;
01119                 // v[8]== Tex0
01120                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff0)= uv;
01121                 // v[9]== Tex1
01122                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1)= uvDLM;
01123 
01124                 // v[10]== GeomInfo.
01125                 static CUV      geomInfo;
01126                 geomInfo.U= pVert->Src->MaxFaceSize * CLandscapeGlobals::OORefineThreshold;
01127                 geomInfo.V= pVert->Src->MaxNearLimit;
01128                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.GeomInfoOff)= geomInfo;
01129 
01130                 // v[11]== EndPos - StartPos
01131                 *(CVector*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.DeltaPosOff)=
01132                         pVert->Src->EndPos - pVert->Src->StartPos;
01133 
01134                 // v[12]== Alpha information
01135                 // Hopefully, fillVBFar1Only() is called each Time the Far1 change, in preRender().
01136                 // So TransitionSqrMin and OOTransitionSqrDelta in CPath are valid.
01137                 geomInfo.U= TransitionSqrMin;
01138                 geomInfo.V= OOTransitionSqrDelta;
01139                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.AlphaInfoOff)= geomInfo;
01140 
01141         }
01142 }
01143 // ***************************************************************************
01144 // NB: need to be inlined only for fillTileVB() in this file.
01145 inline void             CPatch::fillTileVertexVB(CTessNearVertex *pVert)
01146 {
01147         // The Buffers must have been locked
01148         nlassert(CLandscapeGlobals::CurrentTileVBAllocator);
01149         nlassert(CLandscapeGlobals::CurrentTileVBAllocator->bufferLocked());
01150         // VBInfo must be OK.
01151         nlassert(!CLandscapeGlobals::CurrentTileVBAllocator->reallocationOccurs());
01152 
01153         static  uint8   *CurVBPtr;
01154         // Compute/build the new vertex.
01155         CurVBPtr= (uint8*)CLandscapeGlobals::CurrentTileVBInfo.VertexCoordPointer;
01156         CurVBPtr+= pVert->Index * CLandscapeGlobals::CurrentTileVBInfo.VertexSize;
01157 
01158 
01159         // NB: the filling order of data is important, for AGP write combiners.
01160 
01161         // If not VertexProgram (NB: Suppose BTB kill this test).
01162         if( !CLandscapeGlobals::VertexProgramEnabled )
01163         {
01164                 // Set Pos. Set it local to the current center of landscape
01165                 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
01166                 // Set Uvs.
01167                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff0)= pVert->PUv0;
01168                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff1)= pVert->PUv1;
01169                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff2)= pVert->PUv2;
01170         }
01171         else
01172         {
01173                 // Else must setup Vertex program inputs
01174                 // v[0]== StartPos.
01175                 *(CVector*)CurVBPtr= pVert->Src->StartPos;
01176                 // v[8]== Tex0
01177                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff0)= pVert->PUv0;
01178                 // v[9]== Tex1
01179                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff1)= pVert->PUv1;
01180                 // v[13]== Tex2
01181                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff2)= pVert->PUv2;
01182 
01183                 // v[10]== GeomInfo.
01184                 static CUV      geomInfo;
01185                 geomInfo.U= pVert->Src->MaxFaceSize * CLandscapeGlobals::OORefineThreshold;
01186                 geomInfo.V= pVert->Src->MaxNearLimit;
01187                 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.GeomInfoOff)= geomInfo;
01188 
01189                 // v[11]== EndPos - StartPos
01190                 *(CVector*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.DeltaPosOff)=
01191                         pVert->Src->EndPos - pVert->Src->StartPos;
01192         }
01193 }
01194 
01195 
01196 // ***************************************************************************
01197 void            CPatch::fillFar0VertexListVB(CTessList<CTessFarVertex>  &vertList)
01198 {
01199         // Traverse the vertList.
01200         CTessFarVertex  *pVert;
01201         for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01202         {
01203                 fillFar0VertexVB(pVert);
01204         }
01205 }
01206 
01207 
01208 // ***************************************************************************
01209 void            CPatch::fillFar1VertexListVB(CTessList<CTessFarVertex>  &vertList)
01210 {
01211         // Traverse the vertList.
01212         CTessFarVertex  *pVert;
01213         for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01214         {
01215                 fillFar1VertexVB(pVert);
01216         }
01217 }
01218 
01219 
01220 // ***************************************************************************
01221 void            CPatch::fillTileVertexListVB(CTessList<CTessNearVertex>  &vertList)
01222 {
01223         // Traverse the vertList.
01224         CTessNearVertex *pVert;
01225         for(pVert= vertList.begin(); pVert; pVert= (CTessNearVertex*)pVert->Next)
01226         {
01227                 fillTileVertexVB(pVert);
01228         }
01229 }
01230 
01231 
01232 
01233 // ***************************************************************************
01234 void                    CPatch::fillVB()
01235 {
01236         // Fill Far0.
01237         //=======
01238         // fill only if no reallcoation occurs
01239         if(Far0>0 && !CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs() )
01240         {
01241                 // Fill Far0 VB.
01242                 fillFar0VertexListVB(MasterBlock.FarVertexList);
01243                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01244                 {
01245                         CTessBlock      &tblock= TessBlocks[i];
01246                         // fill only if tblock visible.
01247                         if( tblock.visibleFar0() )
01248                                 fillFar0VertexListVB(tblock.FarVertexList);
01249                 }
01250         }
01251         else if(Far0==0 && !CLandscapeGlobals::CurrentTileVBAllocator->reallocationOccurs() )
01252         {
01253                 // Fill Tile VB.
01254                 // No Tiles in MasterBlock!!
01255                 // Traverse the TessBlocks to add vertices.
01256                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01257                 {
01258                         CTessBlock      &tblock= TessBlocks[i];
01259                         // fill only if tblock visible.
01260                         if( tblock.visibleTile() )
01261                                 fillTileVertexListVB(tblock.NearVertexList);
01262                 }
01263         }
01264 
01265         // Fill Far1.
01266         //=======
01267         if(Far1>0 && !CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs() )
01268         {
01269                 // Fill VB.
01270                 fillFar1VertexListVB(MasterBlock.FarVertexList);
01271                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01272                 {
01273                         CTessBlock      &tblock= TessBlocks[i];
01274                         // fill only if tblock visible.
01275                         if( tblock.visibleFar1() )
01276                                 fillFar1VertexListVB(tblock.FarVertexList);
01277                 }
01278         }
01279 
01280 }
01281 
01282 
01283 // ***************************************************************************
01284 void            CPatch::fillVBIfVisible()
01285 {
01286         if(RenderClipped==false)
01287                 fillVB();
01288 }
01289 
01290 
01291 // ***************************************************************************
01292 void            CPatch::fillVBFar0Only()
01293 {
01294         if(Far0>0 && !CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs() )
01295         {
01296                 // Fill Far0 VB.
01297                 fillFar0VertexListVB(MasterBlock.FarVertexList);
01298                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01299                 {
01300                         CTessBlock      &tblock= TessBlocks[i];
01301                         // fill only if tblock visible.
01302                         if( tblock.visibleFar0() )
01303                                 fillFar0VertexListVB(tblock.FarVertexList);
01304                 }
01305         }
01306 }
01307 
01308 
01309 // ***************************************************************************
01310 void            CPatch::fillVBFar1Only()
01311 {
01312         if(Far1>0 && !CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs() )
01313         {
01314                 // Fill VB.
01315                 fillFar1VertexListVB(MasterBlock.FarVertexList);
01316                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01317                 {
01318                         CTessBlock      &tblock= TessBlocks[i];
01319                         // fill only if tblock visible.
01320                         if( tblock.visibleFar1() )
01321                                 fillFar1VertexListVB(tblock.FarVertexList);
01322                 }
01323         }
01324 }
01325 
01326 // ***************************************************************************
01327 // ***************************************************************************
01328 // VB Software Geomorph / Alpha.
01329 // ***************************************************************************
01330 // ***************************************************************************
01331 
01332 
01333 // ***************************************************************************
01334 void            CPatch::computeGeomorphVertexList(CTessList<CTessFarVertex>  &vertList)
01335 {
01336         // Traverse the vertList.
01337         CTessFarVertex  *pVert;
01338         for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01339         {
01340                 // compute geomorph.
01341                 pVert->Src->computeGeomPos();
01342         }
01343 }
01344 
01345 
01346 // ***************************************************************************
01347 void            CPatch::computeGeomorphFar0VertexListVB(CTessList<CTessFarVertex>  &vertList)
01348 {
01349         // Traverse the vertList.
01350         CTessFarVertex  *pVert;
01351         for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01352         {
01353                 static  uint8   *CurVBPtr;
01354                 // Compute/build the new vertex.
01355                 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar0VBInfo.VertexCoordPointer;
01356                 CurVBPtr+= pVert->Index0 * CLandscapeGlobals::CurrentFar0VBInfo.VertexSize;
01357 
01358                 // Set Geomorphed Position. Set it local to the current center of landscape
01359                 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
01360         }
01361 }
01362 
01363 
01364 // ***************************************************************************
01365 void            CPatch::computeGeomorphAlphaFar1VertexListVB(CTessList<CTessFarVertex>  &vertList)
01366 {
01367         // Traverse the vertList.
01368         CTessFarVertex  *pVert;
01369         for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01370         {
01371                 static  uint8   *CurVBPtr;
01372                 // Compute/build the new vertex.
01373                 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar1VBInfo.VertexCoordPointer;
01374                 CurVBPtr+= pVert->Index1 * CLandscapeGlobals::CurrentFar1VBInfo.VertexSize;
01375 
01376                 // NB: the filling order of data is important, for AGP write combiners.
01377 
01378                 // Set Geomorphed Position. Set it local to the current center of landscape
01379                 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
01380 
01381                 // Set Alpha color.
01382                 static CRGBA    col(255,255,255,255);
01383                 // For Far1, use alpha fro transition.
01384                 // Prefer Use Pos, because of caching. So little difference between Soft and VertexProgram mode.
01385                 float   f= (pVert->Src->Pos - CLandscapeGlobals::RefineCenter).sqrnorm();
01386                 f= (f-TransitionSqrMin) * OOTransitionSqrDelta;
01387                 clamp(f,0,1);
01388                 col.A= (uint8)(f*255);
01389                 *(CRGBA*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.ColorOff)= col;
01390         }
01391 }
01392 
01393 
01394 // ***************************************************************************
01395 void            CPatch::computeGeomorphTileVertexListVB(CTessList<CTessNearVertex>  &vertList)
01396 {
01397         // Traverse the vertList.
01398         CTessNearVertex *pVert;
01399         for(pVert= vertList.begin(); pVert; pVert= (CTessNearVertex*)pVert->Next)
01400         {
01401                 static  uint8   *CurVBPtr;
01402                 // Compute/build the new vertex.
01403                 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentTileVBInfo.VertexCoordPointer;
01404                 CurVBPtr+= pVert->Index * CLandscapeGlobals::CurrentTileVBInfo.VertexSize;
01405 
01406                 // Set Geomorphed Position. Set it local to the current center of landscape
01407                 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
01408         }
01409 }
01410 
01411 
01412 
01413 // ***************************************************************************
01414 void            CPatch::computeSoftwareGeomorphAndAlpha()
01415 {
01416         if(RenderClipped)
01417                 return;
01418 
01419         // Compute Geomorph.
01420         //=======
01421         // Need only to fill CTessVertex, so do it only for FarVertices
01422         // Hence Geomorph is done twice on edges of patches!!.
01423         // If not too near for precise, fast compute of geomorph.
01424         if( TessBlocks.size()==0 )
01425         {
01426                 // Just update all vertices of master block.
01427                 computeGeomorphVertexList(MasterBlock.FarVertexList);
01428         }
01429         else
01430         {
01431                 // update all vertices of master block.
01432                 computeGeomorphVertexList(MasterBlock.FarVertexList);
01433                 // update vertices of others block.
01434                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01435                 {
01436                         CTessBlock      &tblock= TessBlocks[i];
01437                         // Precise Clip.
01438                         if(!tblock.getClipped())
01439                         {
01440                                 // compute the geomorph of the vertices in the tessblock.
01441                                 computeGeomorphVertexList(tblock.FarVertexList);
01442                         }
01443                 }
01444         }
01445 
01446 
01447         // Fill Far0.
01448         //=======
01449         if(Far0>0)
01450         {
01451                 // Fill Far0 VB.
01452                 computeGeomorphFar0VertexListVB(MasterBlock.FarVertexList);
01453                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01454                 {
01455                         CTessBlock      &tblock= TessBlocks[i];
01456                         // Precise Clip.
01457                         if( tblock.visibleFar0() )
01458                                 computeGeomorphFar0VertexListVB(tblock.FarVertexList);
01459                 }
01460         }
01461         else if(Far0==0)
01462         {
01463                 // Fill Tile VB.
01464                 // No Tiles in MasterBlock!!
01465                 // Traverse the TessBlocks to compute vertices.
01466                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01467                 {
01468                         CTessBlock      &tblock= TessBlocks[i];
01469                         // Precise Clip.
01470                         if( tblock.visibleTile() )
01471                                 computeGeomorphTileVertexListVB(tblock.NearVertexList);
01472                 }
01473         }
01474 
01475         // Fill Far1.
01476         //=======
01477         if(Far1>0)
01478         {
01479                 // Fill VB.
01480                 computeGeomorphAlphaFar1VertexListVB(MasterBlock.FarVertexList);
01481                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01482                 {
01483                         CTessBlock      &tblock= TessBlocks[i];
01484                         // Precise Clip.
01485                         if( tblock.visibleFar1() )
01486                                 computeGeomorphAlphaFar1VertexListVB(tblock.FarVertexList);
01487                 }
01488         }
01489 }
01490 
01491 
01492 // ***************************************************************************
01493 // ***************************************************************************
01494 // VB clip Allocate/Filling.
01495 // ***************************************************************************
01496 // ***************************************************************************
01497                 
01498 
01499 // ***************************************************************************
01500 void            CPatch::updateClipPatchVB()
01501 {
01502         // If there is a change in the clip state of this patch.
01503         if( OldRenderClipped != RenderClipped )
01504         {
01505                 // bkup this state for next time.
01506                 OldRenderClipped = RenderClipped;
01507 
01508                 // If now the patch is invisible
01509                 if(RenderClipped)
01510                 {
01511                         // Then delete vertices.
01512                         deleteVBAndFaceVector();
01513 
01514                         // Now, all vertices in VB are deleted.
01515                         // Force clip state of all TessBlocks, so no allocation will be done on Vertices in VB.
01516                         if(!TessBlocks.empty())
01517                         {
01518                                 for(uint i=0; i<TessBlocks.size();i++)
01519                                 {
01520                                         CTessBlock      &tblock= TessBlocks[i];
01521                                         tblock.forceClip();
01522                                 }
01523                         }
01524                 }
01525                 else
01526                 {
01527                         // else allocate / fill them.
01528                         allocateVBAndFaceVector();
01529                         // NB: fillVB() test if any reallocation occurs.
01530                         fillVB();
01531                 }
01532         }
01533 }
01534 
01535 
01536 // ***************************************************************************
01537 // ***************************************************************************
01538 // VB refine Allocate/Filling.
01539 // ***************************************************************************
01540 // ***************************************************************************
01541 
01542 
01543 
01544 // ***************************************************************************
01545 void            CPatch::checkCreateVertexVBFar(CTessFarVertex *pVert)
01546 {
01547         nlassert(pVert);
01548         // If visible, and Far0 in !Tile Mode, allocate.
01549         // NB: must test Far0>0 because vertices are reallocated in preRender() if a change of Far occurs.
01550         if(!RenderClipped && Far0>0 && pVert->OwnerBlock->visibleFar0() )
01551         {
01552                 pVert->Index0= CLandscapeGlobals::CurrentFar0VBAllocator->allocateVertex();
01553         }
01554 
01555         // Idem for Far1
01556         if(!RenderClipped && Far1>0 && pVert->OwnerBlock->visibleFar1())
01557         {
01558                 pVert->Index1= CLandscapeGlobals::CurrentFar1VBAllocator->allocateVertex();
01559         }
01560 
01561 }
01562 
01563 
01564 // ***************************************************************************
01565 void            CPatch::checkFillVertexVBFar(CTessFarVertex *pVert)
01566 {
01567         nlassert(pVert);
01568         // If visible, and Far0 in !Tile Mode, try to fill.
01569         // NB: must test Far0>0 because vertices are reallocated in preRender() if a change of Far occurs.
01570         if(!RenderClipped && Far0>0 && pVert->OwnerBlock->visibleFar0())
01571         {
01572                 if( !CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs() )
01573                         fillFar0VertexVB(pVert);
01574         }
01575 
01576         // Idem for Far1
01577         if(!RenderClipped && Far1>0 && pVert->OwnerBlock->visibleFar1())
01578         {
01579                 if( !CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs() )
01580                         fillFar1VertexVB(pVert);
01581         }
01582 }
01583 
01584 
01585 // ***************************************************************************
01586 void            CPatch::checkCreateVertexVBNear(CTessNearVertex *pVert)
01587 {
01588         nlassert(pVert);
01589         // If visible, and Far0 in Tile Mode, allocate.
01590         // NB: must test Far0==0 because vertices are reallocated in preRender() if a change of Far occurs.
01591         if(!RenderClipped && Far0==0 && pVert->OwnerBlock->visibleTile())
01592         {
01593                 pVert->Index= CLandscapeGlobals::CurrentTileVBAllocator->allocateVertex();
01594         }
01595 }
01596 
01597 
01598 // ***************************************************************************
01599 void            CPatch::checkFillVertexVBNear(CTessNearVertex   *pVert)
01600 {
01601         nlassert(pVert);
01602         // If visible, and Far0 in Tile Mode, try to fill.
01603         // NB: must test Far0==0 because vertices are reallocated in preRender() if a change of Far occurs.
01604         if(!RenderClipped&& Far0==0 && pVert->OwnerBlock->visibleTile() )
01605         {
01606                 // try to fill.
01607                 if( !CLandscapeGlobals::CurrentTileVBAllocator->reallocationOccurs() )
01608                         fillTileVertexVB(pVert);
01609         }
01610 }
01611 
01612 
01613 // ***************************************************************************
01614 void            CPatch::checkDeleteVertexVBFar(CTessFarVertex *pVert)
01615 {
01616         nlassert(pVert);
01617         // If visible, and Far0 in !Tile Mode, ok, the vertex exist in VB, so delete.
01618         // NB: must test Far0>0 because vertices are deleted in preRender() if a change of Far occurs.
01619         if(!RenderClipped && Far0>0 && pVert->OwnerBlock->visibleFar0() )
01620         {
01621                 CLandscapeGlobals::CurrentFar0VBAllocator->deleteVertex(pVert->Index0);
01622         }
01623 
01624         // Idem for Far1
01625         if(!RenderClipped && Far1>0  && pVert->OwnerBlock->visibleFar1() )
01626         {
01627                 CLandscapeGlobals::CurrentFar1VBAllocator->deleteVertex(pVert->Index1);
01628         }
01629 }
01630 
01631 // ***************************************************************************
01632 void            CPatch::checkDeleteVertexVBNear(CTessNearVertex *pVert)
01633 {
01634         nlassert(pVert);
01635         // If visible, and Far0 in Tile Mode, ok, the vertex exist in VB, so delete.
01636         // NB: must test Far0==0 because vertices are deleted in preRender() if a change of Far occurs.
01637         if(!RenderClipped && Far0==0 && pVert->OwnerBlock->visibleTile() )
01638         {
01639                 CLandscapeGlobals::CurrentTileVBAllocator->deleteVertex(pVert->Index);
01640         }
01641 }
01642 
01643 
01644 // ***************************************************************************
01645 // ***************************************************************************
01646 // VB DLM Filling
01647 // ***************************************************************************
01648 // ***************************************************************************
01649 
01650 
01651 // ***************************************************************************
01652 void            CPatch::fillFar0DLMUvOnlyVertexListVB(CTessList<CTessFarVertex>  &vertList)
01653 {
01654         // The Buffers must have been locked
01655         nlassert(CLandscapeGlobals::CurrentFar0VBAllocator);
01656         nlassert(CLandscapeGlobals::CurrentFar0VBAllocator->bufferLocked());
01657         // VBInfo must be OK.
01658         nlassert(!CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs());
01659 
01660         static  uint8   *CurVBPtr;
01661         static CUV              uvDLM;
01662 
01663         // If the DLMContext exist
01664         if(_DLMContext)
01665         {
01666                 // Traverse the vertList, to compute new uvDLM
01667                 CTessFarVertex  *pVert;
01668                 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01669                 {
01670                         // Compute/build the new vertex.
01671                         CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar0VBInfo.VertexCoordPointer;
01672                         CurVBPtr+= pVert->Index0 * CLandscapeGlobals::CurrentFar0VBInfo.VertexSize;
01673 
01674                         // compute Uvs.
01675                         CParamCoord     pc= pVert->PCoord;
01676 
01677                         // compute Dynamic lightmap Uv with DLM context info.
01678                         uvDLM.U= pc.getS()* _DLMContext->DLMUScale + _DLMContext->DLMUBias;
01679                         uvDLM.V= pc.getT()* _DLMContext->DLMVScale + _DLMContext->DLMVBias;
01680 
01681                         // Set Uv DLM only (NB: same code for VertexProgram or not, only TexCoordOff1 may change).
01682                         *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1)= uvDLM;
01683                 }
01684         }
01685         // else, reset all Uvs
01686         else
01687         {
01688                 // just set UV so the vertex point to a black pixel (see CTextureDLM).
01689                 uvDLM.U= 1;
01690                 uvDLM.V= 1;
01691 
01692                 // Traverse the vertList, to reset uv
01693                 CTessFarVertex  *pVert;
01694                 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01695                 {
01696                         // Compute/build the new vertex.
01697                         CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar0VBInfo.VertexCoordPointer;
01698                         CurVBPtr+= pVert->Index0 * CLandscapeGlobals::CurrentFar0VBInfo.VertexSize;
01699 
01700                         // Set Uv DLM only (NB: same code for VertexProgram or not, only TexCoordOff1 may change).
01701                         *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1)= uvDLM;
01702                 }
01703         }
01704 }
01705 
01706 // ***************************************************************************
01707 void            CPatch::fillFar1DLMUvOnlyVertexListVB(CTessList<CTessFarVertex>  &vertList)
01708 {
01709         // The Buffers must have been locked
01710         nlassert(CLandscapeGlobals::CurrentFar1VBAllocator);
01711         nlassert(CLandscapeGlobals::CurrentFar1VBAllocator->bufferLocked());
01712         // VBInfo must be OK.
01713         nlassert(!CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs());
01714 
01715         static  uint8   *CurVBPtr;
01716         static CUV              uvDLM;
01717 
01718         // If the DLMContext exist
01719         if(_DLMContext)
01720         {
01721                 // Traverse the vertList, to compute new uvDLM
01722                 CTessFarVertex  *pVert;
01723                 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01724                 {
01725                         // Compute/build the new vertex.
01726                         CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar1VBInfo.VertexCoordPointer;
01727                         CurVBPtr+= pVert->Index1 * CLandscapeGlobals::CurrentFar1VBInfo.VertexSize;
01728 
01729                         // compute Uvs.
01730                         CParamCoord     pc= pVert->PCoord;
01731 
01732                         // compute Dynamic lightmap Uv with DLM context info.
01733                         uvDLM.U= pc.getS()* _DLMContext->DLMUScale + _DLMContext->DLMUBias;
01734                         uvDLM.V= pc.getT()* _DLMContext->DLMVScale + _DLMContext->DLMVBias;
01735 
01736                         // Set Uv DLM only (NB: same code for VertexProgram or not, only TexCoordOff1 may change).
01737                         *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1)= uvDLM;
01738                 }
01739         }
01740         // else, reset all Uvs
01741         else
01742         {
01743                 // just set UV so the vertex point to a black pixel (see CTextureDLM).
01744                 uvDLM.U= 1;
01745                 uvDLM.V= 1;
01746 
01747                 // Traverse the vertList, to reset uv
01748                 CTessFarVertex  *pVert;
01749                 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
01750                 {
01751                         // Compute/build the new vertex.
01752                         CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar1VBInfo.VertexCoordPointer;
01753                         CurVBPtr+= pVert->Index1 * CLandscapeGlobals::CurrentFar1VBInfo.VertexSize;
01754 
01755                         // Set Uv DLM only (NB: same code for VertexProgram or not, only TexCoordOff1 may change).
01756                         *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1)= uvDLM;
01757                 }
01758         }
01759 }
01760 
01761 
01762 // ***************************************************************************
01763 void            CPatch::fillVBFarsDLMUvOnly()
01764 {
01765         // Do it for Far0.
01766         if(Far0>0 && !CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs() )
01767         {
01768                 // Fill Far0 VB.
01769                 fillFar0DLMUvOnlyVertexListVB(MasterBlock.FarVertexList);
01770                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01771                 {
01772                         CTessBlock      &tblock= TessBlocks[i];
01773                         // fill only if tblock visible.
01774                         if( tblock.visibleFar0() )
01775                                 fillFar0DLMUvOnlyVertexListVB(tblock.FarVertexList);
01776                 }
01777         }
01778 
01779         // Do it for Far1.
01780         if(Far1>0 && !CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs() )
01781         {
01782                 // Fill VB.
01783                 fillFar1DLMUvOnlyVertexListVB(MasterBlock.FarVertexList);
01784                 for(sint i=0; i<(sint)TessBlocks.size(); i++)
01785                 {
01786                         CTessBlock      &tblock= TessBlocks[i];
01787                         // fill only if tblock visible.
01788                         if( tblock.visibleFar1() )
01789                                 fillFar1DLMUvOnlyVertexListVB(tblock.FarVertexList);
01790                 }
01791         }
01792 }
01793 
01794 
01795 
01796 } // NL3D