1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
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"
33 using namespace NLMISC
;
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
;
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;
65 // Transition with the next level.
67 if(newFar0
<3 && rr
>-(CLandscapeGlobals::FarTransition
+2*patchSphere
.Radius
))
73 // Update Texture Info.
74 //========================
75 if(newFar0
!=Far0
|| newFar1
!=Far1
)
78 CPatchRdrPass
*oldPass0
=_PatchRdrPassFar0
;
79 CPatchRdrPass
*oldPass1
=_PatchRdrPassFar1
;
87 float oldFar0UScale
=Far0UScale
;
88 float oldFar0VScale
=Far0VScale
;
89 float oldFar0UBias
=Far0UBias
;
90 float oldFar0VBias
=Far0VBias
;
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 ?
105 // Compute / get the texture Far.
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 ?
116 _PatchRdrPassFar0
=oldPass1
;
118 // Copy uv coordinates
119 Far0UScale
=Far1UScale
;
120 Far0VScale
=Far1VScale
;
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
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
137 Flags
|=NL_PATCH_FAR0_ROTATED
;
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 ?
155 // Now let's go with pass1
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 ?
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
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
189 Flags
|=NL_PATCH_FAR1_ROTATED
;
191 Flags
&=~NL_PATCH_FAR1_ROTATED
;
194 // Compute info for transition.
198 case 1: farDist
= CLandscapeGlobals::TileDistNear
; break;
199 case 2: farDist
= CLandscapeGlobals::Far0Dist
; break;
200 case 3: farDist
= CLandscapeGlobals::Far1Dist
; break;
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
);
231 // Set new far values
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.
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;
268 // In this case, major change: delete all VB, then recreate after.
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();
277 // minor change: Far0 UV, or Far1.
278 // Far0 UV: do nothing here.
279 // If change in Far1, must delete Far1
282 // NB: Far1 is still unmodified, so deleteVB() will do the good job.
283 deleteVBAndFaceVectorFar1Only();
289 // Set new far values
298 // major change: recreate all the VB.
299 allocateVBAndFaceVector();
300 // Then try to refill if possible.
305 // minor change: Far0 UV, or Far1.
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.
315 // If change in Far1, must allcoate and recompute UVs.
318 allocateVBAndFaceVectorFar1Only();
319 // try to fill if no reallocation problem
325 // 3. Append patch to renderList.
326 //=====================
327 // This patch is visible. So if good far, append.
330 _PatchRdrPassFar0
->appendRdrPatchFar0(this);
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.
363 // clip the tessBlock.
366 // If we are in Tile/FarTransition
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
++)
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() )
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();
400 updateFar0VBAlloc(tblock
.FarVertexList
, false);
403 if( Far0
==0 && oldVisibleTile
!= tblock
.visibleTile() )
405 if( tblock
.visibleTile() )
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();
418 updateTileVBAlloc(tblock
.NearVertexList
, false);
421 if( Far1
> 0 && oldVisibleFar1
!= tblock
.visibleFar1() )
423 if( tblock
.visibleFar1() )
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();
436 updateFar1VBAlloc(tblock
.FarVertexList
, false);
444 // Special profiling.
445 #ifdef NL3D_PROFILE_LAND
446 #define NL3D_PROFILE_LAND_ADD_FACE_VECTOR(_x, _fv) \
449 NL3D_PROFILE_LAND_ADD(_x, *_fv); \
452 #define NL3D_PROFILE_LAND_ADD_FACE_VECTOR(_x, _fv)
456 // ***************************************************************************
457 static inline void renderFaceVector(TLandscapeIndexType
*fv
)
460 Remind that structure of fv is:
470 // If not NULL (ie not empty).
475 extern uint TEMP_NRFV;
476 extern uint TEMP_NRFVTri;
477 extern float TEMP_NRFVMeanTri;
478 extern float TEMP_NRFVDeltaTri;
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
494 mov edi
, NL3D_LandscapeGlobals_PassTriCurPtr
496 mov edx
, NL3D_LandscapeGlobals_PassNTri
497 xor eax
, eax
// Avoid AGI stall.
502 mov eax
, ecx
// eax= bkup NumTris
503 lea ecx
, [ecx
+ ecx
*2] // ecx= nTriIndex= NumTris*3
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
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
]
526 mov eax
, ecx
// eax= bkup NumTris
527 lea ecx
, [ecx
+ ecx
*2] // ecx= nTriIndex= NumTris*3
532 // for alignment, first copy a single word
540 // for alignment, first copy a single word
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
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
;
559 memcpy( NL3D_LandscapeGlobals_PassTriCurPtr
, fv
+1, nTriIndex
* sizeof(uint16
) );
560 NL3D_LandscapeGlobals_PassTriCurPtr
= (uint16
*)NL3D_LandscapeGlobals_PassTriCurPtr
+ nTriIndex
;
562 NL3D_LandscapeGlobals_PassNTri
+= *fv
;
568 // ***************************************************************************
569 void CPatch::renderFar0()
571 NL3D_PROFILE_LAND_ADD(ProfNPatchRdrFar0
, 1);
574 // Must be visible, and must be called only if the RdrPass is enabled.
575 nlassert(!isRenderClipped() && _PatchRdrPassFar0
);
578 // Render tris of MasterBlock.
579 renderFaceVector(MasterBlock
.Far0FaceVector
);
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
);
594 NL3D_PROFILE_LAND_ADD_FACE_VECTOR(ProfNRdrFar0
, tblock
.Far0FaceVector
);
600 // ***************************************************************************
601 void CPatch::renderFar1()
603 NL3D_PROFILE_LAND_ADD(ProfNPatchRdrFar1
, 1);
606 // Must be visible, and must be called only if the RdrPass is enabled.
607 nlassert(!isRenderClipped() && _PatchRdrPassFar1
);
610 // Render tris of MasterBlock.
611 renderFaceVector(MasterBlock
.Far1FaceVector
);
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
);
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
]);
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
]);
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
]);
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()
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()
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()
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
);
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()
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
);
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())
755 // Create the face for this TessBlock only.
756 block
.createFaceVectorFar0(getLandscape()->_FaceVectorManager
);
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
);
769 // Create the face for this TessBlock only.
770 block
.createFaceVectorFar1(getLandscape()->_FaceVectorManager
);
777 // ***************************************************************************
778 // ***************************************************************************
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
)
792 pVert
->Index0
= CLandscapeGlobals::CurrentFar0VBAllocator
->allocateVertex();
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
)
807 pVert
->Index1
= CLandscapeGlobals::CurrentFar1VBAllocator
->allocateVertex();
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
)
822 pVert
->Index
= CLandscapeGlobals::CurrentTileVBAllocator
->allocateVertex();
824 CLandscapeGlobals::CurrentTileVBAllocator
->deleteVertex(pVert
->Index
);
829 // ***************************************************************************
830 void CPatch::updateVBAlloc(bool alloc
)
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
);
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
];
855 // need update VB only if tessBlock is visible.
856 if( tblock
.visibleTile() )
857 updateTileVBAlloc(tblock
.NearVertexList
, alloc
);
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()
889 createFaceVectorFar1();
890 createFaceVectorFar0OrTile();
894 // ***************************************************************************
895 void CPatch::deleteVBAndFaceVectorFar1Only()
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()
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
)
960 debugAllocationMarkIndicesFarList(MasterBlock
.FarVertexList
, marker
);
961 for(i
=0; i
<(sint
)TessBlocks
.size(); i
++)
963 CTessBlock
&tblock
= TessBlocks
[i
];
964 debugAllocationMarkIndicesFarList(tblock
.FarVertexList
, marker
);
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 // ***************************************************************************
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.
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
;
1012 uv
.U
= pc
.getS()* Far0UScale
+ Far0UBias
;
1013 uv
.V
= pc
.getT()* Far0VScale
+ Far0VBias
;
1016 // compute Dynamic lightmap Uv.
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
;
1026 // just set UV so the vertex point to a black pixel (see CTextureDLM).
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
;
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
;
1045 // Else must setup Vertex program inputs
1047 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo
.Accessor
, CurVBPtr
, sizeof(CVector
));
1048 *(CVector
*)CurVBPtr
= pVert
->Src
->StartPos
;
1050 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar0VBInfo
.Accessor
, CurVBPtr
+ CLandscapeGlobals::CurrentFar0VBInfo
.TexCoordOff0
, sizeof(CUV
));
1051 *(CUV
*)(CurVBPtr
+ CLandscapeGlobals::CurrentFar0VBInfo
.TexCoordOff0
)= uv
;
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.
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
;
1096 uv
.U
= pc
.getS()* Far1UScale
+ Far1UBias
;
1097 uv
.V
= pc
.getT()* Far1VScale
+ Far1VBias
;
1100 // compute Dynamic lightmap Uv.
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
;
1110 // just set UV so the vertex point to a black pixel (see CTextureDLM).
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
;
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
;
1133 // Else must setup Vertex program inputs
1135 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo
.Accessor
, CurVBPtr
, sizeof(CVector
));
1136 *(CVector
*)CurVBPtr
= pVert
->Src
->StartPos
;
1138 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentFar1VBInfo
.Accessor
, CurVBPtr
+ CLandscapeGlobals::CurrentFar1VBInfo
.TexCoordOff0
, sizeof(CUV
));
1139 *(CUV
*)(CurVBPtr
+ CLandscapeGlobals::CurrentFar1VBInfo
.TexCoordOff0
)= uv
;
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
;
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
;
1200 // Else must setup Vertex program inputs
1202 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo
.Accessor
, CurVBPtr
, sizeof(CVector
))
1203 *(CVector
*)CurVBPtr
= pVert
->Src
->StartPos
;
1205 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo
.Accessor
, CurVBPtr
+ CLandscapeGlobals::CurrentTileVBInfo
.TexCoordOff0
, sizeof(CUV
))
1206 *(CUV
*)(CurVBPtr
+ CLandscapeGlobals::CurrentTileVBInfo
.TexCoordOff0
)= pVert
->PUv0
;
1208 CHECK_VBA_RANGE(CLandscapeGlobals::CurrentTileVBInfo
.Accessor
, CurVBPtr
+ CLandscapeGlobals::CurrentTileVBInfo
.TexCoordOff1
, sizeof(CUV
))
1209 *(CUV
*)(CurVBPtr
+ CLandscapeGlobals::CurrentTileVBInfo
.TexCoordOff1
)= pVert
->PUv1
;
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()
1271 // fill only if no reallcoation occurs
1272 if(Far0
>0 && !CLandscapeGlobals::CurrentFar0VBAllocator
->reallocationOccurs() )
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() )
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
);
1300 if(Far1
>0 && !CLandscapeGlobals::CurrentFar1VBAllocator
->reallocationOccurs() )
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)
1324 // ***************************************************************************
1325 void CPatch::fillVBFar0Only()
1327 if(Far0
>0 && !CLandscapeGlobals::CurrentFar0VBAllocator
->reallocationOccurs() )
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() )
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
;
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
;
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())
1456 // Compute Geomorph.
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
);
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
];
1475 if(!tblock
.getClipped())
1477 // compute the geomorph of the vertices in the tessblock.
1478 computeGeomorphVertexList(tblock
.FarVertexList
);
1489 computeGeomorphFar0VertexListVB(MasterBlock
.FarVertexList
);
1490 for(sint i
=0; i
<(sint
)TessBlocks
.size(); i
++)
1492 CTessBlock
&tblock
= TessBlocks
[i
];
1494 if( tblock
.visibleFar0() )
1495 computeGeomorphFar0VertexListVB(tblock
.FarVertexList
);
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
];
1507 if( tblock
.visibleTile() )
1508 computeGeomorphTileVertexListVB(tblock
.NearVertexList
);
1517 computeGeomorphAlphaFar1VertexListVB(MasterBlock
.FarVertexList
);
1518 for(sint i
=0; i
<(sint
)TessBlocks
.size(); i
++)
1520 CTessBlock
&tblock
= TessBlocks
[i
];
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
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
];
1558 // else allocate / fill them.
1559 allocateVBAndFaceVector();
1560 // NB: fillVB() test if any reallocation occurs.
1566 // ***************************************************************************
1567 // ***************************************************************************
1568 // VB refine Allocate/Filling.
1569 // ***************************************************************************
1570 // ***************************************************************************
1574 // ***************************************************************************
1575 void CPatch::checkCreateVertexVBFar(CTessFarVertex
*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();
1586 if(!isRenderClipped() && Far1
>0 && pVert
->OwnerBlock
->visibleFar1())
1588 pVert
->Index1
= CLandscapeGlobals::CurrentFar1VBAllocator
->allocateVertex();
1594 // ***************************************************************************
1595 void CPatch::checkFillVertexVBFar(CTessFarVertex
*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
);
1607 if(!isRenderClipped() && Far1
>0 && pVert
->OwnerBlock
->visibleFar1())
1609 if( !CLandscapeGlobals::CurrentFar1VBAllocator
->reallocationOccurs() )
1610 fillFar1VertexVB(pVert
);
1615 // ***************************************************************************
1616 void CPatch::checkCreateVertexVBNear(CTessNearVertex
*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
)
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() )
1637 if( !CLandscapeGlobals::CurrentTileVBAllocator
->reallocationOccurs() )
1638 fillTileVertexVB(pVert
);
1643 // ***************************************************************************
1644 void CPatch::checkDeleteVertexVBFar(CTessFarVertex
*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
);
1655 if(!isRenderClipped() && Far1
>0 && pVert
->OwnerBlock
->visibleFar1() )
1657 CLandscapeGlobals::CurrentFar1VBAllocator
->deleteVertex(pVert
->Index1
);
1661 // ***************************************************************************
1662 void CPatch::checkDeleteVertexVBNear(CTessNearVertex
*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 // ***************************************************************************
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
;
1693 // If the DLMContext exist
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
;
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
1719 // just set UV so the vertex point to a black pixel (see CTextureDLM).
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
;
1750 // If the DLMContext exist
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
;
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
1776 // just set UV so the vertex point to a black pixel (see CTextureDLM).
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()
1800 if(Far0
>0 && !CLandscapeGlobals::CurrentFar0VBAllocator
->reallocationOccurs() )
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
);
1814 if(Far1
>0 && !CLandscapeGlobals::CurrentFar1VBAllocator
->reallocationOccurs() )
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
);