Change Encyclo button name and macros icon
[ryzomcore.git] / nel / src / 3d / patch_render.cpp
blobde5d0b4ec2b2e235768c42432dbc27279db9b2d9
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
20 #include "nel/3d/patch.h"
21 #include "nel/3d/tessellation.h"
22 #include "nel/3d/bezier_patch.h"
23 #include "nel/3d/zone.h"
24 #include "nel/3d/landscape.h"
25 #include "nel/3d/landscape_profile.h"
26 #include "nel/3d/patchdlm_context.h"
27 #include "nel/3d/debug_vb.h"
29 #include "nel/misc/vector.h"
30 #include "nel/misc/common.h"
32 using namespace std;
33 using namespace NLMISC;
35 #ifdef DEBUG_NEW
36 #define new DEBUG_NEW
37 #endif
39 namespace NL3D
43 // ***************************************************************************
44 // ***************************************************************************
45 // Patch Texture computation.
46 // ***************************************************************************
47 // ***************************************************************************
50 // ***************************************************************************
51 void CPatch::computeNewFar(const NLMISC::CBSphere &patchSphere, sint &newFar0, sint &newFar1)
53 // Classify the patch.
54 //========================
55 float r= (CLandscapeGlobals::RefineCenter-patchSphere.Center).norm() - patchSphere.Radius;
56 float rr=0.0;
57 if(r<CLandscapeGlobals::TileDistNear)
58 rr= r-CLandscapeGlobals::TileDistNear, newFar0= 0;
59 else if(r<CLandscapeGlobals::Far0Dist)
60 rr= r-CLandscapeGlobals::Far0Dist, newFar0= 1;
61 else if(r<CLandscapeGlobals::Far1Dist)
62 rr= r-CLandscapeGlobals::Far1Dist, newFar0= 2;
63 else
64 newFar0= 3;
65 // Transition with the next level.
66 newFar1=0;
67 if(newFar0<3 && rr>-(CLandscapeGlobals::FarTransition+2*patchSphere.Radius))
69 newFar1= newFar0+1;
73 // Update Texture Info.
74 //========================
75 if(newFar0!=Far0 || newFar1!=Far1)
77 // Backup old pass0
78 CPatchRdrPass *oldPass0=_PatchRdrPassFar0;
79 CPatchRdrPass *oldPass1=_PatchRdrPassFar1;
81 // Checks
82 if (oldPass0==NULL)
83 nlassert (Far0<=0);
84 if (oldPass1==NULL)
85 nlassert (Far1<=0);
87 float oldFar0UScale=Far0UScale;
88 float oldFar0VScale=Far0VScale;
89 float oldFar0UBias=Far0UBias;
90 float oldFar0VBias=Far0VBias;
91 uint8 oldFlags=Flags;
94 // Don't delete the pass0 if the new newFar1 will use it
95 if ((newFar1==Far0)&&(Far0>0))
96 _PatchRdrPassFar0=NULL;
98 // Don't delete the pass1 if the new newFar0 will use it
99 if ((newFar0==Far1)&&(Far1>0))
100 _PatchRdrPassFar1=NULL;
102 // Pass0 have changed ?
103 if (newFar0!=Far0)
105 // Compute / get the texture Far.
106 if(newFar0>0)
108 // Free the old pass, don't used any more
109 if (_PatchRdrPassFar0)
110 Zone->Landscape->freeFarRenderPass (this, _PatchRdrPassFar0, Far0);
112 // Can we use the old pass1 ?
113 if (newFar0==Far1)
115 // Yes, recycle it!
116 _PatchRdrPassFar0=oldPass1;
118 // Copy uv coordinates
119 Far0UScale=Far1UScale;
120 Far0VScale=Far1VScale;
121 Far0UBias=Far1UBias;
122 Far0VBias=Far1VBias;
124 // Copy rotation flag
125 Flags&=~NL_PATCH_FAR0_ROTATED; // erase it
126 if (Flags&NL_PATCH_FAR1_ROTATED)
127 Flags|=NL_PATCH_FAR0_ROTATED; // copy it
129 else // get a new render pass
131 // Rotation boolean
132 bool bRot;
133 _PatchRdrPassFar0=Zone->Landscape->getFarRenderPass(this, newFar0, Far0UScale, Far0VScale, Far0UBias, Far0VBias, bRot);
135 // Flags is set if the far texture is rotated of 90deg to the left
136 if (bRot)
137 Flags|=NL_PATCH_FAR0_ROTATED;
138 else
139 Flags&=~NL_PATCH_FAR0_ROTATED;
142 else // no more far pass0
144 if (_PatchRdrPassFar0)
146 Zone->Landscape->freeFarRenderPass (this, _PatchRdrPassFar0, Far0);
147 _PatchRdrPassFar0=NULL;
152 // Pass1 have changed ?
153 if (newFar1!=Far1)
155 // Now let's go with pass1
156 if(newFar1>0)
158 // Delete the pass1 if not used any more
159 if (_PatchRdrPassFar1)
160 Zone->Landscape->freeFarRenderPass (this, _PatchRdrPassFar1, Far1);
162 // Can we use the old pass1 ?
163 if (newFar1==Far0)
165 // Yes, recycle it!
166 _PatchRdrPassFar1= oldPass0;
167 nlassert (_PatchRdrPassFar1);
169 // Copy uv coordinates
170 Far1UScale=oldFar0UScale;
171 Far1VScale=oldFar0VScale;
172 Far1UBias=oldFar0UBias;
173 Far1VBias=oldFar0VBias;
175 // Copy rotation flag
176 Flags&=~NL_PATCH_FAR1_ROTATED; // erase it
177 if (oldFlags&NL_PATCH_FAR0_ROTATED)
178 Flags|=NL_PATCH_FAR1_ROTATED; // copy it
180 else // get a new render pass
182 // Rotation boolean
183 bool bRot;
184 _PatchRdrPassFar1=Zone->Landscape->getFarRenderPass(this, newFar1, Far1UScale, Far1VScale, Far1UBias, Far1VBias, bRot);
185 nlassert (_PatchRdrPassFar1);
187 // Flags is set if the far texture is rotated of 90deg to the left
188 if (bRot)
189 Flags|=NL_PATCH_FAR1_ROTATED;
190 else
191 Flags&=~NL_PATCH_FAR1_ROTATED;
194 // Compute info for transition.
195 float farDist = 0.f;
196 switch(newFar1)
198 case 1: farDist= CLandscapeGlobals::TileDistNear; break;
199 case 2: farDist= CLandscapeGlobals::Far0Dist; break;
200 case 3: farDist= CLandscapeGlobals::Far1Dist; break;
201 default: nlstop;
203 TransitionSqrMin= sqr(farDist-CLandscapeGlobals::FarTransition);
204 OOTransitionSqrDelta= 1.0f/(sqr(farDist)-TransitionSqrMin);
206 else // no more far pass1
208 if (_PatchRdrPassFar1)
210 Zone->Landscape->freeFarRenderPass (this, _PatchRdrPassFar1, Far1);
211 _PatchRdrPassFar1=NULL;
218 // Don't copy Far0 and Far1.
222 // ***************************************************************************
223 void CPatch::updateTextureFarOnly(const NLMISC::CBSphere &patchSphere)
225 sint newFar0,newFar1;
226 // compute new Far0 and new Far1.
227 computeNewFar(patchSphere, newFar0, newFar1);
229 // Far change.
230 //------------------
231 // Set new far values
232 Far0= newFar0;
233 Far1= newFar1;
238 // ***************************************************************************
239 // ***************************************************************************
240 // Patch / Face rendering.
241 // ***************************************************************************
242 // ***************************************************************************
245 // ***************************************************************************
246 void CPatch::preRender(const NLMISC::CBSphere &patchSphere)
248 // 0. Classify the patch, and update TextureInfo.
249 //=======================
250 sint newFar0,newFar1;
251 // compute new Far0 and new Far1.
252 computeNewFar(patchSphere, newFar0, newFar1);
255 // 2. Update vertices in VB
256 //========================
257 sint oldFar0= Far0, oldFar1= Far1;
259 // Test if go in or go out tileMode.
260 bool changeTileMode;
261 // this is true if a change is made, and if old or current is in TileMode.
262 changeTileMode= (newFar0!=oldFar0) && (newFar0==0 || oldFar0==0);
263 // Or this is true if Far0 / Far1 was invalid before.
264 changeTileMode= changeTileMode || oldFar0==-1 || oldFar1==-1;
266 // Pre VB change.
267 //------------------
268 // In this case, major change: delete all VB, then recreate after.
269 if(changeTileMode)
271 // delete the old VB (NB: isRenderClipped()==false here).
272 // NB: Far0 and Far1 are still unmodified, so deleteVB() will do the good job.
273 deleteVBAndFaceVector();
275 else
277 // minor change: Far0 UV, or Far1.
278 // Far0 UV: do nothing here.
279 // If change in Far1, must delete Far1
280 if(newFar1!=oldFar1)
282 // NB: Far1 is still unmodified, so deleteVB() will do the good job.
283 deleteVBAndFaceVectorFar1Only();
287 // Far change.
288 //------------------
289 // Set new far values
290 Far0= newFar0;
291 Far1= newFar1;
294 // Post VB change.
295 //------------------
296 if(changeTileMode)
298 // major change: recreate all the VB.
299 allocateVBAndFaceVector();
300 // Then try to refill if possible.
301 fillVB();
303 else
305 // minor change: Far0 UV, or Far1.
306 // If change in Far0
307 if(newFar0!=oldFar0)
309 // Then must recompute VB with good UVs.
310 // An optimisation is to check if UVs had really change (see UScale ...)
311 // but the case they don't change is very rare: 1/16.
312 fillVBFar0Only();
315 // If change in Far1, must allcoate and recompute UVs.
316 if(newFar1!=oldFar1)
318 allocateVBAndFaceVectorFar1Only();
319 // try to fill if no reallocation problem
320 fillVBFar1Only();
325 // 3. Append patch to renderList.
326 //=====================
327 // This patch is visible. So if good far, append.
328 if(Far0>0)
330 _PatchRdrPassFar0->appendRdrPatchFar0(this);
332 // Same for Far1.
333 if(Far1>0)
335 _PatchRdrPassFar1->appendRdrPatchFar1(this);
339 // 4. Clip tess blocks.
340 //=====================
341 // If we are in Tile/FarTransition
342 bool doClipFar= Far0==0 && Far1==1;
343 // Parse all TessBlocks.
344 uint nTessBlock= TessBlocks.size();
345 CTessBlock *pTessBlock= nTessBlock>0? &TessBlocks[0]: NULL ;
346 for(; nTessBlock>0; pTessBlock++, nTessBlock--)
348 CTessBlock &tblock= *pTessBlock;
350 // bkup the old result for clipping
351 bool oldVisibleFar0= tblock.visibleFar0();
352 bool oldVisibleTile= tblock.visibleTile();
353 bool oldVisibleFar1= tblock.visibleFar1();
355 // If this TessBlock is empty, do not need to clip
356 if(tblock.FaceTileMaterialRefCount==0)
358 // Simply force the clip.
359 tblock.forceClip();
361 else
363 // clip the tessBlock.
364 tblock.resetClip();
365 tblock.clip();
366 // If we are in Tile/FarTransition
367 if(doClipFar)
368 tblock.clipFar(CLandscapeGlobals::RefineCenter, CLandscapeGlobals::TileDistNear, CLandscapeGlobals::FarTransition);
370 // If TileMode, and if tile visible
371 if(Far0==0 && tblock.visibleTile() )
373 // Append all tiles (if any) to the renderPass list!
374 for(uint j=0;j<NL3D_TESSBLOCK_TILESIZE; j++)
376 // If tile exist
377 if(tblock.RdrTileRoot[j])
378 // add it to the renderList
379 tblock.RdrTileRoot[j]->appendTileToEachRenderPass(NumRenderableFaces);
384 // If change of clip in tessBlock, must update the tessBlock
385 if( Far0> 0 && oldVisibleFar0 != tblock.visibleFar0() )
387 if( tblock.visibleFar0() )
389 // allocate
390 updateFar0VBAlloc(tblock.FarVertexList, true);
391 // fill only if possible.
392 if(!CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs())
393 fillFar0VertexListVB(tblock.FarVertexList);
394 // rebuild triangles index list.
395 tblock.refillFaceVectorFar0();
397 else
399 // delete
400 updateFar0VBAlloc(tblock.FarVertexList, false);
403 if( Far0==0 && oldVisibleTile != tblock.visibleTile() )
405 if( tblock.visibleTile() )
407 // allocate
408 updateTileVBAlloc(tblock.NearVertexList, true);
409 // fill only if possible.
410 if(!CLandscapeGlobals::CurrentTileVBAllocator->reallocationOccurs())
411 fillTileVertexListVB(tblock.NearVertexList);
412 // rebuild triangles index list.
413 tblock.refillFaceVectorTile();
415 else
417 // delete
418 updateTileVBAlloc(tblock.NearVertexList, false);
421 if( Far1> 0 && oldVisibleFar1 != tblock.visibleFar1() )
423 if( tblock.visibleFar1() )
425 // allocate
426 updateFar1VBAlloc(tblock.FarVertexList, true);
427 // fill only if possible.
428 if(!CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs())
429 fillFar1VertexListVB(tblock.FarVertexList);
430 // rebuild triangles index list.
431 tblock.refillFaceVectorFar1();
433 else
435 // delete
436 updateFar1VBAlloc(tblock.FarVertexList, false);
444 // Special profiling.
445 #ifdef NL3D_PROFILE_LAND
446 #define NL3D_PROFILE_LAND_ADD_FACE_VECTOR(_x, _fv) \
447 if(_fv) \
449 NL3D_PROFILE_LAND_ADD(_x, *_fv); \
451 #else
452 #define NL3D_PROFILE_LAND_ADD_FACE_VECTOR(_x, _fv)
453 #endif
456 // ***************************************************************************
457 static inline void renderFaceVector(TLandscapeIndexType *fv)
460 Remind that structure of fv is:
461 uint32 NumTri
462 uint32 index0Tri0
463 uint32 index1Tri0
464 uint32 index2Tri0
465 uint32 index0Tri1
466 uint32 index1Tri1
467 .....
470 // If not NULL (ie not empty).
471 if(fv)
473 // TestYoyo: Bench.
475 extern uint TEMP_NRFV;
476 extern uint TEMP_NRFVTri;
477 extern float TEMP_NRFVMeanTri;
478 extern float TEMP_NRFVDeltaTri;
479 TEMP_NRFV++;
480 TEMP_NRFVTri+= *fv;
481 TEMP_NRFVDeltaTri+= sqr(*fv-TEMP_NRFVMeanTri);
484 // here we have NumTri>0, because fv!=NULL.
486 // making lot of render() is slower than copy a block, and render it.
487 //CLandscapeGlobals::PatchCurrentDriver->renderSimpleTriangles(fv+1, *fv);
488 CHECK_IBA_RANGE(CLandscapeGlobals::PassTriArrayIBA, NL3D_LandscapeGlobals_PassTriCurPtr, *fv*3 * sizeof(uint32));
489 #if defined(NL_OS_WINDOWS) && !defined(NL_NO_ASM)
490 #ifndef NL_LANDSCAPE_INDEX16
491 __asm
493 mov ebx, fv
494 mov edi, NL3D_LandscapeGlobals_PassTriCurPtr
496 mov edx, NL3D_LandscapeGlobals_PassNTri
497 xor eax, eax // Avoid AGI stall.
499 mov ecx, [ebx]
500 lea esi, [ebx+4]
502 mov eax, ecx // eax= bkup NumTris
503 lea ecx, [ecx + ecx*2] // ecx= nTriIndex= NumTris*3
505 // copy tri indices
506 rep movsd
508 add edx, eax // edx= NL3D_LandscapeGlobals_PassNTri + NumTri;
510 // NL3D_LandscapeGlobals_PassTriCurPtr= edi= new ptr after copy
511 mov NL3D_LandscapeGlobals_PassTriCurPtr, edi
512 mov NL3D_LandscapeGlobals_PassNTri, edx
514 #else
515 __asm
517 mov ebx, fv
518 mov edi, NL3D_LandscapeGlobals_PassTriCurPtr
520 mov edx, NL3D_LandscapeGlobals_PassNTri
521 xor eax, eax // Avoid AGI stall.
523 movzx ecx, word ptr [ebx]
524 lea esi, [ebx+2]
526 mov eax, ecx // eax= bkup NumTris
527 lea ecx, [ecx + ecx*2] // ecx= nTriIndex= NumTris*3
529 test ecx, 1
530 jne odd_number
531 shr ecx, 1
532 // for alignment, first copy a single word
533 movsw
534 dec ecx
535 rep movsd
536 movsw
537 jmp even_number_done
538 odd_number:
539 shr ecx, 1
540 // for alignment, first copy a single word
541 movsw
542 rep movsd
543 even_number_done:
545 add edx, eax // edx= NL3D_LandscapeGlobals_PassNTri + NumTri;
547 // NL3D_LandscapeGlobals_PassTriCurPtr= edi= new ptr after copy
548 mov NL3D_LandscapeGlobals_PassTriCurPtr, edi
549 mov NL3D_LandscapeGlobals_PassNTri, edx
551 #endif
552 #else
553 uint nTriIndex= *fv*3;
554 // Fill and increment the array.
555 #ifndef NL_LANDSCAPE_INDEX16
556 memcpy( NL3D_LandscapeGlobals_PassTriCurPtr, fv+1, nTriIndex * sizeof(uint32) );
557 NL3D_LandscapeGlobals_PassTriCurPtr= (uint32*)NL3D_LandscapeGlobals_PassTriCurPtr + nTriIndex;
558 #else
559 memcpy( NL3D_LandscapeGlobals_PassTriCurPtr, fv+1, nTriIndex * sizeof(uint16) );
560 NL3D_LandscapeGlobals_PassTriCurPtr= (uint16*)NL3D_LandscapeGlobals_PassTriCurPtr + nTriIndex;
561 #endif
562 NL3D_LandscapeGlobals_PassNTri+= *fv;
563 #endif
568 // ***************************************************************************
569 void CPatch::renderFar0()
571 NL3D_PROFILE_LAND_ADD(ProfNPatchRdrFar0, 1);
573 #ifdef NL_DEBUG
574 // Must be visible, and must be called only if the RdrPass is enabled.
575 nlassert(!isRenderClipped() && _PatchRdrPassFar0);
576 #endif
578 // Render tris of MasterBlock.
579 renderFaceVector(MasterBlock.Far0FaceVector);
580 // profile
581 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar0, MasterBlock.Far0FaceVector);
583 // Render tris of TessBlocks.
584 uint nTessBlock= TessBlocks.size();
585 CTessBlock *pTessBlock= nTessBlock>0? &TessBlocks[0]: NULL ;
586 for(; nTessBlock>0; pTessBlock++, nTessBlock--)
588 CTessBlock &tblock= *pTessBlock;
589 // if block visible, render
590 if( tblock.visibleFar0() )
592 renderFaceVector(tblock.Far0FaceVector);
593 // profile
594 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar0, tblock.Far0FaceVector);
600 // ***************************************************************************
601 void CPatch::renderFar1()
603 NL3D_PROFILE_LAND_ADD(ProfNPatchRdrFar1, 1);
605 #ifdef NL_DEBUG
606 // Must be visible, and must be called only if the RdrPass is enabled.
607 nlassert(!isRenderClipped() && _PatchRdrPassFar1);
608 #endif
610 // Render tris of MasterBlock.
611 renderFaceVector(MasterBlock.Far1FaceVector);
612 // profile.
613 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar1, MasterBlock.Far1FaceVector);
615 // Render tris of TessBlocks.
616 uint nTessBlock= TessBlocks.size();
617 CTessBlock *pTessBlock= nTessBlock>0? &TessBlocks[0]: NULL ;
618 for(; nTessBlock>0; pTessBlock++, nTessBlock--)
620 CTessBlock &tblock= *pTessBlock;
621 // if block visible, render
622 if( tblock.visibleFar1() )
624 renderFaceVector(tblock.Far1FaceVector);
625 // profile.
626 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar1, tblock.Far1FaceVector);
632 // ***************************************************************************
633 void CTileMaterial::renderTile(uint pass)
635 // because precisely inserted in preRender(), and correctly tested, this tile is to be rendered,
636 // If the pass is enabled.
637 if(Pass[pass].PatchRdrPass)
639 // render tris of the good faceList.
640 renderFaceVector(TileFaceVectors[pass]);
642 // profile.
643 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrTile[pass], TileFaceVectors[pass]);
647 // ***************************************************************************
648 void CTileMaterial::renderTilePassRGB0()
650 // because precisely inserted in preRender(), and correctly tested, this tile is to be rendered,
651 // this pass must be enabled!
652 nlassert(Pass[NL3D_TILE_PASS_RGB0].PatchRdrPass);
653 // render tris of the good faceList.
654 renderFaceVector(TileFaceVectors[NL3D_TILE_PASS_RGB0]);
656 // profile.
657 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrTile[NL3D_TILE_PASS_RGB0], TileFaceVectors[NL3D_TILE_PASS_RGB0]);
660 // ***************************************************************************
661 void CTileMaterial::renderTilePassLightmap()
663 // because precisely inserted in preRender(), and correctly tested, this tile is to be rendered,
664 // this pass must be enabled!
665 nlassert(Pass[NL3D_TILE_PASS_LIGHTMAP].PatchRdrPass);
666 // render tris of the good faceList, ie the one of PassRGB0, because vertices are reused.
667 renderFaceVector(TileFaceVectors[NL3D_TILE_PASS_RGB0]);
669 // profile.
670 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrTile[NL3D_TILE_PASS_LIGHTMAP], TileFaceVectors[NL3D_TILE_PASS_RGB0]);
674 // ***************************************************************************
675 // ***************************************************************************
676 // FaceVector Allocation
677 // ***************************************************************************
678 // ***************************************************************************
681 // ***************************************************************************
682 void CPatch::createFaceVectorFar1()
684 if(Far1>0)
686 // Create the face for all TessBlocks.
687 MasterBlock.createFaceVectorFar1(getLandscape()->_FaceVectorManager);
688 for(uint i=0; i<TessBlocks.size(); i++)
689 TessBlocks[i].createFaceVectorFar1(getLandscape()->_FaceVectorManager);
692 // ***************************************************************************
693 void CPatch::deleteFaceVectorFar1()
695 if(Far1>0)
697 // delete the face for all TessBlocks.
698 MasterBlock.deleteFaceVectorFar1(getLandscape()->_FaceVectorManager);
699 for(uint i=0; i<TessBlocks.size(); i++)
700 TessBlocks[i].deleteFaceVectorFar1(getLandscape()->_FaceVectorManager);
703 // ***************************************************************************
704 void CPatch::createFaceVectorFar0OrTile()
706 // If Far Mode.
707 if(Far0>0)
709 // Create the face for all TessBlocks.
710 MasterBlock.createFaceVectorFar0(getLandscape()->_FaceVectorManager);
711 for(uint i=0; i<TessBlocks.size(); i++)
712 TessBlocks[i].createFaceVectorFar0(getLandscape()->_FaceVectorManager);
714 // Or If Tile Mode.
715 else if(Far0==0)
717 // Create the face for all TessBlocks.
718 // No tiles in MasterBlock!
719 for(uint i=0; i<TessBlocks.size(); i++)
720 TessBlocks[i].createFaceVectorTile(getLandscape()->_FaceVectorManager);
723 // ***************************************************************************
724 void CPatch::deleteFaceVectorFar0OrTile()
726 // If Far Mode.
727 if(Far0>0)
729 // delete the face for all TessBlocks.
730 MasterBlock.deleteFaceVectorFar0(getLandscape()->_FaceVectorManager);
731 for(uint i=0; i<TessBlocks.size(); i++)
732 TessBlocks[i].deleteFaceVectorFar0(getLandscape()->_FaceVectorManager);
734 // Or If Tile Mode.
735 else if(Far0==0)
737 // delete the face for all TessBlocks.
738 // No tiles in MasterBlock!
739 for(uint i=0; i<TessBlocks.size(); i++)
740 TessBlocks[i].deleteFaceVectorTile(getLandscape()->_FaceVectorManager);
745 // ***************************************************************************
746 void CPatch::recreateTessBlockFaceVector(CTessBlock &block)
748 // Do it Only if patch is visible.
749 if(!isRenderClipped())
751 // Far0.
752 // If Far Mode.
753 if(Far0>0)
755 // Create the face for this TessBlock only.
756 block.createFaceVectorFar0(getLandscape()->_FaceVectorManager);
758 // Or If Tile Mode.
759 else if(Far0==0)
761 // No tiles in MasterBlock! So no need to call createFaceVectorTile(), if this block is the MasterBlock.
762 if(&block != &MasterBlock)
763 block.createFaceVectorTile(getLandscape()->_FaceVectorManager);
766 // Far1.
767 if(Far1>0)
769 // Create the face for this TessBlock only.
770 block.createFaceVectorFar1(getLandscape()->_FaceVectorManager);
777 // ***************************************************************************
778 // ***************************************************************************
779 // VB Allocation
780 // ***************************************************************************
781 // ***************************************************************************
784 // ***************************************************************************
785 void CPatch::updateFar0VBAlloc(CTessList<CTessFarVertex> &vertList, bool alloc)
787 // Traverse the vertList.
788 CTessFarVertex *pVert;
789 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
791 if(alloc)
792 pVert->Index0= CLandscapeGlobals::CurrentFar0VBAllocator->allocateVertex();
793 else
794 CLandscapeGlobals::CurrentFar0VBAllocator->deleteVertex(pVert->Index0);
799 // ***************************************************************************
800 void CPatch::updateFar1VBAlloc(CTessList<CTessFarVertex> &vertList, bool alloc)
802 // Traverse the vertList.
803 CTessFarVertex *pVert;
804 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
806 if(alloc)
807 pVert->Index1= CLandscapeGlobals::CurrentFar1VBAllocator->allocateVertex();
808 else
809 CLandscapeGlobals::CurrentFar1VBAllocator->deleteVertex(pVert->Index1);
814 // ***************************************************************************
815 void CPatch::updateTileVBAlloc(CTessList<CTessNearVertex> &vertList, bool alloc)
817 // Traverse the vertList.
818 CTessNearVertex *pVert;
819 for(pVert= vertList.begin(); pVert; pVert= (CTessNearVertex*)pVert->Next)
821 if(alloc)
822 pVert->Index= CLandscapeGlobals::CurrentTileVBAllocator->allocateVertex();
823 else
824 CLandscapeGlobals::CurrentTileVBAllocator->deleteVertex(pVert->Index);
829 // ***************************************************************************
830 void CPatch::updateVBAlloc(bool alloc)
832 // update Far0.
833 //=======
834 if(Far0>0)
836 // alloc Far0 VB.
837 updateFar0VBAlloc(MasterBlock.FarVertexList, alloc);
838 for(sint i=0; i<(sint)TessBlocks.size(); i++)
840 CTessBlock &tblock= TessBlocks[i];
841 // need update VB only if tessBlock is visible.
842 if( tblock.visibleFar0() )
843 updateFar0VBAlloc(tblock.FarVertexList, alloc);
846 else if (Far0==0)
848 // alloc Tile VB.
849 // No Tiles in MasterBlock!!
850 // Traverse the TessBlocks to add vertices.
851 for(sint i=0; i<(sint)TessBlocks.size(); i++)
853 CTessBlock &tblock= TessBlocks[i];
854 // Add the vertices.
855 // need update VB only if tessBlock is visible.
856 if( tblock.visibleTile() )
857 updateTileVBAlloc(tblock.NearVertexList, alloc);
861 // update Far1.
862 //=======
863 if(Far1>0)
865 // alloc VB.
866 updateFar1VBAlloc(MasterBlock.FarVertexList, alloc);
867 for(sint i=0; i<(sint)TessBlocks.size(); i++)
869 CTessBlock &tblock= TessBlocks[i];
870 // need update VB only if tessBlock is visible.
871 if( tblock.visibleFar1() )
872 updateFar1VBAlloc(tblock.FarVertexList, alloc);
877 // ***************************************************************************
878 void CPatch::deleteVBAndFaceVector()
880 updateVBAlloc(false);
881 deleteFaceVectorFar1();
882 deleteFaceVectorFar0OrTile();
885 // ***************************************************************************
886 void CPatch::allocateVBAndFaceVector()
888 updateVBAlloc(true);
889 createFaceVectorFar1();
890 createFaceVectorFar0OrTile();
894 // ***************************************************************************
895 void CPatch::deleteVBAndFaceVectorFar1Only()
897 if(Far1>0)
899 // alloc VB.
900 updateFar1VBAlloc(MasterBlock.FarVertexList, false);
901 for(sint i=0; i<(sint)TessBlocks.size(); i++)
903 CTessBlock &tblock= TessBlocks[i];
904 // need update VB only if tessBlock is visible.
905 if( tblock.visibleFar1() )
906 updateFar1VBAlloc(tblock.FarVertexList, false);
910 deleteFaceVectorFar1();
913 // ***************************************************************************
914 void CPatch::allocateVBAndFaceVectorFar1Only()
916 if(Far1>0)
918 // alloc VB.
919 updateFar1VBAlloc(MasterBlock.FarVertexList, true);
920 for(sint i=0; i<(sint)TessBlocks.size(); i++)
922 CTessBlock &tblock= TessBlocks[i];
923 // need update VB only if tessBlock is visible.
924 if( tblock.visibleFar1() )
925 updateFar1VBAlloc(tblock.FarVertexList, true);
929 createFaceVectorFar1();
933 // ***************************************************************************
934 void CPatch::debugAllocationMarkIndicesFarList(CTessList<CTessFarVertex> &vertList, uint marker)
936 // Traverse the vertList.
937 CTessFarVertex *pVert;
938 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
940 pVert->Index0= marker;
941 pVert->Index1= marker;
945 void CPatch::debugAllocationMarkIndicesNearList(CTessList<CTessNearVertex> &vertList, uint marker)
947 // Traverse the vertList.
948 CTessNearVertex *pVert;
949 for(pVert= vertList.begin(); pVert; pVert= (CTessNearVertex*)pVert->Next)
951 pVert->Index= marker;
955 void CPatch::debugAllocationMarkIndices(uint marker)
957 sint i;
959 // Do it For Far.
960 debugAllocationMarkIndicesFarList(MasterBlock.FarVertexList, marker);
961 for(i=0; i<(sint)TessBlocks.size(); i++)
963 CTessBlock &tblock= TessBlocks[i];
964 debugAllocationMarkIndicesFarList(tblock.FarVertexList, marker);
966 // Do it For Near.
967 // No Tiles in MasterBlock!!
968 for(i=0; i<(sint)TessBlocks.size(); i++)
970 CTessBlock &tblock= TessBlocks[i];
971 debugAllocationMarkIndicesNearList(tblock.NearVertexList, marker);
978 // ***************************************************************************
979 // ***************************************************************************
980 // VB Filling.
981 // ***************************************************************************
982 // ***************************************************************************
985 // ***************************************************************************
986 // NB: need to be inlined only for fillFar0VB() in this file.
987 inline void CPatch::fillFar0VertexVB(CTessFarVertex *pVert)
989 // The Buffers must have been locked
990 nlassert(CLandscapeGlobals::CurrentFar0VBAllocator);
991 nlassert(CLandscapeGlobals::CurrentFar0VBAllocator->bufferLocked());
992 // VBInfo must be OK.
993 nlassert(!CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs());
995 static uint8 *CurVBPtr;
996 // Compute/build the new vertex.
997 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar0VBInfo.VertexCoordPointer;
998 CurVBPtr+= pVert->Index0 * CLandscapeGlobals::CurrentFar0VBInfo.VertexSize;
1000 // NB: the filling order of data is important, for AGP write combiners.
1002 // compute Uvs.
1003 static CUV uv;
1004 CParamCoord pc= pVert->PCoord;
1005 if (Flags&NL_PATCH_FAR0_ROTATED)
1007 uv.U= pc.getT()* Far0UScale + Far0UBias;
1008 uv.V= (1.f-pc.getS())* Far0VScale + Far0VBias;
1010 else
1012 uv.U= pc.getS()* Far0UScale + Far0UBias;
1013 uv.V= pc.getT()* Far0VScale + Far0VBias;
1016 // compute Dynamic lightmap Uv.
1017 static CUV uvDLM;
1018 if(_DLMContext) // (NB: Suppose BTB kill this test).
1020 // compute UV with DLM context info.
1021 uvDLM.U= pc.getS()* _DLMContext->DLMUScale + _DLMContext->DLMUBias;
1022 uvDLM.V= pc.getT()* _DLMContext->DLMVScale + _DLMContext->DLMVBias;
1024 else
1026 // just set UV so the vertex point to a black pixel (see CTextureDLM).
1027 uvDLM.U= 1;
1028 uvDLM.V= 1;
1031 // If not VertexProgram (NB: Suppose BTB kill this test).
1032 if( !CLandscapeGlobals::VertexProgramEnabled )
1034 // Set Pos. Set it local to the current center of landscape
1035 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr, sizeof(CVector));
1036 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
1037 // Set Uvs.
1038 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff0, sizeof(CUV));
1039 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff0)= uv;
1040 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1, sizeof(CUV));
1041 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1)= uvDLM;
1043 else
1045 // Else must setup Vertex program inputs
1046 // v[0]== StartPos.
1047 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr, sizeof(CVector));
1048 *(CVector*)CurVBPtr= pVert->Src->StartPos;
1049 // v[8]== Tex0
1050 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff0, sizeof(CUV));
1051 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff0)= uv;
1052 // v[9]== Tex1
1053 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1, sizeof(CUV));
1054 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1)= uvDLM;
1056 // v[10]== GeomInfo.
1057 static CUV geomInfo;
1058 geomInfo.U= pVert->Src->MaxFaceSize * CLandscapeGlobals::OORefineThreshold;
1059 geomInfo.V= pVert->Src->MaxNearLimit;
1060 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.GeomInfoOff, sizeof(CUV));
1061 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.GeomInfoOff)= geomInfo;
1063 // v[11]== EndPos - StartPos
1064 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.DeltaPosOff, sizeof(CVector))
1065 *(CVector*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.DeltaPosOff)=
1066 pVert->Src->EndPos - pVert->Src->StartPos;
1069 // ***************************************************************************
1070 // NB: need to be inlined only for fillFar1VB() in this file.
1071 inline void CPatch::fillFar1VertexVB(CTessFarVertex *pVert)
1073 // The Buffers must have been locked
1074 nlassert(CLandscapeGlobals::CurrentFar1VBAllocator);
1075 nlassert(CLandscapeGlobals::CurrentFar1VBAllocator->bufferLocked());
1076 // VBInfo must be OK.
1077 nlassert(!CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs());
1079 static uint8 *CurVBPtr;
1080 // Compute/build the new vertex.
1081 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar1VBInfo.VertexCoordPointer;
1082 CurVBPtr+= pVert->Index1 * CLandscapeGlobals::CurrentFar1VBInfo.VertexSize;
1084 // NB: the filling order of data is important, for AGP write combiners.
1086 // compute Uvs.
1087 static CUV uv;
1088 CParamCoord pc= pVert->PCoord;
1089 if (Flags&NL_PATCH_FAR1_ROTATED)
1091 uv.U= pc.getT()* Far1UScale + Far1UBias;
1092 uv.V= (1.f-pc.getS())* Far1VScale + Far1VBias;
1094 else
1096 uv.U= pc.getS()* Far1UScale + Far1UBias;
1097 uv.V= pc.getT()* Far1VScale + Far1VBias;
1100 // compute Dynamic lightmap Uv.
1101 static CUV uvDLM;
1102 if(_DLMContext) // (NB: Suppose BTB kill this test).
1104 // compute UV with DLM context info.
1105 uvDLM.U= pc.getS()* _DLMContext->DLMUScale + _DLMContext->DLMUBias;
1106 uvDLM.V= pc.getT()* _DLMContext->DLMVScale + _DLMContext->DLMVBias;
1108 else
1110 // just set UV so the vertex point to a black pixel (see CTextureDLM).
1111 uvDLM.U= 1;
1112 uvDLM.V= 1;
1115 // If not VertexProgram (NB: Suppose BTB kill this test).
1116 if( !CLandscapeGlobals::VertexProgramEnabled )
1118 // Set Pos. Set it local to the current center of landscape
1119 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr, sizeof(CVector));
1120 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
1121 // Set Uvs.
1122 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff0, sizeof(CUV));
1123 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff0)= uv;
1124 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1, sizeof(CUV));
1125 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1)= uvDLM;
1126 // Set default color.
1127 static CRGBA col(255,255,255,255);
1128 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.ColorOff, sizeof(CRGBA));
1129 *(CRGBA*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.ColorOff)= col;
1131 else
1133 // Else must setup Vertex program inputs
1134 // v[0]== StartPos.
1135 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr, sizeof(CVector));
1136 *(CVector*)CurVBPtr= pVert->Src->StartPos;
1137 // v[8]== Tex0
1138 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff0, sizeof(CUV));
1139 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff0)= uv;
1140 // v[9]== Tex1
1141 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1, sizeof(CUV));
1142 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1)= uvDLM;
1144 // v[10]== GeomInfo.
1145 static CUV geomInfo;
1146 geomInfo.U= pVert->Src->MaxFaceSize * CLandscapeGlobals::OORefineThreshold;
1147 geomInfo.V= pVert->Src->MaxNearLimit;
1148 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.GeomInfoOff, sizeof(CUV));
1149 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.GeomInfoOff)= geomInfo;
1151 // v[11]== EndPos - StartPos
1152 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.DeltaPosOff, sizeof(CVector))
1153 *(CVector*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.DeltaPosOff)=
1154 pVert->Src->EndPos - pVert->Src->StartPos;
1156 // v[12]== Alpha information
1157 // Hopefully, fillVBFar1Only() is called each Time the Far1 change, in preRender().
1158 // So TransitionSqrMin and OOTransitionSqrDelta in CPath are valid.
1159 geomInfo.U= TransitionSqrMin;
1160 geomInfo.V= OOTransitionSqrDelta;
1161 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.AlphaInfoOff, sizeof(CUV))
1162 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.AlphaInfoOff)= geomInfo;
1166 // ***************************************************************************
1167 // NB: need to be inlined only for fillTileVB() in this file.
1168 inline void CPatch::fillTileVertexVB(CTessNearVertex *pVert)
1170 // The Buffers must have been locked
1171 nlassert(CLandscapeGlobals::CurrentTileVBAllocator);
1172 nlassert(CLandscapeGlobals::CurrentTileVBAllocator->bufferLocked());
1173 // VBInfo must be OK.
1174 nlassert(!CLandscapeGlobals::CurrentTileVBAllocator->reallocationOccurs());
1176 static uint8 *CurVBPtr;
1177 // Compute/build the new vertex.
1178 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentTileVBInfo.VertexCoordPointer;
1179 CurVBPtr+= pVert->Index * CLandscapeGlobals::CurrentTileVBInfo.VertexSize;
1182 // NB: the filling order of data is important, for AGP write combiners.
1184 // If not VertexProgram (NB: Suppose BTB kill this test).
1185 if( !CLandscapeGlobals::VertexProgramEnabled )
1187 // Set Pos. Set it local to the current center of landscape
1188 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr, sizeof(CVector))
1189 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
1190 // Set Uvs.
1191 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff0, sizeof(CUV))
1192 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff0)= pVert->PUv0;
1193 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff1, sizeof(CUV))
1194 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff1)= pVert->PUv1;
1195 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff2, sizeof(CUV))
1196 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff2)= pVert->PUv2;
1198 else
1200 // Else must setup Vertex program inputs
1201 // v[0]== StartPos.
1202 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr, sizeof(CVector))
1203 *(CVector*)CurVBPtr= pVert->Src->StartPos;
1204 // v[8]== Tex0
1205 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff0, sizeof(CUV))
1206 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff0)= pVert->PUv0;
1207 // v[9]== Tex1
1208 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff1, sizeof(CUV))
1209 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff1)= pVert->PUv1;
1210 // v[12]== Tex2
1211 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff2, sizeof(CUV))
1212 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.TexCoordOff2)= pVert->PUv2;
1214 // v[10]== GeomInfo.
1215 static CUV geomInfo;
1216 geomInfo.U= pVert->Src->MaxFaceSize * CLandscapeGlobals::OORefineThreshold;
1217 geomInfo.V= pVert->Src->MaxNearLimit;
1218 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.GeomInfoOff, sizeof(CUV))
1219 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.GeomInfoOff)= geomInfo;
1221 // v[11]== EndPos - StartPos
1222 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.DeltaPosOff, sizeof(CVector))
1223 *(CVector*)(CurVBPtr + CLandscapeGlobals::CurrentTileVBInfo.DeltaPosOff)=
1224 pVert->Src->EndPos - pVert->Src->StartPos;
1229 // ***************************************************************************
1230 void CPatch::fillFar0VertexListVB(CTessList<CTessFarVertex> &vertList)
1232 // Traverse the vertList.
1233 CTessFarVertex *pVert;
1234 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1236 fillFar0VertexVB(pVert);
1241 // ***************************************************************************
1242 void CPatch::fillFar1VertexListVB(CTessList<CTessFarVertex> &vertList)
1244 // Traverse the vertList.
1245 CTessFarVertex *pVert;
1246 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1248 fillFar1VertexVB(pVert);
1253 // ***************************************************************************
1254 void CPatch::fillTileVertexListVB(CTessList<CTessNearVertex> &vertList)
1256 // Traverse the vertList.
1257 CTessNearVertex *pVert;
1258 for(pVert= vertList.begin(); pVert; pVert= (CTessNearVertex*)pVert->Next)
1260 fillTileVertexVB(pVert);
1266 // ***************************************************************************
1267 void CPatch::fillVB()
1269 // Fill Far0.
1270 //=======
1271 // fill only if no reallcoation occurs
1272 if(Far0>0 && !CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs() )
1274 // Fill Far0 VB.
1275 fillFar0VertexListVB(MasterBlock.FarVertexList);
1276 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1278 CTessBlock &tblock= TessBlocks[i];
1279 // fill only if tblock visible.
1280 if( tblock.visibleFar0() )
1281 fillFar0VertexListVB(tblock.FarVertexList);
1284 else if(Far0==0 && !CLandscapeGlobals::CurrentTileVBAllocator->reallocationOccurs() )
1286 // Fill Tile VB.
1287 // No Tiles in MasterBlock!!
1288 // Traverse the TessBlocks to add vertices.
1289 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1291 CTessBlock &tblock= TessBlocks[i];
1292 // fill only if tblock visible.
1293 if( tblock.visibleTile() )
1294 fillTileVertexListVB(tblock.NearVertexList);
1298 // Fill Far1.
1299 //=======
1300 if(Far1>0 && !CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs() )
1302 // Fill VB.
1303 fillFar1VertexListVB(MasterBlock.FarVertexList);
1304 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1306 CTessBlock &tblock= TessBlocks[i];
1307 // fill only if tblock visible.
1308 if( tblock.visibleFar1() )
1309 fillFar1VertexListVB(tblock.FarVertexList);
1316 // ***************************************************************************
1317 void CPatch::fillVBIfVisible()
1319 if(isRenderClipped()==false)
1320 fillVB();
1324 // ***************************************************************************
1325 void CPatch::fillVBFar0Only()
1327 if(Far0>0 && !CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs() )
1329 // Fill Far0 VB.
1330 fillFar0VertexListVB(MasterBlock.FarVertexList);
1331 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1333 CTessBlock &tblock= TessBlocks[i];
1334 // fill only if tblock visible.
1335 if( tblock.visibleFar0() )
1336 fillFar0VertexListVB(tblock.FarVertexList);
1342 // ***************************************************************************
1343 void CPatch::fillVBFar1Only()
1345 if(Far1>0 && !CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs() )
1347 // Fill VB.
1348 fillFar1VertexListVB(MasterBlock.FarVertexList);
1349 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1351 CTessBlock &tblock= TessBlocks[i];
1352 // fill only if tblock visible.
1353 if( tblock.visibleFar1() )
1354 fillFar1VertexListVB(tblock.FarVertexList);
1359 // ***************************************************************************
1360 // ***************************************************************************
1361 // VB Software Geomorph / Alpha.
1362 // ***************************************************************************
1363 // ***************************************************************************
1366 // ***************************************************************************
1367 void CPatch::computeGeomorphVertexList(CTessList<CTessFarVertex> &vertList)
1369 // Traverse the vertList.
1370 CTessFarVertex *pVert;
1371 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1373 // compute geomorph.
1374 pVert->Src->computeGeomPos();
1379 // ***************************************************************************
1380 void CPatch::computeGeomorphFar0VertexListVB(CTessList<CTessFarVertex> &vertList)
1382 // Traverse the vertList.
1383 CTessFarVertex *pVert;
1384 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1386 static uint8 *CurVBPtr;
1387 // Compute/build the new vertex.
1388 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar0VBInfo.VertexCoordPointer;
1389 CurVBPtr+= pVert->Index0 * CLandscapeGlobals::CurrentFar0VBInfo.VertexSize;
1391 // Set Geomorphed Position. Set it local to the current center of landscape
1392 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr, sizeof(CVector))
1393 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
1398 // ***************************************************************************
1399 void CPatch::computeGeomorphAlphaFar1VertexListVB(CTessList<CTessFarVertex> &vertList)
1401 // Traverse the vertList.
1402 CTessFarVertex *pVert;
1403 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1405 static uint8 *CurVBPtr;
1406 // Compute/build the new vertex.
1407 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar1VBInfo.VertexCoordPointer;
1408 CurVBPtr+= pVert->Index1 * CLandscapeGlobals::CurrentFar1VBInfo.VertexSize;
1410 // NB: the filling order of data is important, for AGP write combiners.
1412 // Set Geomorphed Position. Set it local to the current center of landscape
1413 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr, sizeof(CVector))
1414 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
1416 // Set Alpha color.
1417 static CRGBA col(255,255,255,255);
1418 // For Far1, use alpha fro transition.
1419 // Prefer Use Pos, because of caching. So little difference between Soft and VertexProgram mode.
1420 float f= (pVert->Src->Pos - CLandscapeGlobals::RefineCenter).sqrnorm();
1421 f= (f-TransitionSqrMin) * OOTransitionSqrDelta;
1422 clamp(f,0,1);
1423 col.A= (uint8)(f*255);
1424 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.ColorOff, sizeof(CRGBA))
1425 *(CRGBA*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.ColorOff)= col;
1430 // ***************************************************************************
1431 void CPatch::computeGeomorphTileVertexListVB(CTessList<CTessNearVertex> &vertList)
1433 // Traverse the vertList.
1434 CTessNearVertex *pVert;
1435 for(pVert= vertList.begin(); pVert; pVert= (CTessNearVertex*)pVert->Next)
1437 static uint8 *CurVBPtr;
1438 // Compute/build the new vertex.
1439 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentTileVBInfo.VertexCoordPointer;
1440 CurVBPtr+= pVert->Index * CLandscapeGlobals::CurrentTileVBInfo.VertexSize;
1442 // Set Geomorphed Position. Set it local to the current center of landscape
1443 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo.Accessor, CurVBPtr, sizeof(CVector))
1444 *(CVector*)CurVBPtr= pVert->Src->Pos - CLandscapeGlobals::PZBModelPosition;
1450 // ***************************************************************************
1451 void CPatch::computeSoftwareGeomorphAndAlpha()
1453 if(isRenderClipped())
1454 return;
1456 // Compute Geomorph.
1457 //=======
1458 // Need only to fill CTessVertex, so do it only for FarVertices
1459 // Hence Geomorph is done twice on edges of patches!!.
1460 // If not too near for precise, fast compute of geomorph.
1461 if( TessBlocks.empty() )
1463 // Just update all vertices of master block.
1464 computeGeomorphVertexList(MasterBlock.FarVertexList);
1466 else
1468 // update all vertices of master block.
1469 computeGeomorphVertexList(MasterBlock.FarVertexList);
1470 // update vertices of others block.
1471 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1473 CTessBlock &tblock= TessBlocks[i];
1474 // Precise Clip.
1475 if(!tblock.getClipped())
1477 // compute the geomorph of the vertices in the tessblock.
1478 computeGeomorphVertexList(tblock.FarVertexList);
1484 // Fill Far0.
1485 //=======
1486 if(Far0>0)
1488 // Fill Far0 VB.
1489 computeGeomorphFar0VertexListVB(MasterBlock.FarVertexList);
1490 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1492 CTessBlock &tblock= TessBlocks[i];
1493 // Precise Clip.
1494 if( tblock.visibleFar0() )
1495 computeGeomorphFar0VertexListVB(tblock.FarVertexList);
1498 else if(Far0==0)
1500 // Fill Tile VB.
1501 // No Tiles in MasterBlock!!
1502 // Traverse the TessBlocks to compute vertices.
1503 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1505 CTessBlock &tblock= TessBlocks[i];
1506 // Precise Clip.
1507 if( tblock.visibleTile() )
1508 computeGeomorphTileVertexListVB(tblock.NearVertexList);
1512 // Fill Far1.
1513 //=======
1514 if(Far1>0)
1516 // Fill VB.
1517 computeGeomorphAlphaFar1VertexListVB(MasterBlock.FarVertexList);
1518 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1520 CTessBlock &tblock= TessBlocks[i];
1521 // Precise Clip.
1522 if( tblock.visibleFar1() )
1523 computeGeomorphAlphaFar1VertexListVB(tblock.FarVertexList);
1529 // ***************************************************************************
1530 // ***************************************************************************
1531 // VB clip Allocate/Filling.
1532 // ***************************************************************************
1533 // ***************************************************************************
1536 // ***************************************************************************
1537 void CPatch::updateClipPatchVB(bool renderClipped)
1539 // If now the patch is invisible
1540 if(renderClipped)
1542 // Then delete vertices.
1543 deleteVBAndFaceVector();
1545 // Now, all vertices in VB are deleted.
1546 // Force clip state of all TessBlocks, so no allocation will be done on Vertices in VB.
1547 if(!TessBlocks.empty())
1549 for(uint i=0; i<TessBlocks.size();i++)
1551 CTessBlock &tblock= TessBlocks[i];
1552 tblock.forceClip();
1556 else
1558 // else allocate / fill them.
1559 allocateVBAndFaceVector();
1560 // NB: fillVB() test if any reallocation occurs.
1561 fillVB();
1566 // ***************************************************************************
1567 // ***************************************************************************
1568 // VB refine Allocate/Filling.
1569 // ***************************************************************************
1570 // ***************************************************************************
1574 // ***************************************************************************
1575 void CPatch::checkCreateVertexVBFar(CTessFarVertex *pVert)
1577 nlassert(pVert);
1578 // If visible, and Far0 in !Tile Mode, allocate.
1579 // NB: must test Far0>0 because vertices are reallocated in preRender() if a change of Far occurs.
1580 if(!isRenderClipped() && Far0>0 && pVert->OwnerBlock->visibleFar0() )
1582 pVert->Index0= CLandscapeGlobals::CurrentFar0VBAllocator->allocateVertex();
1585 // Idem for Far1
1586 if(!isRenderClipped() && Far1>0 && pVert->OwnerBlock->visibleFar1())
1588 pVert->Index1= CLandscapeGlobals::CurrentFar1VBAllocator->allocateVertex();
1594 // ***************************************************************************
1595 void CPatch::checkFillVertexVBFar(CTessFarVertex *pVert)
1597 nlassert(pVert);
1598 // If visible, and Far0 in !Tile Mode, try to fill.
1599 // NB: must test Far0>0 because vertices are reallocated in preRender() if a change of Far occurs.
1600 if(!isRenderClipped() && Far0>0 && pVert->OwnerBlock->visibleFar0())
1602 if( !CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs() )
1603 fillFar0VertexVB(pVert);
1606 // Idem for Far1
1607 if(!isRenderClipped() && Far1>0 && pVert->OwnerBlock->visibleFar1())
1609 if( !CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs() )
1610 fillFar1VertexVB(pVert);
1615 // ***************************************************************************
1616 void CPatch::checkCreateVertexVBNear(CTessNearVertex *pVert)
1618 nlassert(pVert);
1619 // If visible, and Far0 in Tile Mode, allocate.
1620 // NB: must test Far0==0 because vertices are reallocated in preRender() if a change of Far occurs.
1621 if(!isRenderClipped() && Far0==0 && pVert->OwnerBlock->visibleTile())
1623 pVert->Index= CLandscapeGlobals::CurrentTileVBAllocator->allocateVertex();
1628 // ***************************************************************************
1629 void CPatch::checkFillVertexVBNear(CTessNearVertex *pVert)
1631 nlassert(pVert);
1632 // If visible, and Far0 in Tile Mode, try to fill.
1633 // NB: must test Far0==0 because vertices are reallocated in preRender() if a change of Far occurs.
1634 if(!isRenderClipped()&& Far0==0 && pVert->OwnerBlock->visibleTile() )
1636 // try to fill.
1637 if( !CLandscapeGlobals::CurrentTileVBAllocator->reallocationOccurs() )
1638 fillTileVertexVB(pVert);
1643 // ***************************************************************************
1644 void CPatch::checkDeleteVertexVBFar(CTessFarVertex *pVert)
1646 nlassert(pVert);
1647 // If visible, and Far0 in !Tile Mode, ok, the vertex exist in VB, so delete.
1648 // NB: must test Far0>0 because vertices are deleted in preRender() if a change of Far occurs.
1649 if(!isRenderClipped() && Far0>0 && pVert->OwnerBlock->visibleFar0() )
1651 CLandscapeGlobals::CurrentFar0VBAllocator->deleteVertex(pVert->Index0);
1654 // Idem for Far1
1655 if(!isRenderClipped() && Far1>0 && pVert->OwnerBlock->visibleFar1() )
1657 CLandscapeGlobals::CurrentFar1VBAllocator->deleteVertex(pVert->Index1);
1661 // ***************************************************************************
1662 void CPatch::checkDeleteVertexVBNear(CTessNearVertex *pVert)
1664 nlassert(pVert);
1665 // If visible, and Far0 in Tile Mode, ok, the vertex exist in VB, so delete.
1666 // NB: must test Far0==0 because vertices are deleted in preRender() if a change of Far occurs.
1667 if(!isRenderClipped() && Far0==0 && pVert->OwnerBlock->visibleTile() )
1669 CLandscapeGlobals::CurrentTileVBAllocator->deleteVertex(pVert->Index);
1674 // ***************************************************************************
1675 // ***************************************************************************
1676 // VB DLM Filling
1677 // ***************************************************************************
1678 // ***************************************************************************
1681 // ***************************************************************************
1682 void CPatch::fillFar0DLMUvOnlyVertexListVB(CTessList<CTessFarVertex> &vertList)
1684 // The Buffers must have been locked
1685 nlassert(CLandscapeGlobals::CurrentFar0VBAllocator);
1686 nlassert(CLandscapeGlobals::CurrentFar0VBAllocator->bufferLocked());
1687 // VBInfo must be OK.
1688 nlassert(!CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs());
1690 static uint8 *CurVBPtr;
1691 static CUV uvDLM;
1693 // If the DLMContext exist
1694 if(_DLMContext)
1696 // Traverse the vertList, to compute new uvDLM
1697 CTessFarVertex *pVert;
1698 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1700 // Compute/build the new vertex.
1701 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar0VBInfo.VertexCoordPointer;
1702 CurVBPtr+= pVert->Index0 * CLandscapeGlobals::CurrentFar0VBInfo.VertexSize;
1704 // compute Uvs.
1705 CParamCoord pc= pVert->PCoord;
1707 // compute Dynamic lightmap Uv with DLM context info.
1708 uvDLM.U= pc.getS()* _DLMContext->DLMUScale + _DLMContext->DLMUBias;
1709 uvDLM.V= pc.getT()* _DLMContext->DLMVScale + _DLMContext->DLMVBias;
1711 // Set Uv DLM only (NB: same code for VertexProgram or not, only TexCoordOff1 may change).
1712 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1, sizeof(CUV))
1713 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1)= uvDLM;
1716 // else, reset all Uvs
1717 else
1719 // just set UV so the vertex point to a black pixel (see CTextureDLM).
1720 uvDLM.U= 1;
1721 uvDLM.V= 1;
1723 // Traverse the vertList, to reset uv
1724 CTessFarVertex *pVert;
1725 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1727 // Compute/build the new vertex.
1728 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar0VBInfo.VertexCoordPointer;
1729 CurVBPtr+= pVert->Index0 * CLandscapeGlobals::CurrentFar0VBInfo.VertexSize;
1731 // Set Uv DLM only (NB: same code for VertexProgram or not, only TexCoordOff1 may change).
1732 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1, sizeof(CUV))
1733 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar0VBInfo.TexCoordOff1)= uvDLM;
1738 // ***************************************************************************
1739 void CPatch::fillFar1DLMUvOnlyVertexListVB(CTessList<CTessFarVertex> &vertList)
1741 // The Buffers must have been locked
1742 nlassert(CLandscapeGlobals::CurrentFar1VBAllocator);
1743 nlassert(CLandscapeGlobals::CurrentFar1VBAllocator->bufferLocked());
1744 // VBInfo must be OK.
1745 nlassert(!CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs());
1747 static uint8 *CurVBPtr;
1748 static CUV uvDLM;
1750 // If the DLMContext exist
1751 if(_DLMContext)
1753 // Traverse the vertList, to compute new uvDLM
1754 CTessFarVertex *pVert;
1755 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1757 // Compute/build the new vertex.
1758 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar1VBInfo.VertexCoordPointer;
1759 CurVBPtr+= pVert->Index1 * CLandscapeGlobals::CurrentFar1VBInfo.VertexSize;
1761 // compute Uvs.
1762 CParamCoord pc= pVert->PCoord;
1764 // compute Dynamic lightmap Uv with DLM context info.
1765 uvDLM.U= pc.getS()* _DLMContext->DLMUScale + _DLMContext->DLMUBias;
1766 uvDLM.V= pc.getT()* _DLMContext->DLMVScale + _DLMContext->DLMVBias;
1768 // Set Uv DLM only (NB: same code for VertexProgram or not, only TexCoordOff1 may change).
1769 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1, sizeof(CUV))
1770 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1)= uvDLM;
1773 // else, reset all Uvs
1774 else
1776 // just set UV so the vertex point to a black pixel (see CTextureDLM).
1777 uvDLM.U= 1;
1778 uvDLM.V= 1;
1780 // Traverse the vertList, to reset uv
1781 CTessFarVertex *pVert;
1782 for(pVert= vertList.begin(); pVert; pVert= (CTessFarVertex*)pVert->Next)
1784 // Compute/build the new vertex.
1785 CurVBPtr= (uint8*)CLandscapeGlobals::CurrentFar1VBInfo.VertexCoordPointer;
1786 CurVBPtr+= pVert->Index1 * CLandscapeGlobals::CurrentFar1VBInfo.VertexSize;
1788 // Set Uv DLM only (NB: same code for VertexProgram or not, only TexCoordOff1 may change).
1789 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo.Accessor, CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1, sizeof(CUV))
1790 *(CUV*)(CurVBPtr + CLandscapeGlobals::CurrentFar1VBInfo.TexCoordOff1)= uvDLM;
1796 // ***************************************************************************
1797 void CPatch::fillVBFarsDLMUvOnly()
1799 // Do it for Far0.
1800 if(Far0>0 && !CLandscapeGlobals::CurrentFar0VBAllocator->reallocationOccurs() )
1802 // Fill Far0 VB.
1803 fillFar0DLMUvOnlyVertexListVB(MasterBlock.FarVertexList);
1804 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1806 CTessBlock &tblock= TessBlocks[i];
1807 // fill only if tblock visible.
1808 if( tblock.visibleFar0() )
1809 fillFar0DLMUvOnlyVertexListVB(tblock.FarVertexList);
1813 // Do it for Far1.
1814 if(Far1>0 && !CLandscapeGlobals::CurrentFar1VBAllocator->reallocationOccurs() )
1816 // Fill VB.
1817 fillFar1DLMUvOnlyVertexListVB(MasterBlock.FarVertexList);
1818 for(sint i=0; i<(sint)TessBlocks.size(); i++)
1820 CTessBlock &tblock= TessBlocks[i];
1821 // fill only if tblock visible.
1822 if( tblock.visibleFar1() )
1823 fillFar1DLMUvOnlyVertexListVB(tblock.FarVertexList);
1830 } // NL3D