Show bonus/malus timer text if available
[ryzomcore.git] / nel / src / 3d / tessellation.cpp
blob88c0fa26e73cafe079ab45c9354b41cc873b68a4
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include "nel/3d/tessellation.h"
23 #include "nel/3d/patch.h"
24 #include "nel/3d/zone.h"
25 #include "nel/misc/common.h"
26 #include "nel/3d/landscape_profile.h"
27 #include "nel/3d/landscape.h"
28 #include "nel/3d/patchdlm_context.h"
30 using namespace NLMISC;
31 using namespace std;
33 #ifdef DEBUG_NEW
34 #define new DEBUG_NEW
35 #endif
37 namespace NL3D
41 // ***************************************************************************
42 #define NL3D_TESS_USE_QUADRANT_THRESHOLD 0.1f
45 // ***************************************************************************
46 // The normal Uvs format.
47 const uint8 TileUvFmtNormal1= 0;
48 const uint8 TileUvFmtNormal2= 1;
49 const uint8 TileUvFmtNormal3= 2;
50 const uint8 TileUvFmtNormal4= 3;
51 const uint8 TileUvFmtNormal5= 4;
54 // ***************************************************************************
55 const float TileSize= 128;
58 // ***************************************************************************
59 // ***************************************************************************
60 // CTileMaterial
61 // ***************************************************************************
62 // ***************************************************************************
65 // ***************************************************************************
66 CTileMaterial::CTileMaterial()
68 // By default, all pass are NULL.
69 for(uint i=0; i<NL3D_MAX_TILE_FACE; i++)
71 TileFaceVectors[i]= NULL;
76 // ***************************************************************************
77 void CTileMaterial::appendTileToEachRenderPass(uint patchNumRenderableFaces)
79 for(uint i=0;i<NL3D_MAX_TILE_PASS;i++)
81 // If RdrPass exist, add this Material Id
82 CPatchRdrPass *rdrPass= Pass[i].PatchRdrPass;
83 if(rdrPass!=NULL)
85 /* enlarge the capacity of the pass so it can renders the tile faces of this patch.
86 * NumRenderableFaces is really too big since the tile-material surely doesn't use all
87 * faces of the patch (except if same texture...)
88 * But doesn't matter. Even if all the visible Tile Surface (80m*80m) is in the same pass,
89 * it leads to only 76K final in CLandscapeGlobals::PassTriArray:
90 * 80*80(Visible surface at 80m max) /4 (2m*2m) *2(triangles) *2 (over-estimate) *3*4(triSize)=
91 * 76800
93 rdrPass->appendRdrPatchTile(i, &Pass[i], patchNumRenderableFaces);
99 // ***************************************************************************
100 // ***************************************************************************
101 // CTessVertex
102 // ***************************************************************************
103 // ***************************************************************************
106 // ***************************************************************************
107 void CTessVertex::computeGeomPos()
109 // Compute Basic ErrorMetric.
110 float sqrDist= (StartPos - CLandscapeGlobals::RefineCenter).sqrnorm();
111 float pgeom= MaxFaceSize * CLandscapeGlobals::OORefineThreshold / sqrDist;
113 // Compute ErrorMetric modified by TileNear transition, only if TileNear transition.
114 if( sqrDist< CLandscapeGlobals::TileDistFarSqr )
116 // Soft optim: do it only if necessary, ie result of max(errorMetric, errorMetricModified) is foreseeable here.
117 if(pgeom < MaxNearLimit)
119 float f= (CLandscapeGlobals::TileDistFarSqr - sqrDist) * CLandscapeGlobals::OOTileDistDeltaSqr;
120 clamp(f, 0, 1);
121 // ^4 gives better smooth result
122 f= sqr(f);
123 f= sqr(f);
124 // interpolate the errorMetric
125 pgeom= MaxNearLimit*f + pgeom*(1-f);
129 // Interpolate StartPos to EndPos, between 1 and 2.
130 if(pgeom<=1.0f)
131 Pos= StartPos;
132 else if(pgeom>=2.0f)
133 Pos= EndPos;
134 else
136 float f= pgeom - 1.0f;
137 Pos= f * (EndPos-StartPos) + StartPos;
142 // ***************************************************************************
143 // ***************************************************************************
144 // CTessFace
145 // ***************************************************************************
146 // ***************************************************************************
149 // ***************************************************************************
150 CTessFace CTessFace::CantMergeFace;
151 CTessFace CTessFace::MultipleBindFace;
154 // ***************************************************************************
155 CTessFace::CTessFace()
157 // Don't modify any of it!!
158 // Patch, SonLeft and SonRight nullity are very useful for MultiplePatch faces, and CantMergeFace.
160 Patch= NULL;
161 VBase=VLeft=VRight= NULL;
162 FBase=FLeft=FRight= NULL;
163 Father=SonLeft=SonRight= NULL;
164 Level=0;
165 ErrorMetricDate= 0;
166 // Size, Center, paramcoord undetermined.
168 TileMaterial= NULL;
169 // Very important (for split reasons). Init Tilefaces to NULL.
170 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
172 TileFaces[i]=NULL;
175 RecursMarkCanMerge=false;
176 RecursMarkForceMerge=false;
179 NL3D_PROFILE_LAND_ADD(ProfNTessFace, 1);
181 ShadowMapTriId= -1;
185 // ***************************************************************************
186 CTessFace::~CTessFace()
188 // Old Code. This is not sufficient to clear the CTessFace.
189 // Vertices and Uvs must be correctly cleared too (but difficult because of sharing).
191 Patch->getLandscape()->deleteTessFace(SonLeft);
192 Patch->getLandscape()->deleteTessFace(SonRight);
194 // update neighbors.
195 if(FBase) FBase->changeNeighbor(this, NULL);
196 if(FLeft) FLeft->changeNeighbor(this, NULL);
197 if(FRight) FRight->changeNeighbor(this, NULL);
199 FBase=FLeft=FRight= NULL;
202 NL3D_PROFILE_LAND_ADD(ProfNTessFace, -1);
204 // Ensure correclty removed from landscape ShadowMap.
205 nlassert(ShadowMapTriId== -1);
209 // ***************************************************************************
210 float CTessFace::computeNearLimit()
212 // General formula for Level, function of Size, threshold etc...:
213 // WantedLevel= log2(BaseSize / sqrdist / RefineThreshold);
214 // <=> WantedLevel= log2( CurSize*2^Level / sqrdist / RefineThreshold).
215 // <=> WantedLevel= log2( ProjectedSize* 2^Level / RefineThreshold).
216 // <=> 2^WantedLevel= ProjectedSize* 2^Level / RefineThreshold.
217 // <=> ProjectedSize= (2^WantedLevel) * RefineThreshold / (2^Level);
218 // <=> ProjectedSize= (1<<WantedLevel) * RefineThreshold / (1<<Level);
219 // UnOptimised formula: limit= (1<<Patch->TileLimitLevel) / (1<<Level);
220 nlassert(Level<=20);
221 static const uint BigValue= 1<<20;
222 static const float OOBigValue= 1.0f / BigValue;
223 return (1<<Patch->TileLimitLevel) * (OOBigValue*(BigValue>>Level));
227 // ***************************************************************************
228 void CTessFace::computeTileErrorMetric()
230 // We must take a more correct errometric here: We must have sons face which have
231 // lower projectedsize than father. This is not the case if Center of face is taken (but when not in
232 // tile mode this is nearly the case). So take the min dist from 3 points.
233 float s0= (VBase->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
234 float s1= (VLeft->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
235 float s2= (VRight->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
236 float sqrdist= minof(s0, s1, s2);
237 // It is also VERY important to take the min of 3, to ensure the split in TileMode when Far1 vertex begin
238 // to blend (see Patch::renderFar1() render).
240 // NB: VertexProgram geomorph take sqrdist= (SplitPoint - RefineCenter).sqrnorm();
241 // It's OK because geomorph will start "far" after the split.
243 if(sqrdist< CLandscapeGlobals::TileDistFarSqr)
245 float nearLimit;
246 nearLimit= CLandscapeGlobals::RefineThreshold * computeNearLimit();
247 // If we are not so subdivided.
248 if(ErrorMetric<nearLimit)
250 if(sqrdist< CLandscapeGlobals::TileDistNearSqr)
252 ErrorMetric=nearLimit;
254 else
256 // Smooth transition to the nearLimit of tesselation.
257 float f= ( CLandscapeGlobals::TileDistFarSqr - sqrdist ) * CLandscapeGlobals::OOTileDistDeltaSqr;
258 // sqr gives better result, by smoothing more the start of transition.
259 f= sqr(f);
260 f= sqr(f);
261 ErrorMetric= ErrorMetric + (nearLimit-ErrorMetric)*f;
263 // If threshold is big like 0.5, transition is still hard, and pops occurs. But The goal is
264 // 0.005 and less, so don't bother.
271 // ***************************************************************************
272 void CTessFace::updateErrorMetric()
274 // If already updated for this pass...
275 if(ErrorMetricDate>= CLandscapeGlobals::CurrentDate)
276 return;
278 CVector viewdir= SplitPoint - CLandscapeGlobals::RefineCenter;
279 float sqrdist= viewdir.sqrnorm();
281 // trivial formula.
282 //-----------------
283 ErrorMetric= Size/ sqrdist;
286 // Hoppe97 formula: k^2= a^2 * ("v-e"^2 - ((v-e).n)^2) / "v-e"^4.
287 //-----------------
288 // Can't do it because geomorph is made on Graphic card, so the simplier is the better.
291 // TileMode Impact.
292 //-----------------
293 /* TileMode Impact. We must split at least at TileLimitLevel, but only if the triangle
294 has a chance to enter in the TileDistFar sphere.
296 if( Level<Patch->TileLimitLevel && sqrdist < sqr(CLandscapeGlobals::TileDistFar+MaxDistToSplitPoint) )
298 computeTileErrorMetric();
301 ErrorMetricDate= CLandscapeGlobals::CurrentDate;
305 // ***************************************************************************
306 inline float CTessFace::computeTileEMForUpdateRefine(float distSplitPoint, float distMinFace, float nearLimit)
308 float ema;
309 // Normal ErrorMetric simulation.
310 ema= Size / sqr(distSplitPoint);
312 // TileErrorMetric simulation.
313 if(distMinFace < CLandscapeGlobals::TileDistFar)
315 // If we are not so subdivided.
316 if( ema<nearLimit )
318 if( distMinFace< CLandscapeGlobals::TileDistNear)
320 ema= nearLimit;
322 else
324 // Smooth transition to the nearLimit of tesselation.
325 float f= ( CLandscapeGlobals::TileDistFarSqr - sqr(distMinFace) ) * CLandscapeGlobals::OOTileDistDeltaSqr;
326 // sqr gives better result, by smoothing more the start of transition.
327 f= sqr(f);
328 f= sqr(f);
329 ema= ema + (nearLimit-ema)*f;
334 return ema * CLandscapeGlobals::OORefineThreshold;
338 // ***************************************************************************
339 void CTessFace::computeSplitPoint()
341 if(isRectangular())
343 // If it is a rectangular triangle, it will be splitted on the middle of VBase/VLeft.
344 // see splitRectangular() conventions.
345 // So for good geomorph compute per vertex, we must have this SplitPoint on this middle.
346 SplitPoint= (VLeft->EndPos + VBase->EndPos)/2;
348 else
350 // If it is a square triangle, it will be splitted on middle of VLeft/VRight.
351 // So for good geomorph compute per vertex, we must have this SplitPoint on this middle.
352 SplitPoint= (VLeft->EndPos + VRight->EndPos)/2;
355 // compute MaxDistToSplitPoint
356 float d0= (VBase->EndPos - SplitPoint).sqrnorm();
357 float d1= (VLeft->EndPos - SplitPoint).sqrnorm();
358 float d2= (VRight->EndPos - SplitPoint).sqrnorm();
359 MaxDistToSplitPoint= max(d0, d1);
360 MaxDistToSplitPoint= max(MaxDistToSplitPoint, d2);
361 // Get the distance.
362 MaxDistToSplitPoint= sqrtf(MaxDistToSplitPoint);
365 // ***************************************************************************
366 void CTessFace::allocTileUv(TTileUvId id)
368 // TileFaces must have been build.
369 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
371 // what src??
372 CTessVertex *vertexSrc;
373 switch(id)
375 case IdUvBase: vertexSrc= VBase; break;
376 case IdUvLeft: vertexSrc= VLeft; break;
377 case IdUvRight: vertexSrc= VRight; break;
378 default: vertexSrc = 0; nlstop; break;
381 // Do it for all possible pass
382 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
384 if(TileFaces[i])
386 CTessNearVertex *newNear= Patch->getLandscape()->newTessNearVertex();
387 newNear->Src= vertexSrc;
388 TileFaces[i]->V[id]= newNear;
389 Patch->appendNearVertexToRenderList(TileMaterial, newNear);
391 // May Allocate/Fill VB. Do it after allocTileUv, because UVs are not comuted yet.
396 // ***************************************************************************
397 void CTessFace::checkCreateFillTileVB(TTileUvId id)
399 // TileFaces must have been build.
400 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
402 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
404 if(TileFaces[i])
406 CTessNearVertex *vertNear;
407 vertNear= TileFaces[i]->V[id];
409 // May Allocate/Fill VB.
410 Patch->checkCreateVertexVBNear(vertNear);
411 Patch->checkFillVertexVBNear(vertNear);
417 // ***************************************************************************
418 void CTessFace::checkFillTileVB(TTileUvId id)
420 // TileFaces must have been build.
421 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
423 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
425 if(TileFaces[i])
427 CTessNearVertex *vertNear;
428 vertNear= TileFaces[i]->V[id];
430 // May Fill VB.
431 Patch->checkFillVertexVBNear(vertNear);
437 // ***************************************************************************
438 void CTessFace::deleteTileUv(TTileUvId id)
440 // TileFaces must still exist.
441 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
443 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
445 if(TileFaces[i])
447 CTessNearVertex *oldNear;
448 oldNear= TileFaces[i]->V[id];
449 TileFaces[i]->V[id]=NULL;
451 // May delete this vertex from VB.
452 Patch->checkDeleteVertexVBNear(oldNear);
454 Patch->removeNearVertexFromRenderList(TileMaterial, oldNear);
455 Patch->getLandscape()->deleteTessNearVertex(oldNear);
459 // ***************************************************************************
460 void CTessFace::copyTileUv(TTileUvId dstId, CTessFace *srcFace, TTileUvId srcId)
462 // TileFaces must have been build.
463 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
465 // Since this a ptr-copy, no need to add/remove the renderlist of near vertices.
467 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
469 if(TileFaces[i])
471 // The srcface should have the same tileFaces enabled.
472 nlassert(srcFace->TileFaces[i]);
474 // copy from src.
475 CTessNearVertex *copyNear;
476 copyNear= srcFace->TileFaces[i]->V[srcId];
478 // copy to dst.
479 TileFaces[i]->V[dstId]= copyNear;
483 // ***************************************************************************
484 void CTessFace::heritTileUv(CTessFace *baseFace)
486 // TileFaces must have been build.
487 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
489 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
491 if(TileFaces[i])
493 // The baseface should have the same tileFaces enabled.
494 nlassert(baseFace->TileFaces[i]);
495 // VBase should be allocated.
496 nlassert(TileFaces[i]->V[IdUvBase]);
497 TileFaces[i]->V[IdUvBase]->initMiddleUv(
498 *baseFace->TileFaces[i]->V[IdUvLeft], *baseFace->TileFaces[i]->V[IdUvRight]);
504 // ***************************************************************************
505 void CTessFace::buildTileFaces()
507 nlassert(TileMaterial);
509 // Do nothgin for lightmap pass, of course.
510 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
512 if(TileMaterial->Pass[i].PatchRdrPass)
514 TileFaces[i]= Patch->getLandscape()->newTileFace();
515 TileFaces[i]->V[IdUvBase]= NULL;
516 TileFaces[i]->V[IdUvLeft]= NULL;
517 TileFaces[i]->V[IdUvRight]= NULL;
521 // ***************************************************************************
522 void CTessFace::deleteTileFaces()
524 nlassert(TileMaterial);
526 // Do nothgin for lightmap pass, of course.
527 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
529 if(TileMaterial->Pass[i].PatchRdrPass)
531 nlassert(TileFaces[i]);
532 Patch->getLandscape()->deleteTileFace(TileFaces[i]);
533 TileFaces[i]= NULL;
535 else
537 nlassert(TileFaces[i]==NULL);
542 // ***************************************************************************
543 bool CTessFace::emptyTileFaces()
545 // Do nothgin for lightmap pass, of course.
546 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
548 // Some TileFace exist??
549 if(TileFaces[i])
550 return false;
553 return true;
558 // ***************************************************************************
559 void CTessFace::initTileUvRGBA(sint pass, bool alpha, CParamCoord pointCoord, CParamCoord middle, CUV &uv)
561 // Get good coordinate according to patch orientation.
562 uv.U= pointCoord.S<=middle.S? 0.0f: 1.0f;
563 uv.V= pointCoord.T<=middle.T? 0.0f: 1.0f;
565 // Get Tile Uv info: orientation and scale.
566 uint8 orient;
567 CVector uvScaleBias;
568 bool is256;
569 uint8 uvOff;
570 Patch->getTileUvInfo(TileId, pass, alpha, orient, uvScaleBias, is256, uvOff);
572 // Orient the UV.
573 float u= uv.U;
574 float v= uv.V;
575 // Speed rotation.
576 switch(orient)
578 case 0:
579 uv.U= u;
580 uv.V= v;
581 break;
582 case 1:
583 uv.U= 1-v;
584 uv.V= u;
585 break;
586 case 2:
587 uv.U= 1-u;
588 uv.V= 1-v;
589 break;
590 case 3:
591 uv.U= v;
592 uv.V= 1-u;
593 break;
596 // Do the 256x256.
597 if(is256)
599 uv*= 0.5;
600 if(uvOff==2 || uvOff==3)
601 uv.U+= 0.5;
602 if(uvOff==1 || uvOff==2)
603 uv.V+= 0.5;
607 // Do the HalfPixel scale bias.
608 float hBiasXY, hBiasZ;
609 if(is256)
611 hBiasXY= CLandscapeGlobals::TilePixelBias256;
612 hBiasZ = CLandscapeGlobals::TilePixelScale256;
614 else
616 hBiasXY= CLandscapeGlobals::TilePixelBias128;
617 hBiasZ = CLandscapeGlobals::TilePixelScale128;
621 // Scale the UV.
622 uv.U*= uvScaleBias.z*hBiasZ;
623 uv.V*= uvScaleBias.z*hBiasZ;
624 uv.U+= uvScaleBias.x+hBiasXY;
625 uv.V+= uvScaleBias.y+hBiasXY;
629 // ***************************************************************************
630 void CTessFace::initTileUvLightmap(CParamCoord pointCoord, CParamCoord middle, CUV &uv)
632 // Get good coordinate according to patch orientation.
633 uv.U= pointCoord.S<=middle.S? 0.0f: 1.0f;
634 uv.V= pointCoord.T<=middle.T? 0.0f: 1.0f;
636 // Get Tile Lightmap Uv info: bias and scale.
637 CVector uvScaleBias;
638 Patch->getTileLightMapUvInfo(TileMaterial->TileS, TileMaterial->TileT, uvScaleBias);
640 // Scale the UV.
641 uv.U*= uvScaleBias.z;
642 uv.V*= uvScaleBias.z;
643 uv.U+= uvScaleBias.x;
644 uv.V+= uvScaleBias.y;
648 // ***************************************************************************
649 void CTessFace::initTileUvDLM(CParamCoord pointCoord, CUV &uv)
651 // get the dlm context from the patch.
652 CPatchDLMContext *dlmCtx= Patch->_DLMContext;
653 // mmust exist at creation of the tile.
654 nlassert(dlmCtx);
656 // get coord in 0..1 range, along the patch.
657 uv.U= pointCoord.getS();
658 uv.V= pointCoord.getT();
660 // ScaleBias according to the context.
661 uv.U*= dlmCtx->DLMUScale;
662 uv.V*= dlmCtx->DLMVScale;
663 uv.U+= dlmCtx->DLMUBias;
664 uv.V+= dlmCtx->DLMVBias;
668 // ***************************************************************************
669 void CTessFace::computeTileMaterial()
671 // 0. Compute TileId.
672 //-------------------
673 // Square Order Patch assumption: assume that when a CTessFace become a tile, his base can ONLY be diagonal...
674 /* a Patch:
675 A ________
676 |\ /|
677 | \ / |
678 C|__\B_/ |
679 | / \ |
680 | / \ |
681 |/______\|
683 Here, if OrderS*OrderT=2*2, ABC is a new CTessFace of a Tile, and AB is the diagonal of the tile.
684 Hence the middle of the tile is the middle of AB.
686 C must be created, but A and B may be created or copied from neighbor.
688 CParamCoord middle(PVLeft,PVRight);
689 uint16 ts= ((uint16)middle.S * (uint16)Patch->OrderS) / 0x8000;
690 uint16 tt= ((uint16)middle.T * (uint16)Patch->OrderT) / 0x8000;
691 TileId= (uint8)(tt*Patch->OrderS + ts);
694 // 1. Compute Tile Material.
695 //--------------------------
696 // if base neighbor is already at TileLimitLevel just ptr-copy, else create the TileMaterial...
697 nlassert(!FBase || FBase->Patch!=Patch || FBase->Level<=Patch->TileLimitLevel);
698 bool copyFromBase;
699 copyFromBase= (FBase && FBase->Patch==Patch);
700 copyFromBase= copyFromBase && (FBase->Level==Patch->TileLimitLevel && FBase->TileMaterial!=NULL);
701 // NB: because of delete/recreateTileUvs(), FBase->TileMaterial may be NULL, even if face is at good TileLimitLevel.
702 if(copyFromBase)
704 TileMaterial= FBase->TileMaterial;
705 nlassert(FBase->TileId== TileId);
707 else
709 sint i;
710 TileMaterial= Patch->getLandscape()->newTileMaterial();
711 TileMaterial->TileS= uint8(ts);
712 TileMaterial->TileT= uint8(tt);
714 // Add this new material to the render list.
715 Patch->appendTileMaterialToRenderList(TileMaterial);
717 // First, get a lightmap for this tile. NB: important to do this after appendTileMaterialToRenderList(),
718 // because use TessBlocks.
719 Patch->getTileLightMap(ts, tt, TileMaterial->Pass[NL3D_TILE_PASS_LIGHTMAP].PatchRdrPass);
721 // Fill pass of multi pass material.
722 for(i=0;i<NL3D_MAX_TILE_PASS;i++)
724 // Get the correct render pass, according to the tile number, and the pass.
725 if(i!=NL3D_TILE_PASS_LIGHTMAP)
726 TileMaterial->Pass[i].PatchRdrPass= Patch->getTileRenderPass(TileId, i);
729 // Fill Pass Info.
730 for(i=0;i<NL3D_MAX_TILE_PASS;i++)
732 TileMaterial->Pass[i].TileMaterial= TileMaterial;
735 // Do not append this tile to each RenderPass, done in preRender().
739 // 2. Compute Uvs.
740 //----------------
741 // NB: TileMaterial is already setup. Useful for initTileUvLightmap() and initTileUvRGBA().
743 // First, must create The TileFaces, according to the TileMaterial passes.
744 buildTileFaces();
746 // Must allocate the Base, and insert into list.
747 allocTileUv(IdUvBase);
750 // Init LightMap UV, in RGB0 pass, UV1..
751 initTileUvLightmap(PVBase, middle, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvBase]->PUv1);
752 // Init DLM Uv, in RGB0 pass, UV2.
753 initTileUvDLM(PVBase, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvBase]->PUv2);
755 // Init UV RGBA, for all pass (but lightmap).
756 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
758 nlassert(i!=NL3D_TILE_PASS_LIGHTMAP);
759 // If pass is valid
760 if( TileMaterial->Pass[i].PatchRdrPass)
762 // Face must exist.
763 nlassert(TileFaces[i]);
764 // Compute RGB UV in UV0.
765 initTileUvRGBA(i, false, PVBase, middle, TileFaces[i]->V[IdUvBase]->PUv0);
766 // If transition tile, compute alpha UV in UV1.
767 // Do it also for Additive, because may have Transition
768 if(i== NL3D_TILE_PASS_RGB1 || i==NL3D_TILE_PASS_RGB2 || i==NL3D_TILE_PASS_ADD)
769 initTileUvRGBA(i, true, PVBase, middle, TileFaces[i]->V[IdUvBase]->PUv1);
773 // UVs are computed, may create and fill VB.
774 checkCreateFillTileVB(IdUvBase);
777 // if base neighbor is already at TileLimitLevel just ptr-copy, else create the left/right TileUvs...
778 if(copyFromBase)
780 // Just cross-copy the pointers.
781 // Make Left near vertices be the Right vertices of FBase
782 copyTileUv(IdUvLeft, FBase, IdUvRight);
783 // Make Right near vertices be the Left vertices of FBase
784 copyTileUv(IdUvRight, FBase, IdUvLeft);
786 else
788 // Must allocate the left/right uv (and insert into list).
789 allocTileUv(IdUvLeft);
790 allocTileUv(IdUvRight);
793 // Init LightMap UV, in UvPass 0, UV1..
794 initTileUvLightmap(PVLeft, middle, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvLeft]->PUv1);
795 initTileUvLightmap(PVRight, middle, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvRight]->PUv1);
796 // Init DLM Uv, in RGB0 pass, UV2.
797 initTileUvDLM(PVLeft, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvLeft]->PUv2);
798 initTileUvDLM(PVRight, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvRight]->PUv2);
800 // Init UV RGBA!
801 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
803 nlassert(i!=NL3D_TILE_PASS_LIGHTMAP);
804 // If pass is valid
805 if(TileMaterial->Pass[i].PatchRdrPass)
807 // Face must exist.
808 nlassert(TileFaces[i]);
809 // Compute RGB UV in UV0.
810 initTileUvRGBA(i, false, PVLeft, middle, TileFaces[i]->V[IdUvLeft]->PUv0);
811 initTileUvRGBA(i, false, PVRight, middle, TileFaces[i]->V[IdUvRight]->PUv0);
812 // If transition tile, compute alpha UV in UV1.
813 // Do it also for Additive, because may have Transition
814 if(i== NL3D_TILE_PASS_RGB1 || i==NL3D_TILE_PASS_RGB2 || i==NL3D_TILE_PASS_ADD)
816 initTileUvRGBA(i, true, PVLeft, middle, TileFaces[i]->V[IdUvLeft]->PUv1);
817 initTileUvRGBA(i, true, PVRight, middle, TileFaces[i]->V[IdUvRight]->PUv1);
822 // UVs are computed, may create and fill VB.
823 checkCreateFillTileVB(IdUvLeft);
824 checkCreateFillTileVB(IdUvRight);
828 // ***************************************************************************
829 void CTessFace::releaseTileMaterial()
831 // Hence, must release the tile. TileUvBase is differnet for each of leaves.
832 deleteTileUv(IdUvBase);
834 nlassert(!FBase || FBase->Level<=Patch->TileLimitLevel);
835 if(FBase && FBase->Level==Patch->TileLimitLevel && FBase->TileMaterial!=NULL)
837 // Do not release Uvs, since neighbor need it...
838 // But release faces.
839 deleteTileFaces();
840 // Do not release TileMaterial, since neighbor need it...
841 TileMaterial= NULL;
843 else
845 // release Uvs.
846 deleteTileUv(IdUvLeft);
847 deleteTileUv(IdUvRight);
849 // After, release Tile faces.
850 deleteTileFaces();
852 // Release the tile lightmap part. Do it before removeTileMaterialFromRenderList().
853 Patch->releaseTileLightMap(TileMaterial->TileS, TileMaterial->TileT);
855 // Remove this material from the render list. DO it before deletion of course :).
856 // NB: TileS/TileT still valid.
857 Patch->removeTileMaterialFromRenderList(TileMaterial);
859 Patch->getLandscape()->deleteTileMaterial(TileMaterial);
860 TileMaterial= NULL;
866 // ***************************************************************************
867 void CTessFace::updateNearFarVertices()
869 nlassert(VBase && FVBase);
870 nlassert(VLeft && FVLeft);
871 nlassert(VRight && FVRight);
873 FVBase->Src= VBase;
874 FVLeft->Src= VLeft;
875 FVRight->Src= VRight;
876 FVBase->PCoord= PVBase;
877 FVLeft->PCoord= PVLeft;
878 FVRight->PCoord= PVRight;
880 // Update VB for far vertices (if needed)
881 Patch->checkFillVertexVBFar(FVBase);
882 Patch->checkFillVertexVBFar(FVLeft);
883 Patch->checkFillVertexVBFar(FVRight);
885 // Near Vertices update (Src only).
886 for(sint i=0; i<NL3D_MAX_TILE_FACE; i++)
888 if(TileFaces[i])
890 TileFaces[i]->V[IdUvBase]->Src= VBase;
891 TileFaces[i]->V[IdUvLeft]->Src= VLeft;
892 TileFaces[i]->V[IdUvRight]->Src= VRight;
894 // Update VB for near vertices (if needed)
895 Patch->checkFillVertexVBNear(TileFaces[i]->V[IdUvBase]);
896 Patch->checkFillVertexVBNear(TileFaces[i]->V[IdUvLeft]);
897 Patch->checkFillVertexVBNear(TileFaces[i]->V[IdUvRight]);
904 // ***************************************************************************
905 void CTessFace::splitRectangular(bool propagateSplit)
907 CTessFace *f0= this;
908 CTessFace *f1= FBase;
909 // Rectangular case: FBase must exist.
910 nlassert(f1);
912 // In rectangular case, we split at the same time this and FBase (f0 and f1).
916 Tesselation is:
918 lt rt lt top rt
919 --------------------- ---------------------
920 |---- | |\ |\ |
921 | ---- f1 | | \ f1l | \ f1r |
922 | ---- | --> | \ | \ |
923 | f0 ---- | | f0r \ | f0l \ |
924 | ---| | \| \|
925 --------------------- ---------------------
926 lb rb lb bot rb
928 Why? For symetry and bind/split reasons: FBase->SonLeft->VBase is always the good vertex to take
929 (see vertex binding).
931 CParamCoord pclt= f1->PVLeft;
932 CParamCoord pclb= f0->PVBase;
933 CParamCoord pcrt= f1->PVBase;
934 CParamCoord pcrb= f1->PVRight;
935 CTessVertex *vlt= f1->VLeft;
936 CTessVertex *vlb= f0->VBase;
937 CTessVertex *vrt= f1->VBase;
938 CTessVertex *vrb= f1->VRight;
940 CTessFarVertex *farvlt= f1->FVLeft;
941 CTessFarVertex *farvlb= f0->FVBase;
942 CTessFarVertex *farvrt= f1->FVBase;
943 CTessFarVertex *farvrb= f1->FVRight;
946 // 1. create new vertices.
947 //------------------------
949 // Create splitted vertices.
950 CParamCoord pctop(f1->PVBase, f1->PVLeft);
951 CParamCoord pcbot(f0->PVBase, f0->PVLeft);
952 CTessVertex *vtop= NULL;
953 CTessVertex *vbot= NULL;
954 // Compute top.
955 if(f1->FLeft==NULL || f1->FLeft->isLeaf())
957 // The base neighbor is a leaf or NULL. So must create the new vertex.
958 vtop= Patch->getLandscape()->newTessVertex();
960 // Compute pos.
961 vtop->StartPos= (f1->VLeft->EndPos + f1->VBase->EndPos)/2;
962 vtop->EndPos= f1->Patch->computeVertex(pctop.getS(), pctop.getT());
963 // Init Pos= InitialPos. Important in the case of enforced split.
964 vtop->Pos= vtop->StartPos;
966 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
967 vtop->MaxFaceSize= f1->Size;
968 vtop->MaxNearLimit= f1->computeNearLimit();
970 else
972 // Else, get from neighbor.
973 // NB: since *FLeft is not a leaf, FBase->SonLeft!=NULL...
974 // NB: this work with both rectangular and square triangles.
975 vtop= f1->FLeft->SonLeft->VBase;
977 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
978 vtop->MaxFaceSize= max( vtop->MaxFaceSize, f1->Size);
979 vtop->MaxNearLimit= max( vtop->MaxNearLimit, f1->computeNearLimit());
981 // Compute bot.
982 if(f0->FLeft==NULL || f0->FLeft->isLeaf())
984 // The base neighbor is a leaf or NULL. So must create the new vertex.
985 vbot= Patch->getLandscape()->newTessVertex();
987 // Compute pos.
988 vbot->StartPos= (f0->VLeft->EndPos + f0->VBase->EndPos)/2;
989 vbot->EndPos= Patch->computeVertex(pcbot.getS(), pcbot.getT());
990 // Init Pos= InitialPos. Important in the case of enforced split.
991 vbot->Pos= vbot->StartPos;
993 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
994 vbot->MaxFaceSize= f0->Size;
995 vbot->MaxNearLimit= f0->computeNearLimit();
997 else
999 // Else, get from neighbor.
1000 // NB: since *FLeft is not a leaf, FBase->SonLeft!=NULL...
1001 // NB: this work with both rectangular and square triangles.
1002 vbot= f0->FLeft->SonLeft->VBase;
1004 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
1005 vbot->MaxFaceSize= max( vbot->MaxFaceSize, f0->Size);
1006 vbot->MaxNearLimit= max( vbot->MaxNearLimit, f0->computeNearLimit());
1009 // In all case, must create new FarVertices, since rect split occurs on border!!
1010 CTessFarVertex *farvtop= Patch->getLandscape()->newTessFarVertex();
1011 CTessFarVertex *farvbot= Patch->getLandscape()->newTessFarVertex();
1012 farvtop->Src= vtop;
1013 farvbot->Src= vbot;
1014 farvtop->PCoord= pctop;
1015 farvbot->PCoord= pcbot;
1016 Patch->appendFarVertexToRenderList(farvtop);
1017 Patch->appendFarVertexToRenderList(farvbot);
1018 // May Allocate/Fill VB.
1019 // NB: vtop / vbot are well computed and ready for the fill in VB.
1020 Patch->checkCreateVertexVBFar(farvtop);
1021 Patch->checkFillVertexVBFar(farvtop);
1022 Patch->checkCreateVertexVBFar(farvbot);
1023 Patch->checkFillVertexVBFar(farvbot);
1025 // For VertexProgram only, must refill the Far vertex of neighbor(s),
1026 // because MaxFaceSize, and MaxNearLimit may have change.
1027 if( CLandscapeGlobals::VertexProgramEnabled )
1029 // f0
1030 if( ! (f0->FLeft==NULL || f0->FLeft->isLeaf()) )
1031 f0->FLeft->Patch->checkFillVertexVBFar(f0->FLeft->SonLeft->FVBase);
1032 // f1
1033 if( ! (f1->FLeft==NULL || f1->FLeft->isLeaf()) )
1034 f1->FLeft->Patch->checkFillVertexVBFar(f1->FLeft->SonLeft->FVBase);
1038 // 2. Create sons, and update links.
1039 //----------------------------------
1041 CTessFace *f0l, *f0r;
1042 CTessFace *f1l, *f1r;
1044 // create and bind Sons.
1045 f0l= f0->SonLeft= Patch->getLandscape()->newTessFace();
1046 f0r= f0->SonRight= Patch->getLandscape()->newTessFace();
1047 f1l= f1->SonLeft= Patch->getLandscape()->newTessFace();
1048 f1r= f1->SonRight= Patch->getLandscape()->newTessFace();
1050 // subdivision left.
1051 f0l->Patch= f0->Patch;
1052 f0l->Father= f0;
1053 f0l->Level= f0->Level+1;
1054 f0l->Size= f0->Size*0.5f;
1055 // subdivision right.
1056 f0r->Patch= f0->Patch;
1057 f0r->Father= f0;
1058 f0r->Level= f0->Level+1;
1059 f0r->Size= f0->Size*0.5f;
1060 // subdivision left.
1061 f1l->Patch= f1->Patch;
1062 f1l->Father= f1;
1063 f1l->Level= f1->Level+1;
1064 f1l->Size= f1->Size*0.5f;
1065 // subdivision right.
1066 f1r->Patch= f1->Patch;
1067 f1r->Father= f1;
1068 f1r->Level= f1->Level+1;
1069 f1r->Size= f1->Size*0.5f;
1071 // Patch coordinates.
1072 f0r->PVRight= pclt;
1073 f0r->PVBase= pclb;
1074 f0r->PVLeft= pcbot;
1075 f1l->PVBase= pctop;
1076 f1l->PVLeft= f0r->PVRight;
1077 f1l->PVRight= f0r->PVLeft;
1079 f0l->PVRight= pctop;
1080 f0l->PVBase= pcbot;
1081 f0l->PVLeft= pcrb;
1082 f1r->PVBase= pcrt;
1083 f1r->PVLeft= f0l->PVRight;
1084 f1r->PVRight= f0l->PVLeft;
1086 // link existing vertex.
1087 f0r->VRight= vlt;
1088 f0r->VBase= vlb;
1089 f0r->VLeft= vbot;
1090 f1l->VBase= vtop;
1091 f1l->VLeft= f0r->VRight;
1092 f1l->VRight= f0r->VLeft;
1094 f0l->VRight= vtop;
1095 f0l->VBase= vbot;
1096 f0l->VLeft= vrb;
1097 f1r->VBase= vrt;
1098 f1r->VLeft= f0l->VRight;
1099 f1r->VRight= f0l->VLeft;
1101 // link Far vertices.
1102 f0r->FVRight= farvlt;
1103 f0r->FVBase= farvlb;
1104 f0r->FVLeft= farvbot;
1105 f1l->FVBase= farvtop;
1106 f1l->FVLeft= f0r->FVRight;
1107 f1l->FVRight= f0r->FVLeft;
1109 f0l->FVRight= farvtop;
1110 f0l->FVBase= farvbot;
1111 f0l->FVLeft= farvrb;
1112 f1r->FVBase= farvrt;
1113 f1r->FVLeft= f0l->FVRight;
1114 f1r->FVRight= f0l->FVLeft;
1116 // link neigbhor faces.
1117 f0r->FBase= f1l;
1118 f1l->FBase= f0r;
1119 f0l->FBase= f1r;
1120 f1r->FBase= f0l;
1121 f1l->FRight= f0l;
1122 f0l->FRight= f1l;
1123 f0r->FRight= f0->FRight;
1124 if(f0->FRight)
1125 f0->FRight->changeNeighbor(f0, f0r);
1126 f1r->FRight= f1->FRight;
1127 if(f1->FRight)
1128 f1->FRight->changeNeighbor(f1, f1r);
1129 // 4 links (all FLeft sons ) are stil invalid here.
1130 f0l->FLeft= NULL;
1131 f0r->FLeft= NULL;
1132 f1l->FLeft= NULL;
1133 f1r->FLeft= NULL;
1135 // Neigbors pointers of undetermined splitted face are not changed. Must Doesn't change this.
1136 // Used and Updated in section 5. ...
1139 // 3. Update Tile infos.
1140 //----------------------
1141 // There is no update tileinfo with rectangular patch, since tiles are always squares. (TileLimitLevel>SquareLimitLevel).
1143 // NB: but must test update of tile info for neighboring, ie 2 faces around the splits.
1144 // For Vertex program only
1145 if( CLandscapeGlobals::VertexProgramEnabled )
1147 // if neighbor face splitted, and if 2 different patchs, we must update the Tile vertices
1148 // because MaxFaceSize and MaxNearLimit may have changed.
1149 if( f0->FLeft!=NULL && !f0->FLeft->isLeaf() && f0->FLeft->Patch!=Patch )
1151 // If neighbors sons at tile level, must update their Tile vertices.
1152 if( f0->FLeft->SonLeft->Level >= f0->FLeft->Patch->TileLimitLevel )
1154 f0->FLeft->SonLeft->checkFillTileVB(IdUvBase);
1155 f0->FLeft->SonRight->checkFillTileVB(IdUvBase);
1158 // idem for f1.
1159 if( f1->FLeft!=NULL && !f1->FLeft->isLeaf() && f1->FLeft->Patch!=Patch )
1161 // If neighbors sons at tile level, must update their Tile vertices.
1162 if( f1->FLeft->SonLeft->Level >= f1->FLeft->Patch->TileLimitLevel )
1164 f1->FLeft->SonLeft->checkFillTileVB(IdUvBase);
1165 f1->FLeft->SonRight->checkFillTileVB(IdUvBase);
1171 // 4. Compute centers.
1172 //--------------------
1173 f0r->computeSplitPoint();
1174 f0l->computeSplitPoint();
1175 f1r->computeSplitPoint();
1176 f1l->computeSplitPoint();
1179 // 5. Propagate, or link sons of base.
1180 //------------------------------------
1181 for(sint i=0;i<2;i++)
1183 CTessFace *f, *fl, *fr;
1184 // TOP face.
1185 if(i==0)
1187 f= f1;
1188 fl= f1l;
1189 fr= f1r;
1191 // then BOT face.
1192 else
1194 f= f0;
1195 fl= f0l;
1196 fr= f0r;
1199 // If current face and FBase has sons, just links.
1200 if(f->FLeft==NULL)
1202 // Just update sons neighbors.
1203 fl->FLeft= NULL;
1204 fr->FLeft= NULL;
1206 else if(!f->FLeft->isLeaf())
1208 CTessFace *toLeft, *toRight;
1209 toLeft= f->FLeft->SonLeft;
1210 toRight= f->FLeft->SonRight;
1211 // Cross connection of sons.
1212 if( !f->FLeft->isRectangular() )
1214 // Case neigbhor is square.
1215 fl->FLeft= toLeft;
1216 fr->FLeft= toRight;
1217 toLeft->FRight= fl;
1218 toRight->FLeft= fr;
1220 else
1222 // Case neigbhor is rectangle.
1223 fl->FLeft= toRight;
1224 fr->FLeft= toLeft;
1225 toLeft->FLeft= fr;
1226 toRight->FLeft= fl;
1229 else if (propagateSplit)
1231 // Warning: at each iteration, the pointer of FLeft may change (because of split() which can change the neighbor
1232 // and so f).
1233 while(f->FLeft->isLeaf())
1234 f->FLeft->split();
1236 // There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.
1237 // And problems may arise because this face hasn't yet good connectivity (especially for rectangles!! :) ).
1238 nlassert(fl->isLeaf() && fr->isLeaf());
1243 // 6. Must remove father from rdr list, and insert sons.
1244 //------------------------------------------------------
1245 // UGLY REFCOUNT SIDE EFFECT: do the append first.
1246 Patch->appendFaceToRenderList(f0l);
1247 Patch->appendFaceToRenderList(f0r);
1248 Patch->appendFaceToRenderList(f1l);
1249 Patch->appendFaceToRenderList(f1r);
1250 Patch->removeFaceFromRenderList(f0);
1251 Patch->removeFaceFromRenderList(f1);
1254 // 7. Update priority list.
1255 //------------------------------------------------------
1256 // Since we are freshly splitted, unlink from any list, and link to the MergePriorityList, because must look
1257 // now when should merge.
1258 Patch->getLandscape()->_MergePriorityList.insert(0, 0, f0);
1259 Patch->getLandscape()->_MergePriorityList.insert(0, 0, f1);
1261 // Since we are split, no need to test father for merge, because it cannot!
1262 if(f0->Father)
1264 // remove father from any priority list.
1265 f0->Father->unlinkInPList();
1267 if(f1->Father)
1269 // remove father from any priority list.
1270 f1->Father->unlinkInPList();
1276 // ***************************************************************************
1277 void CTessFace::split(bool propagateSplit)
1280 // 0. Some easy ending.
1281 //---------------------
1282 // Already splitted??
1283 if(!isLeaf())
1284 return;
1285 // Don't do this!!!
1286 //if(Level>=LS_MAXLEVEL)
1287 // return;
1288 // since split() may reach LS_MAXLEVEL, but enforce splits which outpass this stage!!
1290 NL3D_PROFILE_LAND_ADD(ProfNSplits, 1);
1293 // Special Rectangular case.
1294 if(isRectangular())
1296 splitRectangular(propagateSplit);
1297 return;
1300 // 1. Create sons, and update links.
1301 //----------------------------------
1303 // create and bind Sons.
1304 SonLeft= Patch->getLandscape()->newTessFace();
1305 SonRight= Patch->getLandscape()->newTessFace();
1307 // subdivision left.
1308 SonLeft->Patch= Patch;
1309 SonLeft->Father= this;
1310 SonLeft->Level= Level+1;
1311 SonLeft->Size= Size*0.5f;
1312 // subdivision right.
1313 SonRight->Patch= Patch;
1314 SonRight->Father= this;
1315 SonRight->Level= Level+1;
1316 SonRight->Size= Size*0.5f;
1319 // link Left Son.
1320 // link neighbor face.
1321 SonLeft->FBase= FLeft;
1322 if(FLeft) FLeft->changeNeighbor(this, SonLeft);
1323 SonLeft->FLeft= SonRight;
1324 SonLeft->FRight= NULL; // Temporary. updated later.
1325 // link neighbor vertex.
1326 SonLeft->VLeft= VBase;
1327 SonLeft->VRight= VLeft;
1328 // link neighbor Far vertex.
1329 SonLeft->FVLeft= FVBase;
1330 SonLeft->FVRight= FVLeft;
1331 // Patch coordinates.
1332 SonLeft->PVBase= CParamCoord(PVLeft, PVRight);
1333 SonLeft->PVLeft= PVBase;
1334 SonLeft->PVRight= PVLeft;
1336 // linkRight Son.
1337 // link neighbor face.
1338 SonRight->FBase= FRight;
1339 if(FRight) FRight->changeNeighbor(this, SonRight);
1340 SonRight->FLeft= NULL; // Temporary. updated later.
1341 SonRight->FRight= SonLeft;
1342 // link neighbor vertex.
1343 SonRight->VLeft= VRight;
1344 SonRight->VRight= VBase;
1345 // link neighbor Far vertex.
1346 SonRight->FVLeft= FVRight;
1347 SonRight->FVRight= FVBase;
1348 // Patch coordinates.
1349 SonRight->PVBase= CParamCoord(PVLeft, PVRight);
1350 SonRight->PVLeft= PVRight;
1351 SonRight->PVRight= PVBase;
1354 // FBase->FBase==this. Must Doesn't change this. Used and Updated in section 5. ...
1357 // 2. Update/Create Vertex infos.
1358 //-------------------------------
1360 // Must create/link *->VBase.
1361 if(FBase==NULL || FBase->isLeaf())
1363 // The base neighbor is a leaf or NULL. So must create the new vertex.
1364 CTessVertex *newVertex= Patch->getLandscape()->newTessVertex();
1365 SonRight->VBase= newVertex;
1366 SonLeft->VBase= newVertex;
1368 // Compute pos.
1369 newVertex->StartPos= (VLeft->EndPos + VRight->EndPos)/2;
1370 newVertex->EndPos= Patch->computeVertex(SonLeft->PVBase.getS(), SonLeft->PVBase.getT());
1372 // Init Pos= InitialPos. Important in the case of enforced split.
1373 newVertex->Pos= newVertex->StartPos;
1375 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
1376 newVertex->MaxFaceSize= Size;
1377 newVertex->MaxNearLimit= computeNearLimit();
1379 else
1381 // Else, get from neighbor.
1382 // NB: since *FBase is not a leaf, FBase->SonLeft!=NULL...
1383 // NB: this work with both rectangular and square triangles (see splitRectangular()).
1384 SonRight->VBase= FBase->SonLeft->VBase;
1385 SonLeft->VBase= FBase->SonLeft->VBase;
1387 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
1388 SonLeft->VBase->MaxFaceSize= max( SonLeft->VBase->MaxFaceSize, Size);
1389 SonLeft->VBase->MaxNearLimit= max( SonLeft->VBase->MaxNearLimit, computeNearLimit());
1393 // Must create/link *->FVBase.
1394 // HERE, we must create a FarVertex too if the neighbor is not of the same patch as me.
1395 if(FBase==NULL || FBase->isLeaf() || FBase->Patch!=Patch)
1397 // The base neighbor is a leaf or NULL. So must create the new far vertex.
1398 CTessFarVertex *newFar= Patch->getLandscape()->newTessFarVertex();
1399 SonRight->FVBase= newFar;
1400 SonLeft->FVBase= newFar;
1402 // Compute.
1403 newFar->Src= SonLeft->VBase;
1404 newFar->PCoord= SonLeft->PVBase;
1406 // Append.
1407 Patch->appendFarVertexToRenderList(newFar);
1409 // May Allocate/Fill VB.
1410 // NB: SonLeft->VBase->Pos is well computed and ready for the fill in VB.
1411 Patch->checkCreateVertexVBFar(newFar);
1412 Patch->checkFillVertexVBFar(newFar);
1414 // For VertexProgram only, must refill the Far vertex of neighbor,
1415 // because MaxFaceSize, and MaxNearLimit may have change.
1416 if( CLandscapeGlobals::VertexProgramEnabled && ! (FBase==NULL || FBase->isLeaf()) )
1417 FBase->Patch->checkFillVertexVBFar(FBase->SonLeft->FVBase);
1419 else
1421 // Else, get from neighbor.
1422 // NB: since *FBase is not a leaf, FBase->SonLeft!=NULL...
1423 // NB: this work with both rectangular and square triangles (see splitRectangular()).
1424 SonRight->FVBase= FBase->SonLeft->FVBase;
1425 SonLeft->FVBase= FBase->SonLeft->FVBase;
1427 // NB For VertexProgram only: no need to refill the Far vertex of neighbor, because neighbor is of same Patch
1428 // So MaxNearLimit and MaxFaceSize should be the same.
1432 // 3. Update Tile infos.
1433 //----------------------
1434 // NB: must do it before appendFaceToRenderList().
1435 // NB: must do it after compute of SonLeft->VBase->Pos for good filling in VBuffer.
1436 // There is no problem with rectangular patch, since tiles are always squares.
1437 // If new tile ....
1438 if(SonLeft->Level==Patch->TileLimitLevel)
1440 SonLeft->computeTileMaterial();
1441 SonRight->computeTileMaterial();
1443 // else Tile herit.
1444 else if(SonLeft->Level > Patch->TileLimitLevel)
1446 heritTileMaterial();
1449 // For Vertex program only
1450 if( CLandscapeGlobals::VertexProgramEnabled )
1452 // if neighbor face splitted, and if 2 different patchs, we must update the Tile vertices
1453 // because MaxFaceSize and MaxNearLimit may have changed.
1454 if( FBase!=NULL && !FBase->isLeaf() && FBase->Patch!=Patch )
1456 // If neighbors sons at tile level, must update their Tile vertices.
1457 if( FBase->SonLeft->Level >= FBase->Patch->TileLimitLevel )
1459 FBase->SonLeft->checkFillTileVB(IdUvBase);
1460 FBase->SonRight->checkFillTileVB(IdUvBase);
1466 // 4. Compute centers.
1467 //--------------------
1468 SonRight->computeSplitPoint();
1469 SonLeft->computeSplitPoint();
1472 // 5. Propagate, or link sons of base.
1473 //------------------------------------
1474 // If current face and FBase has sons, just links.
1475 if(FBase==NULL)
1477 // Just update sons neighbors.
1478 SonLeft->FRight= NULL;
1479 SonRight->FLeft= NULL;
1481 else if(!FBase->isLeaf())
1483 CTessFace *toLeft, *toRight;
1484 CTessFace *fl, *fr;
1485 fl= SonLeft;
1486 fr= SonRight;
1487 toLeft= FBase->SonLeft;
1488 toRight= FBase->SonRight;
1489 // Cross connection of sons.
1490 if(!FBase->isRectangular())
1492 // Case neigbhor is square.
1493 fl->FRight= toRight;
1494 fr->FLeft= toLeft;
1495 toLeft->FRight= fr;
1496 toRight->FLeft= fl;
1498 else
1500 // Case neigbhor is rectangular.
1501 fl->FRight= toLeft;
1502 fr->FLeft= toRight;
1503 toLeft->FLeft= fl;
1504 toRight->FLeft= fr;
1507 else if (propagateSplit)
1509 // Warning: at each iteration, the pointer of FBase may change (because of split() which can change the neighbor
1510 // and so "this").
1511 while(FBase->isLeaf())
1512 FBase->split();
1514 // There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.
1515 // And problems may arise because this face hasn't yet good connectivity.
1516 nlassert(SonLeft->isLeaf() && SonRight->isLeaf());
1520 // 6. Must remove father from rdr list, and insert sons.
1521 //------------------------------------------------------
1522 // UGLY REFCOUNT SIDE EFFECT: do the append first.
1523 Patch->appendFaceToRenderList(SonLeft);
1524 Patch->appendFaceToRenderList(SonRight);
1525 Patch->removeFaceFromRenderList(this);
1528 // 7. Update priority list.
1529 //------------------------------------------------------
1530 // Since we are freshly splitted, unlink from any list, and link to the MergePriorityList, because must look
1531 // now when should merge.
1532 Patch->getLandscape()->_MergePriorityList.insert(0, 0, this);
1534 // Since we are split, no need to test father for merge, because it cannot!
1535 if(Father)
1537 // remove father from any priority list.
1538 Father->unlinkInPList();
1542 // ***************************************************************************
1543 bool CTessFace::canMerge(bool testEm)
1545 if(this== &CantMergeFace)
1546 return false;
1548 nlassert(!isLeaf());
1550 // Test diamond config (sons must be leaves).
1551 if(!SonLeft->isLeaf())
1552 return false;
1553 if(!SonRight->isLeaf())
1554 return false;
1555 // If Errormetric must be considered for this test.
1556 if(testEm)
1558 updateErrorMetric();
1559 float ps2= ErrorMetric;
1560 ps2*= CLandscapeGlobals::OORefineThreshold;
1561 if(ps2>=1.0f)
1562 return false;
1565 // Then test neighbors.
1566 RecursMarkCanMerge= true;
1567 bool ok= true;
1568 if(!isRectangular())
1570 if(FBase && !FBase->RecursMarkCanMerge)
1572 if(!FBase->canMerge(testEm))
1573 ok= false;
1576 else
1578 // Rectangular case. May have a longer propagation...
1579 if(FBase && !FBase->RecursMarkCanMerge)
1581 if(!FBase->canMerge(testEm))
1582 ok= false;
1584 if(ok && FLeft && !FLeft->RecursMarkCanMerge)
1586 if(!FLeft->canMerge(testEm))
1587 ok= false;
1590 // Must not return false in preceding tests, because must set RecursMarkCanMerge to false.
1591 RecursMarkCanMerge= false;
1593 return ok;
1597 // ***************************************************************************
1598 void CTessFace::doMerge()
1600 // Assume that canMerge() return true.
1601 // And Assume that !isLeaf().
1602 nlassert(!isLeaf());
1604 if(!isRectangular())
1606 // 1. Let's merge vertex.
1607 //-----------------------
1608 // Delete vertex, only if not already done by the neighbor (ie neighbor not already merged to a leaf).
1609 // NB: this work even if neigbor is rectnagular.
1610 if(!FBase || !FBase->isLeaf())
1611 Patch->getLandscape()->deleteTessVertex(SonLeft->VBase);
1613 // Delete Far Vertex. Idem, but test too if != patch...
1614 if(!FBase || !FBase->isLeaf() || FBase->Patch!=Patch)
1616 // May delete this vertex from VB.
1617 Patch->checkDeleteVertexVBFar(SonLeft->FVBase);
1619 Patch->removeFarVertexFromRenderList(SonLeft->FVBase);
1620 Patch->getLandscape()->deleteTessFarVertex(SonLeft->FVBase);
1624 // 2. Must remove sons from rdr list, and insert father.
1625 //------------------------------------------------------
1626 // Must do it BEFORE the TileFaces are released.
1627 // UGLY REFCOUNT SIDE EFFECT: do the append first.
1628 Patch->appendFaceToRenderList(this);
1629 Patch->removeFaceFromRenderList(SonLeft);
1630 Patch->removeFaceFromRenderList(SonRight);
1633 // 3. Let's merge Uv.
1634 //-------------------
1635 // Delete Uv.
1636 // Must do it for this and FBase separately, since they may not have same tile level (if != patch).
1637 if(SonLeft->Level== Patch->TileLimitLevel)
1639 // Square patch assumption: the sons are not of the same TileId/Patch.
1640 nlassert(!sameTile(SonLeft, SonRight));
1641 // release tiles: NearVertices, TileFaces, and TileMaterial.
1642 SonLeft->releaseTileMaterial();
1643 SonRight->releaseTileMaterial();
1645 else if(SonLeft->Level > Patch->TileLimitLevel)
1647 // Delete Uv, only if not already done by the neighbor (ie neighbor not already merged to a leaf).
1648 // But Always delete if neighbor exist and has not same tile as me.
1649 // NB: this work with rectangular neigbor patch, since sameTile() will return false if different patch.
1650 if(!FBase || !FBase->isLeaf() || !sameTile(this, FBase))
1652 SonLeft->deleteTileUv(IdUvBase);
1654 // In all case, must delete the tilefaces of those face.
1655 SonLeft->deleteTileFaces();
1656 SonRight->deleteTileFaces();
1660 // 4. Let's merge Face.
1661 //-------------------
1662 // Change father 's neighbor pointers.
1663 FLeft= SonLeft->FBase;
1664 if(FLeft) FLeft->changeNeighbor(SonLeft, this);
1665 FRight= SonRight->FBase;
1666 if(FRight) FRight->changeNeighbor(SonRight, this);
1667 // delete sons.
1668 Patch->getLandscape()->deleteTessFace(SonLeft);
1669 Patch->getLandscape()->deleteTessFace(SonRight);
1670 SonLeft=NULL;
1671 SonRight=NULL;
1673 // If not already done, merge the neighbor.
1674 if(FBase!=NULL && !FBase->isLeaf())
1676 FBase->doMerge();
1680 else
1682 // Rectangular case.
1683 // Since minimum Order is 2, Sons of rectangular face are NEVER at TileLimitLevel. => no Uv merge to do.
1684 nlassert(SonLeft->Level< Patch->TileLimitLevel);
1685 nlassert(FBase);
1687 // 1. Let's merge vertex.
1688 //-----------------------
1689 // Delete vertex, only if not already done by the neighbor (ie neighbor not already merged to a leaf).
1690 // NB: this work even if neigbor is rectangular (see tesselation rules in splitRectangular()).
1691 if(!FLeft || !FLeft->isLeaf())
1692 Patch->getLandscape()->deleteTessVertex(SonLeft->VBase);
1694 // Delete Far Vertex. Rect patch: neightb must be of a != pathc as me => must delete FarVertex.
1695 nlassert(!FLeft || FLeft->Patch!=Patch);
1696 // May delete this vertex from VB.
1697 Patch->checkDeleteVertexVBFar(SonLeft->FVBase);
1699 Patch->removeFarVertexFromRenderList(SonLeft->FVBase);
1700 Patch->getLandscape()->deleteTessFarVertex(SonLeft->FVBase);
1703 // 2. Must remove sons from rdr list, and insert father.
1704 //------------------------------------------------------
1705 // UGLY REFCOUNT SIDE EFFECT: do the append first.
1706 Patch->appendFaceToRenderList(this);
1707 Patch->removeFaceFromRenderList(SonLeft);
1708 Patch->removeFaceFromRenderList(SonRight);
1711 // 3. Let's merge Face.
1712 //-------------------
1713 // Change father 's neighbor pointers (see splitRectangular()).
1714 FRight= SonRight->FRight;
1715 if(FRight) FRight->changeNeighbor(SonRight, this);
1716 // delete sons.
1717 Patch->getLandscape()->deleteTessFace(SonLeft);
1718 Patch->getLandscape()->deleteTessFace(SonRight);
1719 SonLeft=NULL;
1720 SonRight=NULL;
1722 // First, do it for my rectangular co-worker FBase (if not already done).
1723 if(!FBase->isLeaf())
1725 FBase->doMerge();
1727 // If not already done, merge the neighbor.
1728 if(FLeft!=NULL && !FLeft->isLeaf())
1730 FLeft->doMerge();
1735 // Update priority list.
1736 //------------------------------------------------------
1737 // Since we are freshly merged, unlink from any list, and link to the SplitPriorityList, because must look
1738 // now when we should split again.
1739 Patch->getLandscape()->_SplitPriorityList.insert(0, 0, this);
1741 // since we are now merged maybe re-insert father in priority list.
1742 if(Father)
1744 nlassert(!Father->isLeaf());
1745 // If sons of father are both leaves (ie this, and the other (complexe case if rectangle) )
1746 if( Father->SonLeft->isLeaf() && Father->SonRight->isLeaf() )
1748 Patch->getLandscape()->_MergePriorityList.insert(0, 0, Father);
1755 // ***************************************************************************
1756 bool CTessFace::merge()
1758 // Must not be a leaf.
1759 nlassert(!isLeaf());
1761 // 0. Verify if merge is posible.
1762 //----------------------------
1763 if(!canMerge(false))
1764 return false;
1766 NL3D_PROFILE_LAND_ADD(ProfNMerges, 1);
1768 // 1. Let's merge the face.
1769 //-----------------------
1770 // Propagation is done in doMerge().
1771 doMerge();
1773 return true;
1776 // ***************************************************************************
1777 void CTessFace::refineAll()
1779 NL3D_PROFILE_LAND_ADD(ProfNRefineFaces, 1);
1780 NL3D_PROFILE_LAND_ADD(ProfNRefineLeaves, isLeaf()?1:0);
1783 if(ps<RefineThreshold), the face must be merged (ie have no leaves).
1784 if(ps E [RefineThreshold, RefineThreshold*2]), the face must be splitted (ave leaves), and is geomorphed.
1785 if(ps>RefineThreshold*2), the face is fully splitted/geomoprhed (tests reported on sons...).
1788 // Test for Split or merge.
1789 //-----------------------
1791 NL3D_PROFILE_LAND_ADD(ProfNRefineComputeFaces, 1);
1793 updateErrorMetric();
1794 float ps=ErrorMetric;
1795 ps*= CLandscapeGlobals::OORefineThreshold;
1796 // 1.0f is the point of split().
1797 // 2.0f is the end of geomorph.
1800 // Test split/merge.
1801 //---------------------
1802 // If wanted, not already done, and limit not reached, split().
1803 if(isLeaf())
1805 if(ps>1.0f && Level< (Patch->TileLimitLevel + CLandscapeGlobals::TileMaxSubdivision) )
1806 split();
1808 else
1810 // Else, if splitted, must merge (if not already the case).
1811 if(ps<1.0f)
1813 // Merge only if agree, and neighbors agree.
1814 // canMerge() test all the good thing: FBase==CantMergeFace, or this is rectangular etc...
1815 // The test is propagated to neighbors.
1816 if(canMerge(true))
1818 merge();
1824 // Recurs.
1825 //-----------------------
1826 if(SonLeft)
1828 SonLeft->refineAll();
1829 SonRight->refineAll();
1835 // ***************************************************************************
1836 // Some updateRefine***() Doc:
1838 // Split or merge, and meaning of errorMetric:
1840 if(errorMetric<RefineThreshold), the face must be merged (ie have no leaves).
1841 if(errorMetric E [RefineThreshold, RefineThreshold*2]), the face must be splitted (ave leaves), and is geomorphed.
1842 if(errorMetric>RefineThreshold*2), the face is fully splitted/geomoprhed.
1846 // Compute distNormalSplitMerge: distance from refineCenter to normal split/merge (ie without tile transition):
1848 normal ErrorMetric formula is:
1849 em = Size*OORefineThreshold/ dist^2; with dist == (SplitPoint - CLandscapeGlobals::RefineCenter).norm()
1850 So inverse this function and we have:
1851 dist= sqrt(Size*OORefineThreshold/em).
1852 Split or merge is when em==1, so
1853 distSplitMerge= sqrt(Size*OORefineThreshold)
1857 // Compute distTileTransSplitMerge.
1858 /* When we are sure that CLandscapeGlobals::TileDistNear < distMinFace < CLandscapeGlobals::TileDistFar,
1859 the clamp in the original formula is skipped
1861 So the TileErrorMetric formula is:
1864 ema= Sife*OORefineThreshold / distSP^2.
1865 f= (TileDistFar^2 - distMinFace^2) * OOTileDeltaDist^2
1866 f= f ^ 4. // no clamp. see above.
1867 emb= NL*f + ema*(1-f)
1868 emFinal= max(ema, emb).
1871 The problem is that the formula is too complex (degree 8 equation).
1872 So search for the result recursively.
1876 // Quadrant Selection
1878 Quadrant/Direction is interesting for updateRefineSplit() only.
1879 In the 2 most simples cases, the action we want is "Know when we enters in a bounding volume"
1880 This fit well for Quadrant notion.
1882 In the case "TileDistNear to TileDistFar", the rule is too complicated and there is also
1883 the notion of "Know when we LEAVE the TileDistFar sphere around the face" which is incompatible
1884 with Quadrant behavior (since can go in any direction to leave the sphere).
1886 updateRefineMerge() are at least all notion of "Know when we LEAVE the SplitSphere around the SplitPoint"
1887 which is incompatible with Quadrant behavior.
1888 This is why updateRefineMerge() don't bother at all quadrant, and so the _MergePriorityList is inited with 0
1889 quadrants.
1893 // ***************************************************************************
1894 void CTessFace::updateRefineSplit()
1896 NL3D_PROFILE_LAND_ADD(ProfNRefineFaces, 1);
1898 nlassert(Patch);
1899 // The face must be not splitted, because tested for split.
1900 nlassert(isLeaf());
1903 NB: see above for some updateRefine*** doc.
1906 // Test for Split.
1907 //-----------------------
1908 bool splitted= false;
1910 updateErrorMetric();
1911 float ps=ErrorMetric;
1912 ps*= CLandscapeGlobals::OORefineThreshold;
1913 // 1.0f is the point of split().
1914 // 2.0f is the end of geomorph.
1917 // Test split.
1918 //---------------------
1919 // If wanted and limit not reached, split().
1920 if(ps>1.0f && Level< (Patch->TileLimitLevel + CLandscapeGlobals::TileMaxSubdivision) )
1922 split();
1924 // if split ok
1925 if(!isLeaf())
1927 splitted= true;
1933 // Insert the face in the priority list.
1934 //-----------------------
1935 // If splitted, then insertion in Landscape->MergePriorityList at 0 has been done. so nothing to update.
1936 // Else, must compute when whe should re-test.
1937 if(!splitted)
1939 // the face is not splitted here.
1940 nlassert(isLeaf());
1942 float minDeltaDistToUpdate;
1944 // by default insert in the quadrant-less rolling table.
1945 uint quadrantId= 0;
1948 CVector dirToSplitPoint= SplitPoint - CLandscapeGlobals::RefineCenter;
1949 // The distance of SplitPoint to center.
1950 float distSplitPoint= dirToSplitPoint.norm();
1951 // The distance where we should split/merge. see updateRefin() doc.
1952 float distNormalSplitMerge= (float)sqrt(Size*CLandscapeGlobals::OORefineThreshold);
1955 // If the face is at its max subdivision
1956 if(Level>=Patch->TileLimitLevel+CLandscapeGlobals::TileMaxSubdivision)
1958 // special case: the face do not need to be tested for splitting, because Max subdivision reached.
1959 // Hence just unlink from any list, and return.
1960 unlinkInPList();
1961 return;
1963 else if(Level>=Patch->TileLimitLevel)
1965 // Always normal ErrorMetric. Because Faces at Tile level decide to split or merge their sons independently
1966 // of "Tile ErrorMetric".
1968 // The test is "when do we enter in the Split area?", so we can use Quadrant PriorityList
1969 quadrantId= Patch->getLandscape()->_SplitPriorityList.selectQuadrant(dirToSplitPoint);
1971 // compute distance to split as default "No Quadrant"
1972 minDeltaDistToUpdate= distSplitPoint - distNormalSplitMerge;
1974 // If a quadrant is selected, try to use it
1975 if(quadrantId>0)
1977 const CVector &quadrantDir= Patch->getLandscape()->_SplitPriorityList.getQuadrantDirection(quadrantId);
1979 // We must not approach the SplitPoint at distNormalSplitMerge
1980 float dMin= quadrantDir*dirToSplitPoint - distNormalSplitMerge;
1982 // If the dist with quadrant is too small then use the std way (without quadrant).
1983 if( dMin<NL3D_TESS_USE_QUADRANT_THRESHOLD )
1984 quadrantId= 0;
1985 // else ok, use quadrant behavior
1986 else
1987 minDeltaDistToUpdate= dMin;
1990 else
1992 // Compute Distance of the face from RefineCenter. It is the min of the 3 points, as in computeTileErrorMetric().
1993 CVector dirToV0= VBase->EndPos - CLandscapeGlobals::RefineCenter;
1994 CVector dirToV1= VLeft->EndPos - CLandscapeGlobals::RefineCenter;
1995 CVector dirToV2= VRight->EndPos - CLandscapeGlobals::RefineCenter;
1996 float s0= dirToV0.sqrnorm();
1997 float s1= dirToV1.sqrnorm();
1998 float s2= dirToV2.sqrnorm();
1999 float distMinFace= (float)sqrt( minof(s0, s1, s2) );
2001 // compute the delta distance to the normal split point. See above for doc.
2002 float normalEMDeltaDist;
2003 normalEMDeltaDist= distSplitPoint - distNormalSplitMerge;
2007 There is 3 possibles cases, according to level, and the distances minFaceDist:
2009 /// TileDistFar to +oo.
2010 if( distMinFace > CLandscapeGlobals::TileDistFar )
2012 // The test is "when do we enter in the Split area OR in TileDistFar area?", so we can use Quadrant PriorityList
2013 quadrantId= Patch->getLandscape()->_SplitPriorityList.selectQuadrant(dirToSplitPoint);
2015 // compute deltaDist as default "Direction less quadrant"
2016 minDeltaDistToUpdate= normalEMDeltaDist;
2017 // We must know when we enter in TileErrorMetric zone, because the computing is different.
2018 minDeltaDistToUpdate= min(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistFar);
2020 // try with quadrant if > 0.
2021 if(quadrantId>0)
2023 const CVector &quadrantDir= Patch->getLandscape()->_SplitPriorityList.getQuadrantDirection(quadrantId);
2025 // We must not approach the SplitPoint at distNormalSplitMerge
2026 float dMin= quadrantDir*dirToSplitPoint - distNormalSplitMerge;
2027 // and we must not reach one of the 3 sphere (Vi, TileDistFar).
2028 float d0 = quadrantDir*dirToV0 - CLandscapeGlobals::TileDistFar;
2029 float d1 = quadrantDir*dirToV1 - CLandscapeGlobals::TileDistFar;
2030 float d2 = quadrantDir*dirToV2 - CLandscapeGlobals::TileDistFar;
2031 // take min dist
2032 dMin= minof(dMin, d0, d1, d2);
2034 // If the dist with quadrant is too small then use the std way (without quadrant).
2035 if( dMin<NL3D_TESS_USE_QUADRANT_THRESHOLD )
2036 quadrantId= 0;
2037 // else ok, use quadrant behavior
2038 else
2039 minDeltaDistToUpdate= dMin;
2042 /// TileDistNear to TileDistFar.
2043 else if( distMinFace > CLandscapeGlobals::TileDistNear )
2045 // NB: can't use quadrant behavior here. Leave quadrantId at 0.
2047 // Profile
2048 NL3D_PROFILE_LAND_ADD(ProfNRefineInTileTransition, 1);
2050 // Compute distance to split/Merge in TileTransition
2051 float distTileTransSplitMerge;
2052 float maxDeltaDist= 8;
2053 float minDeltaDist= 0;
2054 uint nbRecurs= 6;
2055 float nearLimit;
2056 nearLimit= CLandscapeGlobals::RefineThreshold * computeNearLimit();
2057 // search the distance to split recursively.
2058 for(uint i=0; i< nbRecurs; i++)
2060 float pivotDeltaDist= (maxDeltaDist-minDeltaDist)/2;
2061 // If the em computed with this distance is still <1 (ie merged), then we can move further.
2062 if ( computeTileEMForUpdateRefine(distSplitPoint-pivotDeltaDist, distMinFace-pivotDeltaDist, nearLimit ) < 1)
2063 minDeltaDist= pivotDeltaDist;
2064 // else we must move not as far
2065 else
2066 maxDeltaDist= pivotDeltaDist;
2068 // And so take the minimum resulting delta distance
2069 distTileTransSplitMerge= minDeltaDist;
2071 // take the min with distance of distMinFace to the TileDistNear and TileDistFar sphere, because formula change at
2072 // those limits.
2073 minDeltaDistToUpdate= min(distTileTransSplitMerge, CLandscapeGlobals::TileDistFar - distMinFace );
2074 minDeltaDistToUpdate= min(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistNear);
2076 /// 0 to TileDistNear.
2077 else
2079 // because the face is not a Tile Level (ie Level<Patch->TileLimitLevel), it should be splitted,
2080 // and won't merge until reaching at least the TileDistNear sphere.
2081 // if not splited (should not arise), force the split next time.
2082 minDeltaDistToUpdate= 0;
2087 // Profile.
2088 if(minDeltaDistToUpdate<0.0625)
2090 NL3D_PROFILE_LAND_ADD(ProfNRefineWithLowDistance, 1);
2094 // insert in the Split priority list.
2095 // Until the RefineCenter move under minDeltaDistToUpdate, we don't need to test face.
2096 Patch->getLandscape()->_SplitPriorityList.insert(quadrantId, minDeltaDistToUpdate, this);
2101 // ***************************************************************************
2102 void CTessFace::updateRefineMerge()
2104 NL3D_PROFILE_LAND_ADD(ProfNRefineFaces, 1);
2106 nlassert(Patch);
2107 // The face must be splitted, because tested for merge.
2108 nlassert(!isLeaf());
2111 NB: see above for some updateRefine*** doc.
2114 // Test for merge.
2115 //-----------------------
2116 bool merged= false;
2118 updateErrorMetric();
2119 float ps=ErrorMetric;
2120 ps*= CLandscapeGlobals::OORefineThreshold;
2121 // 1.0f is the point of split().
2122 // 2.0f is the end of geomorph.
2125 // Test merge.
2126 //---------------------
2127 // Else, must merge ??
2128 if(ps<1.0f)
2130 // Merge only if agree, and neighbors agree.
2131 // canMerge() test all the good thing: FBase==CantMergeFace, or this is rectangular etc...
2132 // The test is propagated to neighbors.
2133 if(canMerge(true))
2135 merge();
2137 // NB: here, merge() is not propagated to fathers (supposed to be not very useful).
2139 if(isLeaf())
2141 merged= true;
2148 // Insert the face in the priority list.
2149 //-----------------------
2150 // If merged, then insertion in Landscape->SplitPriorityList at 0 has been done. so nothing to update.
2151 // Else, must compute when whe should re-test.
2152 if(!merged)
2154 // the face is splitted here.
2155 nlassert(!isLeaf());
2157 float minDeltaDistToUpdate;
2160 // The distance of SplitPoint to center.
2161 float distSplitPoint= (SplitPoint - CLandscapeGlobals::RefineCenter).norm();
2162 // Compute distance from refineCenter to normal split/merge (ie without tile transition).
2163 float distNormalSplitMerge= (float)sqrt(Size*CLandscapeGlobals::OORefineThreshold);
2166 // If the face is at its max subdivision
2167 if(Level>=Patch->TileLimitLevel+CLandscapeGlobals::TileMaxSubdivision)
2169 // since the face is splitted, then must test always this face, because we must merge it (as soon as it is possible).
2170 minDeltaDistToUpdate= 0;
2172 else if(Level>=Patch->TileLimitLevel)
2174 // Always normal ErrorMetric. Because Faces at Tile level decide to split or merge their sons independently
2175 // of "Tile ErrorMetric".
2176 // since splitted, compute distance to merge.
2177 minDeltaDistToUpdate= distNormalSplitMerge - distSplitPoint;
2178 // NB: it is possible that minDeltaDistToUpdate<0. A good example is when we are enforced split.
2179 // Then, distSplitMerge may be < distSplitPoint, meaning we should have not split, but a neigbhor has enforced us.
2180 // So now, must test every frame if we can merge....
2181 minDeltaDistToUpdate= max( 0.f, minDeltaDistToUpdate );
2183 else
2185 // Compute Distance of the face from RefineCenter. It is the min of the 3 points, as in computeTileErrorMetric().
2186 float s0= (VBase->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
2187 float s1= (VLeft->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
2188 float s2= (VRight->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
2189 float distMinFace= (float)sqrt( minof(s0, s1, s2) );
2191 // compute the delta distance to the normal split point. See above for doc.
2192 float normalEMDeltaDist;
2193 normalEMDeltaDist= distNormalSplitMerge - distSplitPoint;
2194 normalEMDeltaDist= max( 0.f, normalEMDeltaDist );
2198 There is 3 possibles cases, according to level, and the distances minFaceDist:
2200 /// TileDistFar to +oo.
2201 if( distMinFace > CLandscapeGlobals::TileDistFar )
2203 // normal geomorph. Any face compute the distance to the SplitPoint, and take min with distance to
2204 // the TileDistFar sphere.
2205 minDeltaDistToUpdate= normalEMDeltaDist;
2207 // We must know when we enter in TileErrorMetric zone, because the computing is different.
2208 minDeltaDistToUpdate= min(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistFar);
2210 /// TileDistNear to TileDistFar.
2211 else if( distMinFace > CLandscapeGlobals::TileDistNear )
2213 // Profile
2214 NL3D_PROFILE_LAND_ADD(ProfNRefineInTileTransition, 1);
2217 // Compute distance to split/Merge in TileTransition
2218 float distTileTransSplitMerge;
2219 float maxDeltaDist= 8;
2220 float minDeltaDist= 0;
2221 uint nbRecurs= 6;
2222 float nearLimit;
2223 nearLimit= CLandscapeGlobals::RefineThreshold * computeNearLimit();
2224 // Since splitted, compute distance to merge.
2225 // search the distance recursively.
2226 for(uint i=0; i< nbRecurs; i++)
2228 float pivotDeltaDist= (maxDeltaDist-minDeltaDist)/2;
2229 // If the em computed with this distance is still >1 (ie splitted), then we can move further.
2230 if ( computeTileEMForUpdateRefine(distSplitPoint+pivotDeltaDist, distMinFace+pivotDeltaDist, nearLimit ) > 1)
2231 minDeltaDist= pivotDeltaDist;
2232 // else we must move not as far
2233 else
2234 maxDeltaDist= pivotDeltaDist;
2236 // And so take the minimum resulting delta distance
2237 distTileTransSplitMerge= minDeltaDist;
2239 // take the min with distance of distMinFace to the TileDistNear and TileDistFar sphere, because formula change at
2240 // those limits.
2241 minDeltaDistToUpdate= min(distTileTransSplitMerge, CLandscapeGlobals::TileDistFar - distMinFace );
2242 minDeltaDistToUpdate= min(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistNear);
2244 /// 0 to TileDistNear.
2245 else
2247 // because the face is not a Tile Level (ie Level<Patch->TileLimitLevel), it should be splitted,
2248 // and won't merge until reaching at least the TileDistNear sphere.
2249 // Since splitted, Must enter in TileErrorMetric area to know when to merge.
2250 minDeltaDistToUpdate= CLandscapeGlobals::TileDistNear - distMinFace;
2255 // Merge Refine Threshold: because of enforced splits, we have lot of faces whit minDeltaDistToUpdate<0, because
2256 // they alwayas want to merge. To avoid this, add a delta, which delay the test for merge.
2257 // The caveat is that faces which do not need this may merge later. But 2 meters won't add too many faces.
2258 minDeltaDistToUpdate+= NL3D_REFINE_MERGE_THRESHOLD;
2260 // insert in the Merge priority list.
2261 // Until the RefineCenter move under minDeltaDistToUpdate, we don't need to test face.
2262 Patch->getLandscape()->_MergePriorityList.insert(0, minDeltaDistToUpdate, this);
2267 // ***************************************************************************
2268 void CTessFace::unbind()
2270 // NB: since CantMergeFace has a NULL patch ptr, it is unbound too.
2272 // Square case.
2273 //=============
2274 if(!isRectangular())
2276 // Change Left/Right neighbors.
2277 if(isLeaf())
2279 // FLeft and FRight pointers are only valid in Leaves nodes.
2280 if(FLeft && FLeft->Patch!=Patch)
2282 FLeft->changeNeighbor(this, NULL);
2283 FLeft= NULL;
2285 if(FRight && FRight->Patch!=Patch)
2287 FRight->changeNeighbor(this, NULL);
2288 FRight= NULL;
2291 // Change Base neighbors.
2292 if(FBase && FBase->Patch!=Patch)
2294 CTessFace *oldNeigbhorFace= FBase;
2296 FBase->changeNeighbor(this, NULL);
2297 FBase= NULL;
2298 if(!isLeaf())
2300 // Duplicate the VBase of sons, so the unbind is correct and no vertices are shared.
2301 CTessVertex *old= SonLeft->VBase;
2302 SonLeft->VBase= Patch->getLandscape()->newTessVertex();
2303 *(SonLeft->VBase)= *old;
2304 SonRight->VBase= SonLeft->VBase;
2306 // For geomorph (VertexProgram or soft), compute good MaxFaceSize and MaxNearLimit (change since unbinded)
2307 // update us.
2308 SonLeft->VBase->MaxFaceSize= Size;
2309 SonLeft->VBase->MaxNearLimit= computeNearLimit();
2310 // update our neigbhor, only if not a multiple patch face.
2311 if(oldNeigbhorFace->Patch)
2313 old->MaxFaceSize= oldNeigbhorFace->Size;
2314 old->MaxNearLimit= oldNeigbhorFace->computeNearLimit();
2319 // Rectangular case.
2320 //==================
2321 else
2323 // Doens't need to test FBase, since must be same patch.
2324 // In rectangular, FLeft has the behavior of FBase in square case.
2325 if(FLeft && FLeft->Patch!=Patch)
2327 CTessFace *oldNeigbhorFace= FLeft;
2329 FLeft->changeNeighbor(this, NULL);
2330 FLeft= NULL;
2331 if(!isLeaf())
2333 // Duplicate the VBase of sons, so the unbind is correct and no vertices are shared.
2334 // NB: this code is a bit different from square case.
2335 CTessVertex *old= SonLeft->VBase;
2336 SonLeft->VBase= Patch->getLandscape()->newTessVertex();
2337 *(SonLeft->VBase)= *old;
2338 // This is the difference: (see rectangle tesselation rules).
2339 SonRight->VLeft= SonLeft->VBase;
2340 // Yoyo_patch_himself (12/02/2001): I forgot this one!!
2341 nlassert(FBase && FBase->SonLeft);
2342 FBase->SonLeft->VRight= SonLeft->VBase;
2345 // For geomorph (VertexProgram or soft), compute good MaxFaceSize and MaxNearLimit (change since unbinded)
2346 // update us.
2347 SonLeft->VBase->MaxFaceSize= Size;
2348 SonLeft->VBase->MaxNearLimit= computeNearLimit();
2349 // update our neigbhor, only if not a multiple patch face.
2350 if(oldNeigbhorFace->Patch)
2352 old->MaxFaceSize= oldNeigbhorFace->Size;
2353 old->MaxNearLimit= oldNeigbhorFace->computeNearLimit();
2357 // But FRight still valid in leaves nodes only.
2358 if(isLeaf())
2360 if(FRight && FRight->Patch!=Patch)
2362 FRight->changeNeighbor(this, NULL);
2363 FRight= NULL;
2368 // Propagate unbind.
2369 //==================
2370 if(!isLeaf())
2372 // update sons vertex pointers (since they may have been updated by me or my grandfathers).
2373 if(!isRectangular())
2375 SonLeft->VLeft= VBase;
2376 SonLeft->VRight= VLeft;
2377 SonRight->VLeft= VRight;
2378 SonRight->VRight= VBase;
2380 else
2382 // Rectangular case. Update only ptrs which may have changed.
2383 SonLeft->VLeft= VLeft;
2384 SonRight->VBase= VBase;
2385 SonRight->VRight= VRight;
2388 // Must re-create good Vertex links for Far and Near Vertices!!!
2389 SonLeft->updateNearFarVertices();
2390 SonRight->updateNearFarVertices();
2391 if(isRectangular())
2393 //NB: must do this for Base neighbor (see unbind() rectangular case...).
2394 nlassert(FBase && FBase->SonLeft && FBase->SonRight);
2395 FBase->SonLeft->updateNearFarVertices();
2396 FBase->SonRight->updateNearFarVertices();
2399 // unbind the sons.
2400 SonLeft->unbind();
2401 SonRight->unbind();
2405 // ***************************************************************************
2406 void CTessFace::forceMerge()
2408 if(this== &CantMergeFace)
2409 return;
2411 if(!isLeaf())
2413 // First, force merge of Sons and neighbor sons, to have a diamond configuration.
2414 SonLeft->forceMerge();
2415 SonRight->forceMerge();
2417 // forceMerge of necessary neighbors.
2418 RecursMarkForceMerge=true;
2419 if(!isRectangular())
2421 if(FBase && !FBase->RecursMarkForceMerge)
2422 FBase->forceMerge();
2424 else
2426 // Rectangular case. May have a longer propagation...
2427 if(FBase && !FBase->RecursMarkForceMerge)
2428 FBase->forceMerge();
2429 if(FLeft && !FLeft->RecursMarkForceMerge)
2430 FLeft->forceMerge();
2432 RecursMarkForceMerge=false;
2434 // If still a parent, merge.
2435 if(!isLeaf())
2436 merge();
2441 // ***************************************************************************
2442 void CTessFace::forceMergeAtTileLevel()
2444 if(this== &CantMergeFace)
2445 return;
2447 if(!isLeaf())
2449 SonLeft->forceMergeAtTileLevel();
2450 SonRight->forceMergeAtTileLevel();
2452 else
2454 // If we are at tile subdivision, we must force our sons to merge.
2455 if(Level==Patch->TileLimitLevel)
2456 forceMerge();
2461 // ***************************************************************************
2462 void CTessFace::averageTesselationVertices()
2464 // If we are not splitted, no-op.
2465 if(isLeaf())
2466 return;
2469 CTessFace *neighbor;
2470 // Normal square case.
2471 if(!isRectangular())
2473 neighbor= FBase;
2475 // Special Rectangular case.
2476 else
2478 // NB: here, just need to compute average of myself with FLeft, because my neighbor FBase
2479 // is on same patch (see splitRectangular()), and is average with its FLeft neighbor is done
2480 // on another branch of the recurs call.
2481 neighbor= FLeft;
2485 /* Try to average with neighbor.
2486 - if no neighbor, no-op :).
2487 - if neighbor is bind 1/N (CantMergeFace), no-op too, because the vertex is a BaseVertex, so don't modify.
2488 - if my patch is same than my neighbor, then we are on a same patch :), and so no need to average.
2490 if(neighbor!=NULL && neighbor!=&CantMergeFace && Patch!= neighbor->Patch)
2492 nlassert(neighbor->Patch);
2493 nlassert(!neighbor->isLeaf());
2494 // must compute average beetween me and my neighbor.
2495 // NB: this work with both rectangular and square triangles (see split*()).
2496 nlassert(SonLeft->VBase == neighbor->SonLeft->VBase);
2498 CVector v0= Patch->computeVertex(SonLeft->PVBase.getS(), SonLeft->PVBase.getT());
2499 CVector v1= neighbor->Patch->computeVertex(neighbor->SonLeft->PVBase.getS(), neighbor->SonLeft->PVBase.getT());
2501 // And so set the average.
2502 SonLeft->VBase->EndPos= (v0+v1)/2;
2506 // Do same thing for sons. NB: see above, we are not a leaf.
2507 SonLeft->averageTesselationVertices();
2508 SonRight->averageTesselationVertices();
2512 // ***************************************************************************
2513 void CTessFace::refreshTesselationGeometry()
2515 // must enlarge the little tessBlock (if any), for clipping.
2516 Patch->extendTessBlockWithEndPos(this);
2518 // If we are not splitted, no-op.
2519 if(isLeaf())
2520 return;
2523 /* NB: rectangular case: just need to take SonLeft->VBase, because my neighbor on FBase will compute his son
2524 on another branch of the recurs call.
2526 // re-compute this position (maybe with new noise geometry in Tile Edition).
2527 SonLeft->VBase->EndPos= Patch->computeVertex(SonLeft->PVBase.getS(), SonLeft->PVBase.getT());
2528 // overwrite cur Pos (NB: specialy hardcoded for Tile edition).
2529 SonLeft->VBase->Pos= SonLeft->VBase->EndPos;
2531 // Do same thing for sons. NB: see above, we are not a leaf.
2532 SonLeft->refreshTesselationGeometry();
2533 SonRight->refreshTesselationGeometry();
2537 // ***************************************************************************
2538 bool CTessFace::updateBindEdge(CTessFace *&edgeFace, bool &splitWanted)
2540 // Return true, when the bind should be Ok, or if a split has occurred.
2541 // Return false only if pointers are updated, without splits.
2543 if(edgeFace==NULL)
2544 return true;
2546 if(edgeFace->isLeaf())
2547 return true;
2550 Look at the callers, and you'll see that "this" is always a leaf.
2551 Therefore, edgeFace is a valid pointer (either if it is FLeft, FRight or FBase).
2554 // MultiPatch face case.
2555 //======================
2556 // If neighbor is a multiple face.
2557 if(edgeFace->Patch==NULL && edgeFace->FBase==this)
2559 splitWanted= true;
2560 return true;
2564 // neighbor is a "Square face" case.
2565 //==================================
2566 if(!edgeFace->isRectangular())
2568 // NB: this code works either if I AM a rectangular face or a square face.
2570 // If the neighbor is splitted on ourself, split...
2571 if(edgeFace->FBase==this)
2573 splitWanted= true;
2574 return true;
2576 else
2578 // Just update pointers...
2579 if(edgeFace->FLeft==this)
2581 CTessFace *sonLeft= edgeFace->SonLeft;
2582 sonLeft->FBase= this;
2583 edgeFace= sonLeft;
2585 else if(edgeFace->FRight==this)
2587 CTessFace *sonRight= edgeFace->SonRight;
2588 sonRight->FBase= this;
2589 edgeFace= sonRight;
2591 else
2593 // Look at the callers, and you'll see that "this" is always a leaf.
2594 // Therefore, we should never be here.
2595 nlstop;
2599 // neighbor is a "Rectangle face" case.
2600 //=====================================
2601 else
2603 // NB: this code works either if I AM a rectangular face or a square face.
2605 // If the neighbor is splitted on ourself, split...
2606 // Test FLeft because of rectangular case... :)
2607 // FBase should be tested too. If edgeFace->FBase==this, I should be myself a rectangular face.
2608 if(edgeFace->FLeft==this || edgeFace->FBase==this)
2610 splitWanted= true;
2611 return true;
2613 else
2615 if(edgeFace->FRight==this)
2617 // See rectangular tesselation rules, too know why we do this.
2618 CTessFace *sonRight= edgeFace->SonRight;
2619 sonRight->FRight= this;
2620 edgeFace= sonRight;
2622 else
2624 // Look at the callers, and you'll see that "this" is always a leaf.
2625 // Therefore, we should never be here.
2626 nlstop;
2631 return false;
2636 // ***************************************************************************
2637 void CTessFace::updateBindAndSplit()
2639 bool splitWanted= false;
2640 CTessFace *f0= NULL;
2641 CTessFace *f1= NULL;
2643 Look at the callers, and you'll see that "this" is always a leaf.
2644 Therefore, FBase, FLeft and FRight are good pointers, and *FLeft and *FRight should be Ok too.
2646 nlassert(isLeaf());
2647 while(!updateBindEdge(FBase, splitWanted));
2648 // FLeft and FRight pointers are only valid in Leaves nodes.
2649 while(!updateBindEdge(FLeft, splitWanted));
2650 while(!updateBindEdge(FRight, splitWanted));
2651 // In rectangular case, we MUST also update edges of FBase.
2652 // Because splitRectangular() split those two faces at the same time.
2653 if(isRectangular())
2655 f0= this;
2656 f1= FBase;
2657 nlassert(FBase);
2658 nlassert(FBase->isLeaf());
2659 // Doesn't need to update FBase->FBase, since it's me!
2660 // FLeft and FRight pointers are only valid in Leaves nodes.
2661 while(!FBase->updateBindEdge(FBase->FLeft, splitWanted));
2662 while(!FBase->updateBindEdge(FBase->FRight, splitWanted));
2667 CTessFace *fmult= NULL;
2668 CTessFace *fmult0= NULL;
2669 CTessFace *fmult1= NULL;
2670 // If multipatch face case.
2671 //=========================
2672 if(!isRectangular())
2674 // multipatch face case are detected when face->Patch==NULL !!!
2675 if(FBase && FBase->Patch==NULL)
2677 fmult= FBase;
2678 // First, trick: FBase is NULL, so during the split. => no ptr problem.
2679 FBase= NULL;
2682 else
2684 nlassert(f0);
2685 nlassert(f1);
2686 // multipatch face case are detected when face->Patch==NULL !!!
2687 if(f0->FLeft && f0->FLeft->Patch==NULL)
2689 fmult0= f0->FLeft;
2690 // First, trick: neighbor is NULL, so during the split. => no ptr problem.
2691 f0->FLeft= NULL;
2693 // multipatch face case are detected when face->Patch==NULL !!!
2694 if(f1->FLeft && f1->FLeft->Patch==NULL)
2696 fmult1= f1->FLeft;
2697 // First, trick: neighbor is NULL, so during the split. => no ptr problem.
2698 f1->FLeft= NULL;
2702 // Then split, and propagate.
2703 //===========================
2704 split(false);
2705 if(!isRectangular())
2707 if(FBase)
2709 while(FBase->isLeaf())
2710 FBase->updateBindAndSplit();
2712 // There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.
2713 // And problems may arise because this face hasn't yet good connectivity.
2714 nlassert(SonLeft->isLeaf() && SonRight->isLeaf());
2716 else
2718 nlassert(f0);
2719 nlassert(f1);
2720 if(f0->FLeft)
2722 while(f0->FLeft->isLeaf())
2723 f0->FLeft->updateBindAndSplit();
2725 if(f1->FLeft)
2727 while(f1->FLeft->isLeaf())
2728 f1->FLeft->updateBindAndSplit();
2730 // There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.
2731 // And problems may arise because this face hasn't yet good connectivity.
2732 nlassert(f0->SonLeft->isLeaf() && f0->SonRight->isLeaf());
2733 nlassert(f1->SonLeft->isLeaf() && f1->SonRight->isLeaf());
2737 // If multipatch face case, update neighbors.
2738 //===========================================
2739 if(!isRectangular() && fmult)
2741 // Update good Face neighbors.
2742 //============================
2743 SonLeft->FRight= fmult->SonRight;
2744 fmult->SonRight->changeNeighbor(&CTessFace::MultipleBindFace, SonLeft);
2746 SonRight->FLeft= fmult->SonLeft;
2747 fmult->SonLeft->changeNeighbor(&CTessFace::MultipleBindFace, SonRight);
2749 // NB: this work auto with 1/2 or 1/4. See CPatch::bind(), to understand.
2750 // In 1/4 case, fmult->SonLeft and fmult->SonRight are themselves MultiPatch face. So it will recurse.
2752 // Update good vertex pointer.
2753 //============================
2754 CTessVertex *vert= fmult->VBase;
2756 // Copy the good coordinate: those splitted (because of noise).
2757 vert->Pos= vert->StartPos= vert->EndPos= SonLeft->VBase->EndPos;
2758 // But delete the pointer.
2759 Patch->getLandscape()->deleteTessVertex(SonLeft->VBase);
2760 // And update sons pointers, to good vertex.
2761 SonLeft->VBase= vert;
2762 SonRight->VBase= vert;
2763 // Compute correct centers.
2764 SonRight->computeSplitPoint();
2765 SonLeft->computeSplitPoint();
2768 // Update good Far vertex pointer.
2769 //================================
2770 // Because *->VBase may have been merged to the multiple bind face, Near/FarVertices which pointed on it must
2771 // be setup.
2772 // We do not have to propagate this vertex ptr change since sons are leaves!!
2773 nlassert(SonLeft->isLeaf() && SonRight->isLeaf());
2774 // update pointers on vertex.
2775 SonLeft->updateNearFarVertices();
2776 SonRight->updateNearFarVertices();
2779 // Bind FBase to a false face which indicate a bind 1/N.
2780 // This face prevent for "this" face to be merged...
2781 FBase= &CantMergeFace;
2783 // Therefore, the vertex will be never deleted (since face not merged).
2784 // The only way to do this, is to unbind the patch from all (then the vertex is cloned), then the merge will be Ok.
2786 // Else if rectangular.
2787 else if(fmult0 || fmult1)
2789 CTessFace *f;
2790 sint i;
2791 nlassert(f0);
2792 nlassert(f1);
2794 // Same reasoning for rectangular patchs, as above.
2795 for(i=0;i<2;i++)
2797 if(i==0)
2798 f= f0, fmult= fmult0;
2799 else
2800 f= f1, fmult= fmult1;
2801 if(fmult)
2803 // Update good Face neighbors (when I am a rectangle).
2804 //============================
2805 // Consider the fmult face as a square face.
2806 CTessFace *toLeft, *toRight;
2807 CTessFace *fl=f->SonLeft, *fr=f->SonRight;
2808 toLeft= fmult->SonLeft;
2809 toRight= fmult->SonRight;
2810 // Cross connection of sons.
2811 fl->FLeft= toLeft;
2812 fr->FLeft= toRight;
2813 toLeft->changeNeighbor(&CTessFace::MultipleBindFace, fl);
2814 toRight->changeNeighbor(&CTessFace::MultipleBindFace, fr);
2816 // Update good vertex pointer.
2817 //============================
2818 CTessVertex *vert= fmult->VBase;
2820 // Copy the good coordinate: those splitted (because of noise).
2821 // NB: this work too with rectangular patch (see tesselation rules).
2822 vert->Pos= vert->StartPos= vert->EndPos= fl->VBase->EndPos;
2823 // But delete the pointer.
2824 Patch->getLandscape()->deleteTessVertex(fl->VBase);
2825 // And update sons pointers, to good vertex (rectangular case, see tesselation rules).
2826 fl->VBase= vert;
2827 fr->VLeft= vert;
2828 f->FBase->SonLeft->VRight= vert;
2830 // Point to a bind 1/N indicator.
2831 f->FLeft= &CantMergeFace;
2834 // After all updates done. recompute centers of both sons 's faces, and update far vertices pointers.
2835 for(i=0;i<2;i++)
2837 if(i==0)
2838 f= f0;
2839 else
2840 f= f1;
2841 // Compute correct centers.
2842 f->SonRight->computeSplitPoint();
2843 f->SonLeft->computeSplitPoint();
2845 // Update good Far vertex pointer.
2846 //================================
2847 // Because *->VBase may have been merged to the multiple bind face, Near/FarVertices which pointed on it must
2848 // be setup.
2849 // We do not have to propagate this vertex ptr change, since sons are leaves!!
2850 nlassert(f->SonLeft->isLeaf() && f->SonRight->isLeaf());
2851 // update pointers on vertex.
2852 f->SonLeft->updateNearFarVertices();
2853 f->SonRight->updateNearFarVertices();
2859 // ***************************************************************************
2860 void CTessFace::updateBind()
2863 Remind that updateBind() is called ONLY on the patch which is binded (not the neighbors).
2864 Since updateBind() is called on the bintree, and that precedent propagated split may have occur, we may not
2865 be a leaf here. So we are not sure that FLeft and FRight are good, and we doesn't need to update them (since we have
2866 sons).
2867 Also, since we are splitted, and correctly linked (this may not be the case in updateBindAndSplit()), FBase IS
2868 correct. His FBase neighbor and him form a diamond. So we don't need to update him.
2870 Same remarks for rectangular patchs.
2872 if(isLeaf())
2874 bool splitWanted= false;
2875 while(!updateBindEdge(FBase, splitWanted));
2876 // FLeft and FRight pointers are only valid in Leaves nodes.
2877 while(!updateBindEdge(FLeft, splitWanted));
2878 while(!updateBindEdge(FRight, splitWanted));
2879 if(splitWanted)
2880 updateBindAndSplit();
2884 // Recurse to sons.
2885 if(!isLeaf())
2887 // Update bind of sons.
2888 SonLeft->updateBind();
2889 SonRight->updateBind();
2893 // ***************************************************************************
2894 static inline bool matchEdge(const CVector2f &uv0, const CVector2f &uv1, const CVector2f &uva, const CVector2f &uvb)
2896 if(uv0==uva && uv1==uvb)
2897 return true;
2898 if(uv0==uvb && uv1==uva)
2899 return true;
2900 return false;
2903 // ***************************************************************************
2904 CTessFace *CTessFace::linkTessFaceWithEdge(const CVector2f &uv0, const CVector2f &uv1, CTessFace *linkTo)
2906 // Compute 0,1 coords of 3 patch coords.
2907 CVector2f vb( PVBase.getS(), PVBase.getT() );
2908 CVector2f vl( PVLeft.getS(), PVLeft.getT() );
2909 CVector2f vr( PVRight.getS(), PVRight.getT() );
2911 // Search if one of the 3 edges of this triangle match the wanted edge.
2912 // Base Edge
2913 if(matchEdge(uv0, uv1, vl, vr))
2915 // If leaf, check if unbound (else ptr is invalid)
2916 nlassert(FBase==NULL || !isLeaf());
2917 FBase= linkTo;
2918 return this;
2920 // Left Edge
2921 if(matchEdge(uv0, uv1, vb, vl))
2923 // If leaf, check if unbound (else ptr is invalid)
2924 nlassert(FLeft==NULL || !isLeaf());
2925 FLeft= linkTo;
2926 return this;
2928 // Right Edge
2929 if(matchEdge(uv0, uv1, vb, vr))
2931 // If leaf, check if unbound (else ptr is invalid)
2932 nlassert(FRight==NULL || !isLeaf());
2933 FRight= linkTo;
2934 return this;
2938 // If not found here, recurs to children
2939 CTessFace *ret= NULL;
2940 if( !isLeaf() )
2942 ret= SonLeft->linkTessFaceWithEdge(uv0, uv1, linkTo);
2943 // if no found in this branch, recusr right branch.
2944 if(!ret)
2945 ret= SonRight->linkTessFaceWithEdge(uv0, uv1, linkTo);
2948 // return the result from subBranchs
2949 return ret;
2953 // ***************************************************************************
2954 bool CTessFace::isRectangular() const
2956 return Level<Patch->SquareLimitLevel;
2961 // ***************************************************************************
2962 // ***************************************************************************
2963 // For changePatchTexture.
2964 // ***************************************************************************
2965 // ***************************************************************************
2968 // ***************************************************************************
2969 void CTessFace::deleteTileUvs()
2971 // NB: NearVertices are removed from renderlist with deleteTileUv (called in releaseTileMaterial()).
2973 if(!isLeaf())
2975 // Must delete the materials of leaves first.
2976 SonLeft->deleteTileUvs();
2977 SonRight->deleteTileUvs();
2978 if(SonLeft->Level== Patch->TileLimitLevel)
2980 // Square patch assumption: the sons are not of the same TileId/Patch.
2981 nlassert(!sameTile(SonLeft, SonRight));
2982 // release tiles.
2983 SonLeft->releaseTileMaterial();
2984 SonRight->releaseTileMaterial();
2986 else if(SonLeft->Level > Patch->TileLimitLevel)
2988 nlassert(!FBase || !FBase->isLeaf());
2990 // Delete Uv, only if not already done by the neighbor (ie neighbor has yet TileFaces!!).
2991 // But Always delete if neighbor exist and has not same tile as me.
2992 // NB: this work with rectangular neigbor patch, since sameTile() will return false if different patch.
2993 if(!FBase || !FBase->SonLeft->emptyTileFaces() || !sameTile(this, FBase))
2995 SonLeft->deleteTileUv(IdUvBase);
2997 // In all case, must delete the tilefaces of those face.
2998 SonLeft->deleteTileFaces();
2999 SonRight->deleteTileFaces();
3000 // For createTileUvs, it is important to mark those faces as NO TileMaterial.
3001 SonLeft->TileMaterial= NULL;
3002 SonRight->TileMaterial= NULL;
3005 else
3007 // NB: this is done always BELOW tile creation (see above).
3008 // Do this only for tiles.
3009 if(TileMaterial)
3010 Patch->removeFaceFromTileRenderList(this);
3016 // ***************************************************************************
3017 void CTessFace::recreateTileUvs()
3019 // NB: NearVertices are append to renderlist with allocTileUv (called in computeTileMaterial()/heritTileMaterial()).
3021 if(!isLeaf())
3023 // Must recreate the materials of parent first.
3025 // There is no problem with rectangular patch, since tiles are always squares.
3026 // If new tile ....
3027 if(SonLeft->Level==Patch->TileLimitLevel)
3029 SonLeft->computeTileMaterial();
3030 SonRight->computeTileMaterial();
3032 // else Tile herit.
3033 else if(SonLeft->Level > Patch->TileLimitLevel)
3035 heritTileMaterial();
3038 SonLeft->recreateTileUvs();
3039 SonRight->recreateTileUvs();
3041 else
3043 // NB: this is done always AFTER tile creation (see above).
3044 // Do this only for tiles.
3045 if(TileMaterial)
3046 Patch->appendFaceToTileRenderList(this);
3052 // ***************************************************************************
3053 void CTessFace::heritTileMaterial()
3055 SonLeft->TileMaterial= TileMaterial;
3056 SonLeft->TileId= TileId;
3057 SonLeft->buildTileFaces();
3058 SonLeft->copyTileUv(IdUvLeft, this, IdUvBase);
3059 SonLeft->copyTileUv(IdUvRight, this, IdUvLeft);
3061 SonRight->TileMaterial= TileMaterial;
3062 SonRight->TileId= TileId;
3063 SonRight->buildTileFaces();
3064 SonRight->copyTileUv(IdUvLeft, this, IdUvRight);
3065 SonRight->copyTileUv(IdUvRight, this, IdUvBase);
3067 // Create, or link to the tileUv.
3068 // Try to link to a neighbor TileUv.
3069 // Can only work iff exist, and iff FBase is same patch, and same TileId.
3070 if(FBase!=NULL && !FBase->isLeaf() && FBase->SonLeft->TileMaterial!=NULL && sameTile(this, FBase) )
3072 // Ok!! link to the (existing) TileUv.
3073 // FBase->SonLeft!=NULL since FBase->isLeaf()==false.
3074 SonLeft->copyTileUv(IdUvBase, FBase->SonLeft, IdUvBase);
3075 SonRight->copyTileUv(IdUvBase, FBase->SonLeft, IdUvBase);
3077 else
3079 // Allocate a new vertex, and copy it to SonLeft and SonRight.
3080 SonLeft->allocTileUv(IdUvBase);
3081 SonRight->copyTileUv(IdUvBase, SonLeft, IdUvBase);
3083 // Fill the new near vertex, with middle of Left/Right father.
3084 SonLeft->heritTileUv(this);
3086 // UVs are computed, may create and fill VB.
3087 SonLeft->checkCreateFillTileVB(IdUvBase);
3093 // ***************************************************************************
3094 // ***************************************************************************
3095 // For getTesselatedPos
3096 // ***************************************************************************
3097 // ***************************************************************************
3100 // ***************************************************************************
3101 void CTessFace::getTesselatedPos(const CUV &uv, bool verifInclusion, CVector &ret)
3103 CVector uvPos(uv.U, uv.V, 0);
3105 // may verif if uv is In this triangle. supposed true if rectangular branch.
3106 if(verifInclusion && !(isRectangular() && !isLeaf()) )
3108 CVector uvs[3];
3109 uvs[0].set( PVBase.getS(), PVBase.getT(), 0);
3110 uvs[1].set( PVLeft.getS(), PVLeft.getT(), 0);
3111 uvs[2].set( PVRight.getS(), PVRight.getT(), 0);
3112 for(sint i=0; i<3; i++)
3114 CVector dUv= uvs[(i+1)%3] - uvs[i];
3115 CVector normalUv(dUv.y, -dUv.x, 0);
3116 // if out this 2D plane, uv is out this triangle
3117 if(normalUv * (uvPos-uvs[i]) <0)
3118 return;
3122 // compute tesselated pos in this face.
3123 if(isLeaf())
3124 // ok, no more sons, let's do it.
3125 computeTesselatedPos(uv, ret);
3126 else
3128 // must subdivide.
3129 // if we are rectangular (strange tesselation), must test in both leaves, else, choose only one.
3130 if(isRectangular())
3132 SonLeft->getTesselatedPos(uv, true, ret);
3133 SonRight->getTesselatedPos(uv, true, ret);
3135 else
3137 // Compute the uv plane which separate the 2 leaves.
3138 CVector uvBase, uvMiddle;
3139 uvBase.set ( PVBase.getS(), PVBase.getT(), 0);
3140 uvMiddle.set( SonLeft->PVBase.getS(), SonLeft->PVBase.getT(), 0);
3141 CVector dUv= uvMiddle - uvBase;
3142 CVector normalUv(dUv.y, -dUv.x, 0);
3143 // choose what leaf to recurs.
3144 if(normalUv * (uvPos - uvBase) <0)
3145 SonLeft->getTesselatedPos(uv, false, ret);
3146 else
3147 SonRight->getTesselatedPos(uv, false, ret);
3155 // ***************************************************************************
3156 void CTessFace::computeTesselatedPos(const CUV &uv, CVector &ret)
3158 CVector uvPos(uv.U, uv.V, 0);
3160 // compute the UV triangle of this face.
3161 CTriangle uvTri;
3162 uvTri.V0.set( PVBase.getS(), PVBase.getT(), 0);
3163 uvTri.V1.set( PVLeft.getS(), PVLeft.getT(), 0);
3164 uvTri.V2.set( PVRight.getS(), PVRight.getT(), 0);
3166 // must interpolate the position with given UV, so compute XYZ gradients.
3167 CVector Gx;
3168 CVector Gy;
3169 CVector Gz;
3170 // If VertexProgram activated
3171 if( CLandscapeGlobals::VertexProgramEnabled )
3173 // then Must update geomorphed position because not done !!
3174 VBase->computeGeomPos();
3175 VLeft->computeGeomPos();
3176 VRight->computeGeomPos();
3178 // NB: take geomorphed position.
3179 uvTri.computeGradient(VBase->Pos.x, VLeft->Pos.x, VRight->Pos.x, Gx);
3180 uvTri.computeGradient(VBase->Pos.y, VLeft->Pos.y, VRight->Pos.y, Gy);
3181 uvTri.computeGradient(VBase->Pos.z, VLeft->Pos.z, VRight->Pos.z, Gz);
3183 // Compute interpolated position.
3184 ret= VBase->Pos;
3185 uvPos-= uvTri.V0;
3186 ret.x+= Gx*uvPos;
3187 ret.y+= Gy*uvPos;
3188 ret.z+= Gz*uvPos;
3193 // ***************************************************************************
3194 void CTessFace::appendTessellationLeaves(std::vector<const CTessFace*> &leaves) const
3196 if(isLeaf())
3197 leaves.push_back(this);
3198 else
3200 SonLeft->appendTessellationLeaves(leaves);
3201 SonRight->appendTessellationLeaves(leaves);
3206 } // NL3D