#include <tessellation.h>
Inheritance diagram for NL3D::CTessFace:

Nevrax France
Definition at line 233 of file tessellation.h.
|
|
Definition at line 264 of file tessellation.h.
|
|
|
Definition at line 161 of file tessellation.cpp. References ErrorMetricDate, FBase, FLeft, FRight, NL3D_MAX_TILE_FACE, NL3D_PROFILE_LAND_ADD, NL3D::ProfNTessFace, RecursMarkCanMerge, RecursMarkForceMerge, ShadowMapTriId, sint, SonLeft, SonRight, TileFaces, VBase, VLeft, and VRight.
00162 {
00163 // Don't modify any of it!!
00164 // Patch, SonLeft and SonRight nullity are very usefull for MultiplePatch faces, and CantMergeFace.
00165
00166 Patch= NULL;
00167 VBase=VLeft=VRight= NULL;
00168 FBase=FLeft=FRight= NULL;
00169 Father=SonLeft=SonRight= NULL;
00170 Level=0;
00171 ErrorMetricDate= 0;
00172 // Size, Center, paramcoord undetermined.
00173
00174 TileMaterial= NULL;
00175 // Very important (for split reasons). Init Tilefaces to NULL.
00176 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00177 {
00178 TileFaces[i]=NULL;
00179 }
00180
00181 RecursMarkCanMerge=false;
00182 RecursMarkForceMerge=false;
00183
00184
00185 NL3D_PROFILE_LAND_ADD(ProfNTessFace, 1);
00186
00187 ShadowMapTriId= -1;
00188 }
|
|
|
Definition at line 192 of file tessellation.cpp. References NL3D_PROFILE_LAND_ADD, nlassert, NL3D::ProfNTessFace, and ShadowMapTriId.
00193 {
00194 // Old Code. This is not sufficient to clear the CTessFace.
00195 // Vertices and Uvs must be correctly cleared too (but difficult because of sharing).
00196 /*
00197 Patch->getLandscape()->deleteTessFace(SonLeft);
00198 Patch->getLandscape()->deleteTessFace(SonRight);
00199
00200 // update neighbors.
00201 if(FBase) FBase->changeNeighbor(this, NULL);
00202 if(FLeft) FLeft->changeNeighbor(this, NULL);
00203 if(FRight) FRight->changeNeighbor(this, NULL);
00204
00205 FBase=FLeft=FRight= NULL;
00206 */
00207
00208 NL3D_PROFILE_LAND_ADD(ProfNTessFace, -1);
00209
00210 // Ensure correclty removed from landscape ShadowMap.
00211 nlassert(ShadowMapTriId== -1);
00212 }
|
|
|
Definition at line 372 of file tessellation.cpp. References NL3D::CPatch::appendNearVertexToRenderList(), NL3D::CPatch::getLandscape(), IdUvBase, IdUvLeft, IdUvRight, NL3D::CLandscape::newTessNearVertex(), NL3D_MAX_TILE_FACE, NL3D_TILE_PASS_RGB0, nlassert, nlstop, sint, NL3D::CTessNearVertex::Src, TileFaces, NL3D::CTileFace::V, VBase, VLeft, and VRight. Referenced by computeTileMaterial(), and heritTileMaterial().
00373 {
00374 // TileFaces must have been build.
00375 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
00376
00377 // what src??
00378 CTessVertex *vertexSrc;
00379 switch(id)
00380 {
00381 case IdUvBase: vertexSrc= VBase; break;
00382 case IdUvLeft: vertexSrc= VLeft; break;
00383 case IdUvRight: vertexSrc= VRight; break;
00384 default: nlstop;
00385 };
00386
00387 // Do it for all possible pass
00388 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00389 {
00390 if(TileFaces[i])
00391 {
00392 CTessNearVertex *newNear= Patch->getLandscape()->newTessNearVertex();
00393 newNear->Src= vertexSrc;
00394 TileFaces[i]->V[id]= newNear;
00395 Patch->appendNearVertexToRenderList(TileMaterial, newNear);
00396
00397 // May Allocate/Fill VB. Do it after allocTileUv, because UVs are not comuted yet.
00398 }
00399 }
00400 }
|
|
|
append a list just after this node. root is the root of the list. It is not inserted in the result. After this, the list pointed by "root" is empty. Definition at line 88 of file tess_face_priority_list.cpp. References NL3D::CTessFacePListNode::_NextTessFaceInPList, and NL3D::CTessFacePListNode::_PrecTessFaceInPList. Referenced by NL3D::CLandscape::refine(), NL3D::CTessFacePriorityList::shift(), and NL3D::CTessFacePriorityList::CRollingTable::shiftEntries().
00089 {
00090 // If list to append is not empty.
00091 if( root._NextTessFaceInPList != &root )
00092 {
00093 // If we are empty.
00094 if( _NextTessFaceInPList==this )
00095 {
00096 // link the appendList to the root.
00097 _PrecTessFaceInPList= root._PrecTessFaceInPList;
00098 _NextTessFaceInPList= root._NextTessFaceInPList;
00099 // link the root to the appendList.
00100 _PrecTessFaceInPList->_NextTessFaceInPList= this;
00101 _NextTessFaceInPList->_PrecTessFaceInPList= this;
00102 }
00103 // else bind first-last in the interval prec-next.
00104 else
00105 {
00106 CTessFacePListNode *first= root._NextTessFaceInPList;
00107 CTessFacePListNode *last= root._PrecTessFaceInPList;
00108 CTessFacePListNode *prec= this;
00109 CTessFacePListNode *next= _NextTessFaceInPList;
00110 // insert the appendList in our list.
00111 next->_PrecTessFaceInPList= last;
00112 prec->_NextTessFaceInPList= first;
00113 // insert our list in the appendList.
00114 last->_NextTessFaceInPList= next;
00115 first->_PrecTessFaceInPList= prec;
00116 }
00117
00118 // clear input list.
00119 root._PrecTessFaceInPList= &root;
00120 root._NextTessFaceInPList= &root;
00121 }
00122 }
|
|
|
Definition at line 3194 of file tessellation.cpp. References isLeaf(), SonLeft, and SonRight. Referenced by NL3D::CPatch::appendTessellationLeaves().
|
|
|
Definition at line 2468 of file tessellation.cpp. References CantMergeFace, NL3D::CPatch::computeVertex(), NL3D::CTessVertex::EndPos, FBase, FLeft, NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), isLeaf(), isRectangular(), nlassert, Patch, PVBase, SonLeft, SonRight, and VBase. Referenced by NL3D::CPatch::averageTesselationVertices().
02469 {
02470 // If we are not splitted, no-op.
02471 if(isLeaf())
02472 return;
02473
02474
02475 CTessFace *neighbor;
02476 // Normal square case.
02477 if(!isRectangular())
02478 {
02479 neighbor= FBase;
02480 }
02481 // Special Rectangular case.
02482 else
02483 {
02484 // NB: here, just need to compute average of myself with FLeft, because my neighbor FBase
02485 // is on same patch (see splitRectangular()), and is average with its FLeft neighbor is done
02486 // on an other branch of the recurs call.
02487 neighbor= FLeft;
02488 }
02489
02490
02491 /* Try to average with neighbor.
02492 - if no neighbor, no-op :).
02493 - if neighbor is bind 1/N (CantMergeFace), no-op too, because the vertex is a BaseVertex, so don't modify.
02494 - if my patch is same than my neighbor, then we are on a same patch :), and so no need to average.
02495 */
02496 if(neighbor!=NULL && neighbor!=&CantMergeFace && Patch!= neighbor->Patch)
02497 {
02498 nlassert(neighbor->Patch);
02499 nlassert(!neighbor->isLeaf());
02500 // must compute average beetween me and my neighbor.
02501 // NB: this work with both rectangular and square triangles (see split*()).
02502 nlassert(SonLeft->VBase == neighbor->SonLeft->VBase);
02503
02504 CVector v0= Patch->computeVertex(SonLeft->PVBase.getS(), SonLeft->PVBase.getT());
02505 CVector v1= neighbor->Patch->computeVertex(neighbor->SonLeft->PVBase.getS(), neighbor->SonLeft->PVBase.getT());
02506
02507 // And so set the average.
02508 SonLeft->VBase->EndPos= (v0+v1)/2;
02509 }
02510
02511
02512 // Do same thing for sons. NB: see above, we are not a leaf.
02513 SonLeft->averageTesselationVertices();
02514 SonRight->averageTesselationVertices();
02515 }
|
|
|
Definition at line 511 of file tessellation.cpp. References NL3D::CPatch::getLandscape(), IdUvBase, IdUvLeft, IdUvRight, NL3D::CLandscape::newTileFace(), NL3D_MAX_TILE_FACE, nlassert, NL3D::CTileMaterial::Pass, NL3D::CRdrTileId::PatchRdrPass, sint, TileFaces, and NL3D::CTileFace::V. Referenced by computeTileMaterial(), and heritTileMaterial().
00512 {
00513 nlassert(TileMaterial);
00514
00515 // Do nothgin for lightmap pass, of course.
00516 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00517 {
00518 if(TileMaterial->Pass[i].PatchRdrPass)
00519 {
00520 TileFaces[i]= Patch->getLandscape()->newTileFace();
00521 TileFaces[i]->V[IdUvBase]= NULL;
00522 TileFaces[i]->V[IdUvLeft]= NULL;
00523 TileFaces[i]->V[IdUvRight]= NULL;
00524 }
00525 }
00526 }
|
|
|
Definition at line 1549 of file tessellation.cpp. References CantMergeFace, ErrorMetric, FBase, FLeft, isLeaf(), isRectangular(), nlassert, RecursMarkCanMerge, SonLeft, SonRight, and updateErrorMetric(). Referenced by merge(), refineAll(), and updateRefineMerge().
01550 {
01551 if(this== &CantMergeFace)
01552 return false;
01553
01554 nlassert(!isLeaf());
01555
01556 // Test diamond config (sons must be leaves).
01557 if(!SonLeft->isLeaf())
01558 return false;
01559 if(!SonRight->isLeaf())
01560 return false;
01561 // If Errormetric must be considered for this test.
01562 if(testEm)
01563 {
01564 updateErrorMetric();
01565 float ps2= ErrorMetric;
01566 ps2*= CLandscapeGlobals::OORefineThreshold;
01567 if(ps2>=1.0f)
01568 return false;
01569 }
01570
01571 // Then test neighbors.
01572 RecursMarkCanMerge= true;
01573 bool ok= true;
01574 if(!isRectangular())
01575 {
01576 if(FBase && !FBase->RecursMarkCanMerge)
01577 {
01578 if(!FBase->canMerge(testEm))
01579 ok= false;
01580 }
01581 }
01582 else
01583 {
01584 // Rectangular case. May have a longer propagation...
01585 if(FBase && !FBase->RecursMarkCanMerge)
01586 {
01587 if(!FBase->canMerge(testEm))
01588 ok= false;
01589 }
01590 if(ok && FLeft && !FLeft->RecursMarkCanMerge)
01591 {
01592 if(!FLeft->canMerge(testEm))
01593 ok= false;
01594 }
01595 }
01596 // Must not return false in preceding tests, because must set RecursMarkCanMerge to false.
01597 RecursMarkCanMerge= false;
01598
01599 return ok;
01600 }
|
|
||||||||||||
|
Definition at line 298 of file tessellation.h. References FBase, FLeft, FRight, and from. Referenced by doMerge(), split(), splitRectangular(), unbind(), and updateBindAndSplit().
|
|
|
Definition at line 403 of file tessellation.cpp. References NL3D::CPatch::checkCreateVertexVBNear(), NL3D::CPatch::checkFillVertexVBNear(), NL3D_MAX_TILE_FACE, NL3D_TILE_PASS_RGB0, nlassert, sint, TileFaces, and NL3D::CTileFace::V. Referenced by computeTileMaterial(), and heritTileMaterial().
00404 {
00405 // TileFaces must have been build.
00406 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
00407
00408 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00409 {
00410 if(TileFaces[i])
00411 {
00412 CTessNearVertex *vertNear;
00413 vertNear= TileFaces[i]->V[id];
00414
00415 // May Allocate/Fill VB.
00416 Patch->checkCreateVertexVBNear(vertNear);
00417 Patch->checkFillVertexVBNear(vertNear);
00418 }
00419 }
00420 }
|
|
|
Definition at line 424 of file tessellation.cpp. References NL3D::CPatch::checkFillVertexVBNear(), NL3D_MAX_TILE_FACE, NL3D_TILE_PASS_RGB0, nlassert, sint, TileFaces, and NL3D::CTileFace::V. Referenced by split(), and splitRectangular().
00425 {
00426 // TileFaces must have been build.
00427 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
00428
00429 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00430 {
00431 if(TileFaces[i])
00432 {
00433 CTessNearVertex *vertNear;
00434 vertNear= TileFaces[i]->V[id];
00435
00436 // May Fill VB.
00437 Patch->checkFillVertexVBNear(vertNear);
00438 }
00439 }
00440 }
|
|
|
Definition at line 216 of file tessellation.cpp. References nlassert, NL3D::CPatch::TileLimitLevel, and uint. Referenced by computeTileErrorMetric(), split(), splitRectangular(), unbind(), updateRefineMerge(), and updateRefineSplit().
00217 {
00218 // General formula for Level, function of Size, treshold etc...:
00219 // WantedLevel= log2(BaseSize / sqrdist / RefineThreshold);
00220 // <=> WantedLevel= log2( CurSize*2^Level / sqrdist / RefineThreshold).
00221 // <=> WantedLevel= log2( ProjectedSize* 2^Level / RefineThreshold).
00222 // <=> 2^WantedLevel= ProjectedSize* 2^Level / RefineThreshold.
00223 // <=> ProjectedSize= (2^WantedLevel) * RefineThreshold / (2^Level);
00224 // <=> ProjectedSize= (1<<WantedLevel) * RefineThreshold / (1<<Level);
00225 // UnOptimised formula: limit= (1<<Patch->TileLimitLevel) / (1<<Level);
00226 nlassert(Level<=20);
00227 static const uint BigValue= 1<<20;
00228 static const float OOBigValue= 1.0f / BigValue;
00229 return (1<<Patch->TileLimitLevel) * (OOBigValue*(BigValue>>Level));
00230 }
|
|
|
compute the SplitPoint. VBase / VLeft and VRight must be valid. Also compute MaxDistToSplitPoint. Definition at line 345 of file tessellation.cpp. References NL3D::CTessVertex::EndPos, isRectangular(), MaxDistToSplitPoint, SplitPoint, NLMISC::CVector::sqrnorm(), VBase, VLeft, and VRight. Referenced by NL3D::CPatch::bind(), NL3D::CPatch::makeRoots(), split(), splitRectangular(), and updateBindAndSplit().
00346 {
00347 if(isRectangular())
00348 {
00349 // If it is a rectangular triangle, it will be splitted on the middle of VBase/VLeft.
00350 // see splitRectangular() conventions.
00351 // So for good geomorph compute per vertex, we must have this SplitPoint on this middle.
00352 SplitPoint= (VLeft->EndPos + VBase->EndPos)/2;
00353 }
00354 else
00355 {
00356 // If it is a square triangle, it will be splitted on middle of VLeft/VRight.
00357 // So for good geomorph compute per vertex, we must have this SplitPoint on this middle.
00358 SplitPoint= (VLeft->EndPos + VRight->EndPos)/2;
00359 }
00360
00361 // compute MaxDistToSplitPoint
00362 float d0= (VBase->EndPos - SplitPoint).sqrnorm();
00363 float d1= (VLeft->EndPos - SplitPoint).sqrnorm();
00364 float d2= (VRight->EndPos - SplitPoint).sqrnorm();
00365 MaxDistToSplitPoint= max(d0, d1);
00366 MaxDistToSplitPoint= max(MaxDistToSplitPoint, d2);
00367 // Get the distance.
00368 MaxDistToSplitPoint= sqrtf(MaxDistToSplitPoint);
00369 }
|
|
||||||||||||
|
Definition at line 3156 of file tessellation.cpp. References NL3D::CTessVertex::computeGeomPos(), NLMISC::CTriangle::computeGradient(), NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), NL3D::CTessVertex::Pos, PVBase, PVLeft, PVRight, NLMISC::CVector::set(), NLMISC::CUV::U, NLMISC::CUV::V, NLMISC::CTriangle::V0, NLMISC::CTriangle::V1, NLMISC::CTriangle::V2, VBase, VLeft, VRight, NLMISC::CVector::x, NLMISC::CVector::y, and NLMISC::CVector::z. Referenced by getTesselatedPos().
03157 {
03158 CVector uvPos(uv.U, uv.V, 0);
03159
03160 // compute the UV triangle of this face.
03161 CTriangle uvTri;
03162 uvTri.V0.set( PVBase.getS(), PVBase.getT(), 0);
03163 uvTri.V1.set( PVLeft.getS(), PVLeft.getT(), 0);
03164 uvTri.V2.set( PVRight.getS(), PVRight.getT(), 0);
03165
03166 // must interpolate the position with given UV, so compute XYZ gradients.
03167 CVector Gx;
03168 CVector Gy;
03169 CVector Gz;
03170 // If VertexProgram activated
03171 if( CLandscapeGlobals::VertexProgramEnabled )
03172 {
03173 // then Must update geomorphed position because not done !!
03174 VBase->computeGeomPos();
03175 VLeft->computeGeomPos();
03176 VRight->computeGeomPos();
03177 }
03178 // NB: take geomorphed position.
03179 uvTri.computeGradient(VBase->Pos.x, VLeft->Pos.x, VRight->Pos.x, Gx);
03180 uvTri.computeGradient(VBase->Pos.y, VLeft->Pos.y, VRight->Pos.y, Gy);
03181 uvTri.computeGradient(VBase->Pos.z, VLeft->Pos.z, VRight->Pos.z, Gz);
03182
03183 // Compute interpolated position.
03184 ret= VBase->Pos;
03185 uvPos-= uvTri.V0;
03186 ret.x+= Gx*uvPos;
03187 ret.y+= Gy*uvPos;
03188 ret.z+= Gz*uvPos;
03189
03190 }
|
|
||||||||||||||||
|
Definition at line 312 of file tessellation.cpp. References NLMISC::sqr(). Referenced by updateRefineMerge(), and updateRefineSplit().
00313 {
00314 float ema;
00315 // Normal ErrorMetric simulation.
00316 ema= Size / sqr(distSplitPoint);
00317
00318 // TileErrorMetric simulation.
00319 if(distMinFace < CLandscapeGlobals::TileDistFar)
00320 {
00321 // If we are not so subdivided.
00322 if( ema<nearLimit )
00323 {
00324 if( distMinFace< CLandscapeGlobals::TileDistNear)
00325 {
00326 ema= nearLimit;
00327 }
00328 else
00329 {
00330 // Smooth transition to the nearLimit of tesselation.
00331 float f= ( CLandscapeGlobals::TileDistFarSqr - sqr(distMinFace) ) * CLandscapeGlobals::OOTileDistDeltaSqr;
00332 // sqr gives better result, by smoothing more the start of transition.
00333 f= sqr(f);
00334 f= sqr(f);
00335 ema= ema + (nearLimit-ema)*f;
00336 }
00337 }
00338 }
00339
00340 return ema * CLandscapeGlobals::OORefineThreshold;
00341 }
|
|
|
Definition at line 234 of file tessellation.cpp. References computeNearLimit(), NL3D::CTessVertex::EndPos, ErrorMetric, NLMISC::sqr(), VBase, VLeft, and VRight. Referenced by updateErrorMetric().
00235 {
00236 // We must take a more correct errometric here: We must have sons face which have
00237 // lower projectedsize than father. This is not the case if Center of face is taken (but when not in
00238 // tile mode this is nearly the case). So take the min dist from 3 points.
00239 float s0= (VBase->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
00240 float s1= (VLeft->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
00241 float s2= (VRight->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
00242 float sqrdist= minof(s0, s1, s2);
00243 // It is also VERY important to take the min of 3, to ensure the split in TileMode when Far1 vertex begin
00244 // to blend (see Patch::renderFar1() render).
00245
00246 // NB: VertexProgram geomorph take sqrdist= (SplitPoint - RefineCenter).sqrnorm();
00247 // It's OK because geomorph will start "far" after the split.
00248
00249 if(sqrdist< CLandscapeGlobals::TileDistFarSqr)
00250 {
00251 float nearLimit;
00252 nearLimit= CLandscapeGlobals::RefineThreshold * computeNearLimit();
00253 // If we are not so subdivided.
00254 if(ErrorMetric<nearLimit)
00255 {
00256 if(sqrdist< CLandscapeGlobals::TileDistNearSqr)
00257 {
00258 ErrorMetric=nearLimit;
00259 }
00260 else
00261 {
00262 // Smooth transition to the nearLimit of tesselation.
00263 float f= ( CLandscapeGlobals::TileDistFarSqr - sqrdist ) * CLandscapeGlobals::OOTileDistDeltaSqr;
00264 // sqr gives better result, by smoothing more the start of transition.
00265 f= sqr(f);
00266 f= sqr(f);
00267 ErrorMetric= ErrorMetric + (nearLimit-ErrorMetric)*f;
00268
00269 // If threshold is big like 0.5, transition is still hard, and pops occurs. But The goal is
00270 // 0.005 and less, so don't bother.
00271 }
00272 }
00273 }
00274 }
|
|
|
Definition at line 675 of file tessellation.cpp. References allocTileUv(), buildTileFaces(), checkCreateFillTileVB(), copyTileUv(), FBase, IdUvBase, IdUvLeft, IdUvRight, initTileUvDLM(), initTileUvLightmap(), initTileUvRGBA(), Level, NL3D_MAX_TILE_FACE, NL3D_MAX_TILE_PASS, NL3D_TILE_PASS_ADD, NL3D_TILE_PASS_LIGHTMAP, NL3D_TILE_PASS_RGB0, NL3D_TILE_PASS_RGB1, NL3D_TILE_PASS_RGB2, nlassert, NL3D::CPatch::OrderS, NL3D::CPatch::OrderT, NL3D::CTileMaterial::Pass, Patch, NL3D::CRdrTileId::PatchRdrPass, PVBase, PVLeft, PVRight, NL3D::CParamCoord::S, sint, NL3D::CParamCoord::T, TileFaces, TileId, NL3D::CPatch::TileLimitLevel, NL3D::CRdrTileId::TileMaterial, TileMaterial, NL3D::CTileMaterial::TileS, and NL3D::CTileMaterial::TileT. Referenced by recreateTileUvs(), and split().
00676 {
00677 // 0. Compute TileId.
00678 //-------------------
00679 // Square Order Patch assumption: assume that when a CTessFace become a tile, his base can ONLY be diagonal...
00680 /* a Patch:
00681 A ________
00682 |\ /|
00683 | \ / |
00684 C|__\B_/ |
00685 | / \ |
00686 | / \ |
00687 |/______\|
00688
00689 Here, if OrderS*OrderT=2*2, ABC is a new CTessFace of a Tile, and AB is the diagonal of the tile.
00690 Hence the middle of the tile is the middle of AB.
00691
00692 C must be created, but A and B may be created or copied from neighbor.
00693 */
00694 CParamCoord middle(PVLeft,PVRight);
00695 sint ts= ((sint)middle.S * (sint)Patch->OrderS) / 0x8000;
00696 sint tt= ((sint)middle.T * (sint)Patch->OrderT) / 0x8000;
00697 TileId= tt*Patch->OrderS + ts;
00698
00699
00700 // 1. Compute Tile Material.
00701 //--------------------------
00702 // if base neighbor is already at TileLimitLevel just ptr-copy, else create the TileMaterial...
00703 nlassert(!FBase || FBase->Patch!=Patch || FBase->Level<=Patch->TileLimitLevel);
00704 bool copyFromBase;
00705 copyFromBase= (FBase && FBase->Patch==Patch);
00706 copyFromBase= copyFromBase && (FBase->Level==Patch->TileLimitLevel && FBase->TileMaterial!=NULL);
00707 // NB: because of delete/recreateTileUvs(), FBase->TileMaterial may be NULL, even if face is at good TileLimitLevel.
00708 if(copyFromBase)
00709 {
00710 TileMaterial= FBase->TileMaterial;
00711 nlassert(FBase->TileId== TileId);
00712 }
00713 else
00714 {
00715 sint i;
00716 TileMaterial= Patch->getLandscape()->newTileMaterial();
00717 TileMaterial->TileS= ts;
00718 TileMaterial->TileT= tt;
00719
00720 // Add this new material to the render list.
00721 Patch->appendTileMaterialToRenderList(TileMaterial);
00722
00723 // First, get a lightmap for this tile. NB: important to do this after appendTileMaterialToRenderList(),
00724 // because use TessBlocks.
00725 Patch->getTileLightMap(ts, tt, TileMaterial->Pass[NL3D_TILE_PASS_LIGHTMAP].PatchRdrPass);
00726
00727 // Fill pass of multi pass material.
00728 for(i=0;i<NL3D_MAX_TILE_PASS;i++)
00729 {
00730 // Get the correct render pass, according to the tile number, and the pass.
00731 if(i!=NL3D_TILE_PASS_LIGHTMAP)
00732 TileMaterial->Pass[i].PatchRdrPass= Patch->getTileRenderPass(TileId, i);
00733 }
00734
00735 // Fill Pass Info.
00736 for(i=0;i<NL3D_MAX_TILE_PASS;i++)
00737 {
00738 TileMaterial->Pass[i].TileMaterial= TileMaterial;
00739 }
00740
00741 // Do not append this tile to each RenderPass, done in preRender().
00742 }
00743
00744
00745 // 2. Compute Uvs.
00746 //----------------
00747 // NB: TileMaterial is already setup. Usefull for initTileUvLightmap() and initTileUvRGBA().
00748
00749 // First, must create The TileFaces, according to the TileMaterial passes.
00750 buildTileFaces();
00751
00752 // Must allocate the Base, and insert into list.
00753 allocTileUv(IdUvBase);
00754
00755
00756 // Init LightMap UV, in RGB0 pass, UV1..
00757 initTileUvLightmap(PVBase, middle, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvBase]->PUv1);
00758 // Init DLM Uv, in RGB0 pass, UV2.
00759 initTileUvDLM(PVBase, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvBase]->PUv2);
00760
00761 // Init UV RGBA, for all pass (but lightmap).
00762 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00763 {
00764 nlassert(i!=NL3D_TILE_PASS_LIGHTMAP);
00765 // If pass is valid
00766 if( TileMaterial->Pass[i].PatchRdrPass)
00767 {
00768 // Face must exist.
00769 nlassert(TileFaces[i]);
00770 // Compute RGB UV in UV0.
00771 initTileUvRGBA(i, false, PVBase, middle, TileFaces[i]->V[IdUvBase]->PUv0);
00772 // If transition tile, compute alpha UV in UV1.
00773 // Do it also for Additive, because may have Transition
00774 if(i== NL3D_TILE_PASS_RGB1 || i==NL3D_TILE_PASS_RGB2 || i==NL3D_TILE_PASS_ADD)
00775 initTileUvRGBA(i, true, PVBase, middle, TileFaces[i]->V[IdUvBase]->PUv1);
00776 }
00777 }
00778
00779 // UVs are computed, may create and fill VB.
00780 checkCreateFillTileVB(IdUvBase);
00781
00782
00783 // if base neighbor is already at TileLimitLevel just ptr-copy, else create the left/right TileUvs...
00784 if(copyFromBase)
00785 {
00786 // Just cross-copy the pointers.
00787 // Make Left near vertices be the Right vertices of FBase
00788 copyTileUv(IdUvLeft, FBase, IdUvRight);
00789 // Make Right near vertices be the Left vertices of FBase
00790 copyTileUv(IdUvRight, FBase, IdUvLeft);
00791 }
00792 else
00793 {
00794 // Must allocate the left/right uv (and insert into list).
00795 allocTileUv(IdUvLeft);
00796 allocTileUv(IdUvRight);
00797
00798
00799 // Init LightMap UV, in UvPass 0, UV1..
00800 initTileUvLightmap(PVLeft, middle, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvLeft]->PUv1);
00801 initTileUvLightmap(PVRight, middle, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvRight]->PUv1);
00802 // Init DLM Uv, in RGB0 pass, UV2.
00803 initTileUvDLM(PVLeft, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvLeft]->PUv2);
00804 initTileUvDLM(PVRight, TileFaces[NL3D_TILE_PASS_RGB0]->V[IdUvRight]->PUv2);
00805
00806 // Init UV RGBA!
00807 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00808 {
00809 nlassert(i!=NL3D_TILE_PASS_LIGHTMAP);
00810 // If pass is valid
00811 if(TileMaterial->Pass[i].PatchRdrPass)
00812 {
00813 // Face must exist.
00814 nlassert(TileFaces[i]);
00815 // Compute RGB UV in UV0.
00816 initTileUvRGBA(i, false, PVLeft, middle, TileFaces[i]->V[IdUvLeft]->PUv0);
00817 initTileUvRGBA(i, false, PVRight, middle, TileFaces[i]->V[IdUvRight]->PUv0);
00818 // If transition tile, compute alpha UV in UV1.
00819 // Do it also for Additive, because may have Transition
00820 if(i== NL3D_TILE_PASS_RGB1 || i==NL3D_TILE_PASS_RGB2 || i==NL3D_TILE_PASS_ADD)
00821 {
00822 initTileUvRGBA(i, true, PVLeft, middle, TileFaces[i]->V[IdUvLeft]->PUv1);
00823 initTileUvRGBA(i, true, PVRight, middle, TileFaces[i]->V[IdUvRight]->PUv1);
00824 }
00825 }
00826 }
00827
00828 // UVs are computed, may create and fill VB.
00829 checkCreateFillTileVB(IdUvLeft);
00830 checkCreateFillTileVB(IdUvRight);
00831 }
00832
00833 }
|
|
||||||||||||||||
|
Definition at line 466 of file tessellation.cpp. References NL3D_MAX_TILE_FACE, NL3D_TILE_PASS_RGB0, nlassert, sint, TileFaces, and NL3D::CTileFace::V. Referenced by computeTileMaterial(), and heritTileMaterial().
00467 {
00468 // TileFaces must have been build.
00469 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
00470
00471 // Since this a ptr-copy, no need to add/remove the renderlist of near vertices.
00472
00473 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00474 {
00475 if(TileFaces[i])
00476 {
00477 // The srcface should have the same tileFaces enabled.
00478 nlassert(srcFace->TileFaces[i]);
00479
00480 // copy from src.
00481 CTessNearVertex *copyNear;
00482 copyNear= srcFace->TileFaces[i]->V[srcId];
00483
00484 // copy to dst.
00485 TileFaces[i]->V[dstId]= copyNear;
00486 }
00487 }
00488 }
|
|
|
Definition at line 528 of file tessellation.cpp. References NL3D::CLandscape::deleteTileFace(), NL3D::CPatch::getLandscape(), NL3D_MAX_TILE_FACE, nlassert, NL3D::CTileMaterial::Pass, NL3D::CRdrTileId::PatchRdrPass, sint, and TileFaces. Referenced by deleteTileUvs(), doMerge(), and releaseTileMaterial().
00529 {
00530 nlassert(TileMaterial);
00531
00532 // Do nothgin for lightmap pass, of course.
00533 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00534 {
00535 if(TileMaterial->Pass[i].PatchRdrPass)
00536 {
00537 nlassert(TileFaces[i]);
00538 Patch->getLandscape()->deleteTileFace(TileFaces[i]);
00539 TileFaces[i]= NULL;
00540 }
00541 else
00542 {
00543 nlassert(TileFaces[i]==NULL);
00544 }
00545 }
00546 }
|
|
|
Definition at line 444 of file tessellation.cpp. References NL3D::CPatch::checkDeleteVertexVBNear(), NL3D::CLandscape::deleteTessNearVertex(), NL3D::CPatch::getLandscape(), NL3D_MAX_TILE_FACE, NL3D_TILE_PASS_RGB0, nlassert, NL3D::CPatch::removeNearVertexFromRenderList(), sint, TileFaces, and NL3D::CTileFace::V. Referenced by deleteTileUvs(), doMerge(), and releaseTileMaterial().
00445 {
00446 // TileFaces must still exist.
00447 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
00448
00449 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00450 {
00451 if(TileFaces[i])
00452 {
00453 CTessNearVertex *oldNear;
00454 oldNear= TileFaces[i]->V[id];
00455 TileFaces[i]->V[id]=NULL;
00456
00457 // May delete this vertex from VB.
00458 Patch->checkDeleteVertexVBNear(oldNear);
00459
00460 Patch->removeNearVertexFromRenderList(TileMaterial, oldNear);
00461 Patch->getLandscape()->deleteTessNearVertex(oldNear);
00462 }
00463 }
00464 }
|
|
|
Definition at line 2969 of file tessellation.cpp. References deleteTileFaces(), deleteTileUv(), emptyTileFaces(), FBase, IdUvBase, isLeaf(), Level, nlassert, releaseTileMaterial(), NL3D::CPatch::removeFaceFromTileRenderList(), sameTile(), SonLeft, SonRight, NL3D::CPatch::TileLimitLevel, and TileMaterial. Referenced by NL3D::CPatch::deleteTileUvs().
02970 {
02971 // NB: NearVertices are removed from renderlist with deleteTileUv (called in releaseTileMaterial()).
02972
02973 if(!isLeaf())
02974 {
02975 // Must delete the materials of leaves first.
02976 SonLeft->deleteTileUvs();
02977 SonRight->deleteTileUvs();
02978 if(SonLeft->Level== Patch->TileLimitLevel)
02979 {
02980 // Square patch assumption: the sons are not of the same TileId/Patch.
02981 nlassert(!sameTile(SonLeft, SonRight));
02982 // release tiles.
02983 SonLeft->releaseTileMaterial();
02984 SonRight->releaseTileMaterial();
02985 }
02986 else if(SonLeft->Level > Patch->TileLimitLevel)
02987 {
02988 nlassert(!FBase || !FBase->isLeaf());
02989
02990 // Delete Uv, only if not already done by the neighbor (ie neighbor has yet TileFaces!!).
02991 // But Always delete if neighbor exist and has not same tile as me.
02992 // NB: this work with rectangular neigbor patch, since sameTile() will return false if different patch.
02993 if(!FBase || !FBase->SonLeft->emptyTileFaces() || !sameTile(this, FBase))
02994 {
02995 SonLeft->deleteTileUv(IdUvBase);
02996 }
02997 // In all case, must delete the tilefaces of those face.
02998 SonLeft->deleteTileFaces();
02999 SonRight->deleteTileFaces();
03000 // For createTileUvs, it is important to mark those faces as NO TileMaterial.
03001 SonLeft->TileMaterial= NULL;
03002 SonRight->TileMaterial= NULL;
03003 }
03004 }
03005 else
03006 {
03007 // NB: this is done always BELOW tile creation (see above).
03008 // Do this only for tiles.
03009 if(TileMaterial)
03010 Patch->removeFaceFromTileRenderList(this);
03011 }
03012
03013 }
|
|
|
Definition at line 1604 of file tessellation.cpp. References NL3D::CLandscape::_MergePriorityList, NL3D::CLandscape::_SplitPriorityList, NL3D::CPatch::appendFaceToRenderList(), changeNeighbor(), NL3D::CPatch::checkDeleteVertexVBFar(), NL3D::CLandscape::deleteTessFace(), NL3D::CLandscape::deleteTessFarVertex(), NL3D::CLandscape::deleteTessVertex(), deleteTileFaces(), deleteTileUv(), FBase, FLeft, FRight, FVBase, NL3D::CPatch::getLandscape(), IdUvBase, NL3D::CTessFacePriorityList::insert(), isLeaf(), isRectangular(), Level, nlassert, Patch, releaseTileMaterial(), NL3D::CPatch::removeFaceFromRenderList(), NL3D::CPatch::removeFarVertexFromRenderList(), sameTile(), SonLeft, SonRight, NL3D::CPatch::TileLimitLevel, and VBase. Referenced by merge().
01605 {
01606 // Assume that canMerge() return true.
01607 // And Assume that !isLeaf().
01608 nlassert(!isLeaf());
01609
01610 if(!isRectangular())
01611 {
01612 // 1. Let's merge vertex.
01613 //-----------------------
01614 // Delete vertex, only if not already done by the neighbor (ie neighbor not already merged to a leaf).
01615 // NB: this work even if neigbor is rectnagular.
01616 if(!FBase || !FBase->isLeaf())
01617 Patch->getLandscape()->deleteTessVertex(SonLeft->VBase);
01618
01619 // Delete Far Vertex. Idem, but test too if != patch...
01620 if(!FBase || !FBase->isLeaf() || FBase->Patch!=Patch)
01621 {
01622 // May delete this vertex from VB.
01623 Patch->checkDeleteVertexVBFar(SonLeft->FVBase);
01624
01625 Patch->removeFarVertexFromRenderList(SonLeft->FVBase);
01626 Patch->getLandscape()->deleteTessFarVertex(SonLeft->FVBase);
01627 }
01628
01629
01630 // 2. Must remove sons from rdr list, and insert father.
01631 //------------------------------------------------------
01632 // Must do it BEFORE the TileFaces are released.
01633 // UGLY REFCOUNT SIDE EFFECT: do the append first.
01634 Patch->appendFaceToRenderList(this);
01635 Patch->removeFaceFromRenderList(SonLeft);
01636 Patch->removeFaceFromRenderList(SonRight);
01637
01638
01639 // 3. Let's merge Uv.
01640 //-------------------
01641 // Delete Uv.
01642 // Must do it for this and FBase separately, since they may not have same tile level (if != patch).
01643 if(SonLeft->Level== Patch->TileLimitLevel)
01644 {
01645 // Square patch assumption: the sons are not of the same TileId/Patch.
01646 nlassert(!sameTile(SonLeft, SonRight));
01647 // release tiles: NearVertices, TileFaces, and TileMaterial.
01648 SonLeft->releaseTileMaterial();
01649 SonRight->releaseTileMaterial();
01650 }
01651 else if(SonLeft->Level > Patch->TileLimitLevel)
01652 {
01653 // Delete Uv, only if not already done by the neighbor (ie neighbor not already merged to a leaf).
01654 // But Always delete if neighbor exist and has not same tile as me.
01655 // NB: this work with rectangular neigbor patch, since sameTile() will return false if different patch.
01656 if(!FBase || !FBase->isLeaf() || !sameTile(this, FBase))
01657 {
01658 SonLeft->deleteTileUv(IdUvBase);
01659 }
01660 // In all case, must delete the tilefaces of those face.
01661 SonLeft->deleteTileFaces();
01662 SonRight->deleteTileFaces();
01663 }
01664
01665
01666 // 4. Let's merge Face.
01667 //-------------------
01668 // Change father 's neighbor pointers.
01669 FLeft= SonLeft->FBase;
01670 if(FLeft) FLeft->changeNeighbor(SonLeft, this);
01671 FRight= SonRight->FBase;
01672 if(FRight) FRight->changeNeighbor(SonRight, this);
01673 // delete sons.
01674 Patch->getLandscape()->deleteTessFace(SonLeft);
01675 Patch->getLandscape()->deleteTessFace(SonRight);
01676 SonLeft=NULL;
01677 SonRight=NULL;
01678
01679 // If not already done, merge the neighbor.
01680 if(FBase!=NULL && !FBase->isLeaf())
01681 {
01682 FBase->doMerge();
01683 }
01684
01685 }
01686 else
01687 {
01688 // Rectangular case.
01689 // Since minimum Order is 2, Sons of rectangular face are NEVER at TileLimitLevel. => no Uv merge to do.
01690 nlassert(SonLeft->Level< Patch->TileLimitLevel);
01691 nlassert(FBase);
01692
01693 // 1. Let's merge vertex.
01694 //-----------------------
01695 // Delete vertex, only if not already done by the neighbor (ie neighbor not already merged to a leaf).
01696 // NB: this work even if neigbor is rectangular (see tesselation rules in splitRectangular()).
01697 if(!FLeft || !FLeft->isLeaf())
01698 Patch->getLandscape()->deleteTessVertex(SonLeft->VBase);
01699
01700 // Delete Far Vertex. Rect patch: neightb must be of a != pathc as me => must delete FarVertex.
01701 nlassert(!FLeft || FLeft->Patch!=Patch);
01702 // May delete this vertex from VB.
01703 Patch->checkDeleteVertexVBFar(SonLeft->FVBase);
01704
01705 Patch->removeFarVertexFromRenderList(SonLeft->FVBase);
01706 Patch->getLandscape()->deleteTessFarVertex(SonLeft->FVBase);
01707
01708
01709 // 2. Must remove sons from rdr list, and insert father.
01710 //------------------------------------------------------
01711 // UGLY REFCOUNT SIDE EFFECT: do the append first.
01712 Patch->appendFaceToRenderList(this);
01713 Patch->removeFaceFromRenderList(SonLeft);
01714 Patch->removeFaceFromRenderList(SonRight);
01715
01716
01717 // 3. Let's merge Face.
01718 //-------------------
01719 // Change father 's neighbor pointers (see splitRectangular()).
01720 FRight= SonRight->FRight;
01721 if(FRight) FRight->changeNeighbor(SonRight, this);
01722 // delete sons.
01723 Patch->getLandscape()->deleteTessFace(SonLeft);
01724 Patch->getLandscape()->deleteTessFace(SonRight);
01725 SonLeft=NULL;
01726 SonRight=NULL;
01727
01728 // First, do it for my rectangular co-worker FBase (if not already done).
01729 if(!FBase->isLeaf())
01730 {
01731 FBase->doMerge();
01732 }
01733 // If not already done, merge the neighbor.
01734 if(FLeft!=NULL && !FLeft->isLeaf())
01735 {
01736 FLeft->doMerge();
01737 }
01738 }
01739
01740
01741 // Update priority list.
01742 //------------------------------------------------------
01743 // Since we are freshly merged, unlink from any list, and link to the SplitPriorityList, because must look
01744 // now when we should split again.
01745 Patch->getLandscape()->_SplitPriorityList.insert(0, 0, this);
01746
01747 // since we are now merged maybe re-insert father in priority list.
01748 if(Father)
01749 {
01750 nlassert(!Father->isLeaf());
01751 // If sons of father are both leaves (ie this, and the other (complexe case if rectangle) )
01752 if( Father->SonLeft->isLeaf() && Father->SonRight->isLeaf() )
01753 {
01754 Patch->getLandscape()->_MergePriorityList.insert(0, 0, Father);
01755 }
01756 }
01757
01758 }
|
|
|
Definition at line 549 of file tessellation.cpp. References NL3D_MAX_TILE_FACE, sint, and TileFaces. Referenced by deleteTileUvs().
00550 {
00551 // Do nothgin for lightmap pass, of course.
00552 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00553 {
00554 // Some TileFace exist??
00555 if(TileFaces[i])
00556 return false;
00557 }
00558
00559 return true;
00560 }
|
|
|
Definition at line 2412 of file tessellation.cpp. References CantMergeFace, FBase, FLeft, isLeaf(), isRectangular(), merge(), RecursMarkForceMerge, SonLeft, and SonRight. Referenced by forceMergeAtTileLevel(), and NL3D::CPatch::unbind().
02413 {
02414 if(this== &CantMergeFace)
02415 return;
02416
02417 if(!isLeaf())
02418 {
02419 // First, force merge of Sons and neighbor sons, to have a diamond configuration.
02420 SonLeft->forceMerge();
02421 SonRight->forceMerge();
02422
02423 // forceMerge of necessary neighbors.
02424 RecursMarkForceMerge=true;
02425 if(!isRectangular())
02426 {
02427 if(FBase && !FBase->RecursMarkForceMerge)
02428 FBase->forceMerge();
02429 }
02430 else
02431 {
02432 // Rectangular case. May have a longer propagation...
02433 if(FBase && !FBase->RecursMarkForceMerge)
02434 FBase->forceMerge();
02435 if(FLeft && !FLeft->RecursMarkForceMerge)
02436 FLeft->forceMerge();
02437 }
02438 RecursMarkForceMerge=false;
02439
02440 // If still a parent, merge.
02441 if(!isLeaf())
02442 merge();
02443 }
02444 }
|
|
|
Definition at line 2448 of file tessellation.cpp. References CantMergeFace, forceMerge(), isLeaf(), SonLeft, SonRight, and NL3D::CPatch::TileLimitLevel. Referenced by NL3D::CPatch::forceMergeAtTileLevel().
02449 {
02450 if(this== &CantMergeFace)
02451 return;
02452
02453 if(!isLeaf())
02454 {
02455 SonLeft->forceMergeAtTileLevel();
02456 SonRight->forceMergeAtTileLevel();
02457 }
02458 else
02459 {
02460 // If we are at tile subdivision, we must force our sons to merge.
02461 if(Level==Patch->TileLimitLevel)
02462 forceMerge();
02463 }
02464 }
|
|
||||||||||||||||
|
Definition at line 3101 of file tessellation.cpp. References computeTesselatedPos(), NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), isLeaf(), isRectangular(), PVBase, PVLeft, PVRight, NLMISC::CVector::set(), sint, SonLeft, SonRight, NLMISC::CUV::U, NLMISC::CUV::V, NLMISC::CVector::x, and NLMISC::CVector::y. Referenced by NL3D::CPatch::getTesselatedPos().
03102 {
03103 CVector uvPos(uv.U, uv.V, 0);
03104
03105 // may verif if uv is In this triangle. supposed true if rectangular branch.
03106 if(verifInclusion && !(isRectangular() && !isLeaf()) )
03107 {
03108 CVector uvs[3];
03109 uvs[0].set( PVBase.getS(), PVBase.getT(), 0);
03110 uvs[1].set( PVLeft.getS(), PVLeft.getT(), 0);
03111 uvs[2].set( PVRight.getS(), PVRight.getT(), 0);
03112 for(sint i=0; i<3; i++)
03113 {
03114 CVector dUv= uvs[(i+1)%3] - uvs[i];
03115 CVector normalUv(dUv.y, -dUv.x, 0);
03116 // if out this 2D plane, uv is out this triangle
03117 if(normalUv * (uvPos-uvs[i]) <0)
03118 return;
03119 }
03120 }
03121
03122 // compute tesselated pos in this face.
03123 if(isLeaf())
03124 // ok, no more sons, let's do it.
03125 computeTesselatedPos(uv, ret);
03126 else
03127 {
03128 // must subdivide.
03129 // if we are rectangular (strange tesselation), must test in both leaves, else, choose only one.
03130 if(isRectangular())
03131 {
03132 SonLeft->getTesselatedPos(uv, true, ret);
03133 SonRight->getTesselatedPos(uv, true, ret);
03134 }
03135 else
03136 {
03137 // Compute the uv plane which separate the 2 leaves.
03138 CVector uvBase, uvMiddle;
03139 uvBase.set ( PVBase.getS(), PVBase.getT(), 0);
03140 uvMiddle.set( SonLeft->PVBase.getS(), SonLeft->PVBase.getT(), 0);
03141 CVector dUv= uvMiddle - uvBase;
03142 CVector normalUv(dUv.y, -dUv.x, 0);
03143 // choose what leaf to recurs.
03144 if(normalUv * (uvPos - uvBase) <0)
03145 SonLeft->getTesselatedPos(uv, false, ret);
03146 else
03147 SonRight->getTesselatedPos(uv, false, ret);
03148
03149 }
03150 }
03151
03152 }
|
|
||||||||||||
|
Definition at line 297 of file tessellation.h. References hasVertex().
|
|
|
Definition at line 296 of file tessellation.h. References v, VBase, VLeft, and VRight. Referenced by hasEdge().
|
|
|
Definition at line 3053 of file tessellation.cpp. References allocTileUv(), buildTileFaces(), checkCreateFillTileVB(), copyTileUv(), FBase, heritTileUv(), IdUvBase, IdUvLeft, IdUvRight, isLeaf(), sameTile(), SonLeft, SonRight, TileId, and TileMaterial. Referenced by recreateTileUvs(), and split().
03054 {
03055 SonLeft->TileMaterial= TileMaterial;
03056 SonLeft->TileId= TileId;
03057 SonLeft->buildTileFaces();
03058 SonLeft->copyTileUv(IdUvLeft, this, IdUvBase);
03059 SonLeft->copyTileUv(IdUvRight, this, IdUvLeft);
03060
03061 SonRight->TileMaterial= TileMaterial;
03062 SonRight->TileId= TileId;
03063 SonRight->buildTileFaces();
03064 SonRight->copyTileUv(IdUvLeft, this, IdUvRight);
03065 SonRight->copyTileUv(IdUvRight, this, IdUvBase);
03066
03067 // Create, or link to the tileUv.
03068 // Try to link to a neighbor TileUv.
03069 // Can only work iff exist, and iff FBase is same patch, and same TileId.
03070 if(FBase!=NULL && !FBase->isLeaf() && FBase->SonLeft->TileMaterial!=NULL && sameTile(this, FBase) )
03071 {
03072 // Ok!! link to the (existing) TileUv.
03073 // FBase->SonLeft!=NULL since FBase->isLeaf()==false.
03074 SonLeft->copyTileUv(IdUvBase, FBase->SonLeft, IdUvBase);
03075 SonRight->copyTileUv(IdUvBase, FBase->SonLeft, IdUvBase);
03076 }
03077 else
03078 {
03079 // Allocate a new vertex, and copy it to SonLeft and SonRight.
03080 SonLeft->allocTileUv(IdUvBase);
03081 SonRight->copyTileUv(IdUvBase, SonLeft, IdUvBase);
03082
03083 // Fill the new near vertex, with middle of Left/Right father.
03084 SonLeft->heritTileUv(this);
03085
03086 // UVs are computed, may create and fill VB.
03087 SonLeft->checkCreateFillTileVB(IdUvBase);
03088 }
03089
03090 }
|
|
|
Definition at line 490 of file tessellation.cpp. References IdUvBase, IdUvLeft, IdUvRight, NL3D::CTessNearVertex::initMiddleUv(), NL3D_MAX_TILE_FACE, NL3D_TILE_PASS_RGB0, nlassert, sint, TileFaces, and NL3D::CTileFace::V. Referenced by heritTileMaterial().
00491 {
00492 // TileFaces must have been build.
00493 nlassert(TileFaces[NL3D_TILE_PASS_RGB0]);
00494
00495 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00496 {
00497 if(TileFaces[i])
00498 {
00499 // The baseface should have the same tileFaces enabled.
00500 nlassert(baseFace->TileFaces[i]);
00501 // VBase should be allocated.
00502 nlassert(TileFaces[i]->V[IdUvBase]);
00503 TileFaces[i]->V[IdUvBase]->initMiddleUv(
00504 *baseFace->TileFaces[i]->V[IdUvLeft], *baseFace->TileFaces[i]->V[IdUvRight]);
00505 }
00506 }
00507 }
|
|
||||||||||||
|
Definition at line 655 of file tessellation.cpp. References NL3D::CPatch::_DLMContext, NL3D::CPatchDLMContext::DLMUBias, NL3D::CPatchDLMContext::DLMUScale, NL3D::CPatchDLMContext::DLMVBias, NL3D::CPatchDLMContext::DLMVScale, NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), nlassert, NLMISC::CUV::U, and NLMISC::CUV::V. Referenced by computeTileMaterial().
00656 {
00657 // get the dlm context from the patch.
00658 CPatchDLMContext *dlmCtx= Patch->_DLMContext;
00659 // mmust exist at creation of the tile.
00660 nlassert(dlmCtx);
00661
00662 // get coord in 0..1 range, along the patch.
00663 uv.U= pointCoord.getS();
00664 uv.V= pointCoord.getT();
00665
00666 // ScaleBias according to the context.
00667 uv.U*= dlmCtx->DLMUScale;
00668 uv.V*= dlmCtx->DLMVScale;
00669 uv.U+= dlmCtx->DLMUBias;
00670 uv.V+= dlmCtx->DLMVBias;
00671 }
|
|
||||||||||||||||
|
Definition at line 636 of file tessellation.cpp. References NL3D::CPatch::getTileLightMapUvInfo(), NL3D::CParamCoord::S, NL3D::CParamCoord::T, NL3D::CTileMaterial::TileS, NL3D::CTileMaterial::TileT, NLMISC::CUV::U, NLMISC::CUV::V, NLMISC::CVector::x, NLMISC::CVector::y, and NLMISC::CVector::z. Referenced by computeTileMaterial().
00637 {
00638 // Get good coordinate according to patch orientation.
00639 uv.U= pointCoord.S<=middle.S? 0.0f: 1.0f;
00640 uv.V= pointCoord.T<=middle.T? 0.0f: 1.0f;
00641
00642 // Get Tile Lightmap Uv info: bias and scale.
00643 CVector uvScaleBias;
00644 Patch->getTileLightMapUvInfo(TileMaterial->TileS, TileMaterial->TileT, uvScaleBias);
00645
00646 // Scale the UV.
00647 uv.U*= uvScaleBias.z;
00648 uv.V*= uvScaleBias.z;
00649 uv.U+= uvScaleBias.x;
00650 uv.V+= uvScaleBias.y;
00651 }
|
|
||||||||||||||||||||||||
|
Definition at line 565 of file tessellation.cpp. References alpha, NL3D::CPatch::getTileUvInfo(), NL3D::CParamCoord::S, sint, NL3D::CParamCoord::T, TileId, NLMISC::CUV::U, uint8, v, NLMISC::CUV::V, NLMISC::CVector::x, NLMISC::CVector::y, and NLMISC::CVector::z. Referenced by computeTileMaterial().
00566 {
00567 // Get good coordinate according to patch orientation.
00568 uv.U= pointCoord.S<=middle.S? 0.0f: 1.0f;
00569 uv.V= pointCoord.T<=middle.T? 0.0f: 1.0f;
00570
00571 // Get Tile Uv info: orientation and scale.
00572 uint8 orient;
00573 CVector uvScaleBias;
00574 bool is256;
00575 uint8 uvOff;
00576 Patch->getTileUvInfo(TileId, pass, alpha, orient, uvScaleBias, is256, uvOff);
00577
00578 // Orient the UV.
00579 float u= uv.U;
00580 float v= uv.V;
00581 // Speed rotation.
00582 switch(orient)
00583 {
00584 case 0:
00585 uv.U= u;
00586 uv.V= v;
00587 break;
00588 case 1:
00589 uv.U= 1-v;
00590 uv.V= u;
00591 break;
00592 case 2:
00593 uv.U= 1-u;
00594 uv.V= 1-v;
00595 break;
00596 case 3:
00597 uv.U= v;
00598 uv.V= 1-u;
00599 break;
00600 }
00601
00602 // Do the 256x256.
00603 if(is256)
00604 {
00605 uv*= 0.5;
00606 if(uvOff==2 || uvOff==3)
00607 uv.U+= 0.5;
00608 if(uvOff==1 || uvOff==2)
00609 uv.V+= 0.5;
00610 }
00611
00612
00613 // Do the HalfPixel scale bias.
00614 float hBiasXY, hBiasZ;
00615 if(is256)
00616 {
00617 hBiasXY= CLandscapeGlobals::TilePixelBias256;
00618 hBiasZ = CLandscapeGlobals::TilePixelScale256;
00619 }
00620 else
00621 {
00622 hBiasXY= CLandscapeGlobals::TilePixelBias128;
00623 hBiasZ = CLandscapeGlobals::TilePixelScale128;
00624 }
00625
00626
00627 // Scale the UV.
00628 uv.U*= uvScaleBias.z*hBiasZ;
00629 uv.V*= uvScaleBias.z*hBiasZ;
00630 uv.U+= uvScaleBias.x+hBiasXY;
00631 uv.V+= uvScaleBias.y+hBiasXY;
00632 }
|
|
|
Definition at line 294 of file tessellation.h. References SonLeft. Referenced by appendTessellationLeaves(), averageTesselationVertices(), NL3D::CPatch::bind(), canMerge(), deleteTileUvs(), doMerge(), forceMerge(), forceMergeAtTileLevel(), getTesselatedPos(), heritTileMaterial(), linkTessFaceWithEdge(), merge(), recreateTileUvs(), refineAll(), refreshTesselationGeometry(), NL3D::CPatch::release(), split(), splitRectangular(), unbind(), NL3D::CPatch::unbind(), updateBind(), updateBindAndSplit(), updateBindEdge(), updateRefineMerge(), and updateRefineSplit().
00294 {return SonLeft==NULL;}
|
|
|
Definition at line 2954 of file tessellation.cpp. References NL3D::CPatch::SquareLimitLevel. Referenced by averageTesselationVertices(), canMerge(), computeSplitPoint(), doMerge(), forceMerge(), getTesselatedPos(), split(), splitRectangular(), unbind(), updateBindAndSplit(), and updateBindEdge().
|
|
|
unlinkInPList, then link this node to the root of a list.
Definition at line 49 of file tess_face_priority_list.cpp. References NL3D::CTessFacePListNode::_NextTessFaceInPList, and NL3D::CTessFacePListNode::_PrecTessFaceInPList. Referenced by NL3D::CLandscape::newTessFace().
00050 {
00051 // unlink old list from me.
00052 _PrecTessFaceInPList->_NextTessFaceInPList= _NextTessFaceInPList;
00053 _NextTessFaceInPList->_PrecTessFaceInPList= _PrecTessFaceInPList;
00054
00055 // link me to the list.
00056 _PrecTessFaceInPList= &root;
00057 _NextTessFaceInPList= root._NextTessFaceInPList;
00058 // link the list to me.
00059 root._NextTessFaceInPList->_PrecTessFaceInPList= this;
00060 root._NextTessFaceInPList= this;
00061 /*
00062 NB if list was empty (this, this), then
00063 _PrecTessFaceInPList= &root
00064 _NextTessFaceInPList= root._NextTessFaceInPList= &root !
00065 root._NextTessFaceInPList->_PrecTessFaceInPList= this; => root._PrecTessFaceInPList= this
00066 root._NextTessFaceInPList= this
00067 */
00068 }
|
|
||||||||||||||||
|
Definition at line 2904 of file tessellation.cpp. References FBase, FLeft, FRight, NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), isLeaf(), NL3D::matchEdge(), nlassert, PVBase, PVLeft, PVRight, SonLeft, and SonRight. Referenced by NL3D::CPatch::linkTessFaceWithEdge().
02905 {
02906 // Compute 0,1 coords of 3 patch coords.
02907 CVector2f vb( PVBase.getS(), PVBase.getT() );
02908 CVector2f vl( PVLeft.getS(), PVLeft.getT() );
02909 CVector2f vr( PVRight.getS(), PVRight.getT() );
02910
02911 // Search if one of the 3 edges of this triangle match the wanted edge.
02912 // Base Edge
02913 if(matchEdge(uv0, uv1, vl, vr))
02914 {
02915 // If leaf, check if unbound (else ptr is invalid)
02916 nlassert(FBase==NULL || !isLeaf());
02917 FBase= linkTo;
02918 return this;
02919 }
02920 // Left Edge
02921 if(matchEdge(uv0, uv1, vb, vl))
02922 {
02923 // If leaf, check if unbound (else ptr is invalid)
02924 nlassert(FLeft==NULL || !isLeaf());
02925 FLeft= linkTo;
02926 return this;
02927 }
02928 // Right Edge
02929 if(matchEdge(uv0, uv1, vb, vr))
02930 {
02931 // If leaf, check if unbound (else ptr is invalid)
02932 nlassert(FRight==NULL || !isLeaf());
02933 FRight= linkTo;
02934 return this;
02935 }
02936
02937
02938 // If not found here, recurs to children
02939 CTessFace *ret= NULL;
02940 if( !isLeaf() )
02941 {
02942 ret= SonLeft->linkTessFaceWithEdge(uv0, uv1, linkTo);
02943 // if no found in this branch, recusr right branch.
02944 if(!ret)
02945 ret= SonRight->linkTessFaceWithEdge(uv0, uv1, linkTo);
02946 }
02947
02948 // return the result from subBranchs
02949 return ret;
02950 }
|
|
|
Definition at line 1762 of file tessellation.cpp. References canMerge(), doMerge(), isLeaf(), NL3D_PROFILE_LAND_ADD, nlassert, and NL3D::ProfNMerges. Referenced by forceMerge(), refineAll(), and updateRefineMerge().
01763 {
01764 // Must not be a leaf.
01765 nlassert(!isLeaf());
01766
01767 // 0. Verify if merge is posible.
01768 //----------------------------
01769 if(!canMerge(false))
01770 return false;
01771
01772 NL3D_PROFILE_LAND_ADD(ProfNMerges, 1);
01773
01774 // 1. Let's merge the face.
01775 //-----------------------
01776 // Propagation is done in doMerge().
01777 doMerge();
01778
01779 return true;
01780 }
|
|
|
Definition at line 84 of file tess_face_priority_list.h. References NL3D::CTessFacePListNode::_NextTessFaceInPList. Referenced by NL3D::CTessFacePriorityList::CRollingTable::clearRollTableEntry(), and NL3D::CLandscape::refine().
00084 {return _NextTessFaceInPList;}
|
|
|
get next ptr. next==this if list empty.
Definition at line 83 of file tess_face_priority_list.h. References NL3D::CTessFacePListNode::_PrecTessFaceInPList.
00083 {return _PrecTessFaceInPList;}
|
|
|
Definition at line 3017 of file tessellation.cpp. References NL3D::CPatch::appendFaceToTileRenderList(), computeTileMaterial(), heritTileMaterial(), isLeaf(), Level, SonLeft, SonRight, and NL3D::CPatch::TileLimitLevel. Referenced by NL3D::CPatch::recreateTileUvs().
03018 {
03019 // NB: NearVertices are append to renderlist with allocTileUv (called in computeTileMaterial()/heritTileMaterial()).
03020
03021 if(!isLeaf())
03022 {
03023 // Must recreate the materials of parent first.
03024
03025 // There is no problem with rectangular patch, since tiles are always squares.
03026 // If new tile ....
03027 if(SonLeft->Level==Patch->TileLimitLevel)
03028 {
03029 SonLeft->computeTileMaterial();
03030 SonRight->computeTileMaterial();
03031 }
03032 // else Tile herit.
03033 else if(SonLeft->Level > Patch->TileLimitLevel)
03034 {
03035 heritTileMaterial();
03036 }
03037
03038 SonLeft->recreateTileUvs();
03039 SonRight->recreateTileUvs();
03040 }
03041 else
03042 {
03043 // NB: this is done always AFTER tile creation (see above).
03044 // Do this only for tiles.
03045 if(TileMaterial)
03046 Patch->appendFaceToTileRenderList(this);
03047 }
03048 }
|
|
|
refine the node, and his sons. Refine all nodes.
Definition at line 1783 of file tessellation.cpp. References canMerge(), ErrorMetric, isLeaf(), merge(), NL3D_PROFILE_LAND_ADD, NL3D::ProfNRefineComputeFaces, NL3D::ProfNRefineFaces, NL3D::ProfNRefineLeaves, SonLeft, SonRight, split(), NL3D::CPatch::TileLimitLevel, and updateErrorMetric(). Referenced by NL3D::CPatch::refineAll().
01784 {
01785 NL3D_PROFILE_LAND_ADD(ProfNRefineFaces, 1);
01786 NL3D_PROFILE_LAND_ADD(ProfNRefineLeaves, isLeaf()?1:0);
01787
01788 /*
01789 if(ps<RefineThreshold), the face must be merged (ie have no leaves).
01790 if(ps E [RefineThreshold, RefineTreshold*2]), the face must be splitted (ave leaves), and is geomorphed.
01791 if(ps>RefineThreshold*2), the face is fully splitted/geomoprhed (tests reported on sons...).
01792 */
01793
01794 // Test for Split or merge.
01795 //-----------------------
01796 {
01797 NL3D_PROFILE_LAND_ADD(ProfNRefineComputeFaces, 1);
01798
01799 updateErrorMetric();
01800 float ps=ErrorMetric;
01801 ps*= CLandscapeGlobals::OORefineThreshold;
01802 // 1.0f is the point of split().
01803 // 2.0f is the end of geomorph.
01804
01805
01806 // Test split/merge.
01807 //---------------------
01808 // If wanted, not already done, and limit not reached, split().
01809 if(isLeaf())
01810 {
01811 if(ps>1.0f && Level< (Patch->TileLimitLevel + CLandscapeGlobals::TileMaxSubdivision) )
01812 split();
01813 }
01814 else
01815 {
01816 // Else, if splitted, must merge (if not already the case).
01817 if(ps<1.0f)
01818 {
01819 // Merge only if agree, and neighbors agree.
01820 // canMerge() test all the good thing: FBase==CantMergeFace, or this is rectangular etc...
01821 // The test is propagated to neighbors.
01822 if(canMerge(true))
01823 {
01824 merge();
01825 }
01826 }
01827 }
01828 }
01829
01830 // Recurs.
01831 //-----------------------
01832 if(SonLeft)
01833 {
01834 SonLeft->refineAll();
01835 SonRight->refineAll();
01836 }
01837
01838 }
|
|
|
Definition at line 2519 of file tessellation.cpp. References NL3D::CPatch::computeVertex(), NL3D::CTessVertex::EndPos, NL3D::CPatch::extendTessBlockWithEndPos(), NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), isLeaf(), NL3D::CTessVertex::Pos, PVBase, SonLeft, SonRight, and VBase. Referenced by NL3D::CPatch::refreshTesselationGeometry().
02520 {
02521 // must enlarge the little tessBlock (if any), for clipping.
02522 Patch->extendTessBlockWithEndPos(this);
02523
02524 // If we are not splitted, no-op.
02525 if(isLeaf())
02526 return;
02527
02528
02529 /* NB: rectangular case: just need to take SonLeft->VBase, because my neighbor on FBase will compute his son
02530 on an other branch of the recurs call.
02531 */
02532 // re-compute this position (maybe with new noise geometry in Tile Edition).
02533 SonLeft->VBase->EndPos= Patch->computeVertex(SonLeft->PVBase.getS(), SonLeft->PVBase.getT());
02534 // overwrite cur Pos (NB: specialy hardcoded for Tile edition).
02535 SonLeft->VBase->Pos= SonLeft->VBase->EndPos;
02536
02537 // Do same thing for sons. NB: see above, we are not a leaf.
02538 SonLeft->refreshTesselationGeometry();
02539 SonRight->refreshTesselationGeometry();
02540 }
|
|
|
Definition at line 835 of file tessellation.cpp. References deleteTileFaces(), NL3D::CLandscape::deleteTileMaterial(), deleteTileUv(), FBase, NL3D::CPatch::getLandscape(), IdUvBase, IdUvLeft, IdUvRight, Level, nlassert, NL3D::CPatch::releaseTileLightMap(), NL3D::CPatch::removeTileMaterialFromRenderList(), NL3D::CPatch::TileLimitLevel, TileMaterial, NL3D::CTileMaterial::TileS, and NL3D::CTileMaterial::TileT. Referenced by deleteTileUvs(), and doMerge().
00836 {
00837 // Hence, must release the tile. TileUvBase is differnet for each of leaves.
00838 deleteTileUv(IdUvBase);
00839
00840 nlassert(!FBase || FBase->Level<=Patch->TileLimitLevel);
00841 if(FBase && FBase->Level==Patch->TileLimitLevel && FBase->TileMaterial!=NULL)
00842 {
00843 // Do not release Uvs, since neighbor need it...
00844 // But release faces.
00845 deleteTileFaces();
00846 // Do not release TileMaterial, since neighbor need it...
00847 TileMaterial= NULL;
00848 }
00849 else
00850 {
00851 // release Uvs.
00852 deleteTileUv(IdUvLeft);
00853 deleteTileUv(IdUvRight);
00854
00855 // After, release Tile faces.
00856 deleteTileFaces();
00857
00858 // Release the tile lightmap part. Do it before removeTileMaterialFromRenderList().
00859 Patch->releaseTileLightMap(TileMaterial->TileS, TileMaterial->TileT);
00860
00861 // Remove this material from the render list. DO it before deletion of course :).
00862 // NB: TileS/TileT still valid.
00863 Patch->removeTileMaterialFromRenderList(TileMaterial);
00864
00865 Patch->getLandscape()->deleteTileMaterial(TileMaterial);
00866 TileMaterial= NULL;
00867 }
00868 }
|
|
||||||||||||
|
Definition at line 368 of file tessellation.h. Referenced by deleteTileUvs(), doMerge(), and heritTileMaterial().
00369 {
00370 // WE CANNOT do this test, testing TileMaterial, because this one may be releleased by releaseMaterial() !!
00371 return (a->Patch==b->Patch && a->TileId==b->TileId);
00372 }
|
|
|
Definition at line 1283 of file tessellation.cpp. References NL3D::CLandscape::_MergePriorityList, NL3D::CPatch::appendFaceToRenderList(), NL3D::CPatch::appendFarVertexToRenderList(), changeNeighbor(), NL3D::CPatch::checkCreateVertexVBFar(), checkFillTileVB(), NL3D::CPatch::checkFillVertexVBFar(), computeNearLimit(), computeSplitPoint(), computeTileMaterial(), NL3D::CPatch::computeVertex(), NL3D::CTessVertex::EndPos, Father, FBase, FLeft, FRight, FVBase, FVLeft, FVRight, NL3D::CPatch::getLandscape(), NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), heritTileMaterial(), IdUvBase, NL3D::CTessFacePriorityList::insert(), isLeaf(), isRectangular(), Level, NL3D::CTessVertex::MaxFaceSize, NL3D::CTessVertex::MaxNearLimit, NL3D::CLandscape::newTessFace(), NL3D::CLandscape::newTessFarVertex(), NL3D::CLandscape::newTessVertex(), NL3D_PROFILE_LAND_ADD, nlassert, Patch, NL3D::CTessFarVertex::PCoord, NL3D::CTessVertex::Pos, NL3D::ProfNSplits, PVBase, PVLeft, PVRight, NL3D::CPatch::removeFaceFromRenderList(), Size, SonLeft, SonRight, splitRectangular(), NL3D::CTessFarVertex::Src, NL3D::CTessVertex::StartPos, NL3D::CPatch::TileLimitLevel, NL3D::CTessFacePListNode::unlinkInPList(), VBase, VLeft, and VRight. Referenced by refineAll(), splitRectangular(), updateBindAndSplit(), and updateRefineSplit().
01284 {
01285
01286 // 0. Some easy ending.
01287 //---------------------
01288 // Already splitted??
01289 if(!isLeaf())
01290 return;
01291 // Don't do this!!!
01292 //if(Level>=LS_MAXLEVEL)
01293 // return;
01294 // since split() may reach LS_MAXLEVEL, but enforce splits which outpass this stage!!
01295
01296 NL3D_PROFILE_LAND_ADD(ProfNSplits, 1);
01297
01298
01299 // Special Rectangular case.
01300 if(isRectangular())
01301 {
01302 splitRectangular(propagateSplit);
01303 return;
01304 }
01305
01306 // 1. Create sons, and update links.
01307 //----------------------------------
01308
01309 // create and bind Sons.
01310 SonLeft= Patch->getLandscape()->newTessFace();
01311 SonRight= Patch->getLandscape()->newTessFace();
01312
01313 // subdivision left.
01314 SonLeft->Patch= Patch;
01315 SonLeft->Father= this;
01316 SonLeft->Level= Level+1;
01317 SonLeft->Size= Size*0.5f;
01318 // subdivision right.
01319 SonRight->Patch= Patch;
01320 SonRight->Father= this;
01321 SonRight->Level= Level+1;
01322 SonRight->Size= Size*0.5f;
01323
01324
01325 // link Left Son.
01326 // link neighbor face.
01327 SonLeft->FBase= FLeft;
01328 if(FLeft) FLeft->changeNeighbor(this, SonLeft);
01329 SonLeft->FLeft= SonRight;
01330 SonLeft->FRight= NULL; // Temporary. updated later.
01331 // link neighbor vertex.
01332 SonLeft->VLeft= VBase;
01333 SonLeft->VRight= VLeft;
01334 // link neighbor Far vertex.
01335 SonLeft->FVLeft= FVBase;
01336 SonLeft->FVRight= FVLeft;
01337 // Patch coordinates.
01338 SonLeft->PVBase= CParamCoord(PVLeft, PVRight);
01339 SonLeft->PVLeft= PVBase;
01340 SonLeft->PVRight= PVLeft;
01341
01342 // linkRight Son.
01343 // link neighbor face.
01344 SonRight->FBase= FRight;
01345 if(FRight) FRight->changeNeighbor(this, SonRight);
01346 SonRight->FLeft= NULL; // Temporary. updated later.
01347 SonRight->FRight= SonLeft;
01348 // link neighbor vertex.
01349 SonRight->VLeft= VRight;
01350 SonRight->VRight= VBase;
01351 // link neighbor Far vertex.
01352 SonRight->FVLeft= FVRight;
01353 SonRight->FVRight= FVBase;
01354 // Patch coordinates.
01355 SonRight->PVBase= CParamCoord(PVLeft, PVRight);
01356 SonRight->PVLeft= PVRight;
01357 SonRight->PVRight= PVBase;
01358
01359
01360 // FBase->FBase==this. Must Doesn't change this. Used and Updated in section 5. ...
01361
01362
01363 // 2. Update/Create Vertex infos.
01364 //-------------------------------
01365
01366 // Must create/link *->VBase.
01367 if(FBase==NULL || FBase->isLeaf())
01368 {
01369 // The base neighbor is a leaf or NULL. So must create the new vertex.
01370 CTessVertex *newVertex= Patch->getLandscape()->newTessVertex();
01371 SonRight->VBase= newVertex;
01372 SonLeft->VBase= newVertex;
01373
01374 // Compute pos.
01375 newVertex->StartPos= (VLeft->EndPos + VRight->EndPos)/2;
01376 newVertex->EndPos= Patch->computeVertex(SonLeft->PVBase.getS(), SonLeft->PVBase.getT());
01377
01378 // Init Pos= InitialPos. Important in the case of enforced split.
01379 newVertex->Pos= newVertex->StartPos;
01380
01381 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
01382 newVertex->MaxFaceSize= Size;
01383 newVertex->MaxNearLimit= computeNearLimit();
01384 }
01385 else
01386 {
01387 // Else, get from neighbor.
01388 // NB: since *FBase is not a leaf, FBase->SonLeft!=NULL...
01389 // NB: this work with both rectangular and square triangles (see splitRectangular()).
01390 SonRight->VBase= FBase->SonLeft->VBase;
01391 SonLeft->VBase= FBase->SonLeft->VBase;
01392
01393 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
01394 SonLeft->VBase->MaxFaceSize= max( SonLeft->VBase->MaxFaceSize, Size);
01395 SonLeft->VBase->MaxNearLimit= max( SonLeft->VBase->MaxNearLimit, computeNearLimit());
01396 }
01397
01398
01399 // Must create/link *->FVBase.
01400 // HERE, we must create a FarVertex too if the neighbor is not of the same patch as me.
01401 if(FBase==NULL || FBase->isLeaf() || FBase->Patch!=Patch)
01402 {
01403 // The base neighbor is a leaf or NULL. So must create the new far vertex.
01404 CTessFarVertex *newFar= Patch->getLandscape()->newTessFarVertex();
01405 SonRight->FVBase= newFar;
01406 SonLeft->FVBase= newFar;
01407
01408 // Compute.
01409 newFar->Src= SonLeft->VBase;
01410 newFar->PCoord= SonLeft->PVBase;
01411
01412 // Append.
01413 Patch->appendFarVertexToRenderList(newFar);
01414
01415 // May Allocate/Fill VB.
01416 // NB: SonLeft->VBase->Pos is well computed and ready for the fill in VB.
01417 Patch->checkCreateVertexVBFar(newFar);
01418 Patch->checkFillVertexVBFar(newFar);
01419
01420 // For VertexProgram only, must refill the Far vertex of neighbor,
01421 // because MaxFaceSize, and MaxNearLimit may have change.
01422 if( CLandscapeGlobals::VertexProgramEnabled && ! (FBase==NULL || FBase->isLeaf()) )
01423 FBase->Patch->checkFillVertexVBFar(FBase->SonLeft->FVBase);
01424 }
01425 else
01426 {
01427 // Else, get from neighbor.
01428 // NB: since *FBase is not a leaf, FBase->SonLeft!=NULL...
01429 // NB: this work with both rectangular and square triangles (see splitRectangular()).
01430 SonRight->FVBase= FBase->SonLeft->FVBase;
01431 SonLeft->FVBase= FBase->SonLeft->FVBase;
01432
01433 // NB For VertexProgram only: no need to refill the Far vertex of neighbor, because neighbor is of same Patch
01434 // So MaxNearLimit and MaxFaceSize should be the same.
01435 }
01436
01437
01438 // 3. Update Tile infos.
01439 //----------------------
01440 // NB: must do it before appendFaceToRenderList().
01441 // NB: must do it after compute of SonLeft->VBase->Pos for good filling in VBuffer.
01442 // There is no problem with rectangular patch, since tiles are always squares.
01443 // If new tile ....
01444 if(SonLeft->Level==Patch->TileLimitLevel)
01445 {
01446 SonLeft->computeTileMaterial();
01447 SonRight->computeTileMaterial();
01448 }
01449 // else Tile herit.
01450 else if(SonLeft->Level > Patch->TileLimitLevel)
01451 {
01452 heritTileMaterial();
01453 }
01454
01455 // For Vertex program only
01456 if( CLandscapeGlobals::VertexProgramEnabled )
01457 {
01458 // if neighbor face splitted, and if 2 different patchs, we must update the Tile vertices
01459 // because MaxFaceSize and MaxNearLimit may have changed.
01460 if( FBase!=NULL && !FBase->isLeaf() && FBase->Patch!=Patch )
01461 {
01462 // If neighbors sons at tile level, must update their Tile vertices.
01463 if( FBase->SonLeft->Level >= FBase->Patch->TileLimitLevel )
01464 {
01465 FBase->SonLeft->checkFillTileVB(IdUvBase);
01466 FBase->SonRight->checkFillTileVB(IdUvBase);
01467 }
01468 }
01469 }
01470
01471
01472 // 4. Compute centers.
01473 //--------------------
01474 SonRight->computeSplitPoint();
01475 SonLeft->computeSplitPoint();
01476
01477
01478 // 5. Propagate, or link sons of base.
01479 //------------------------------------
01480 // If current face and FBase has sons, just links.
01481 if(FBase==NULL)
01482 {
01483 // Just update sons neighbors.
01484 SonLeft->FRight= NULL;
01485 SonRight->FLeft= NULL;
01486 }
01487 else if(!FBase->isLeaf())
01488 {
01489 CTessFace *toLeft, *toRight;
01490 CTessFace *fl, *fr;
01491 fl= SonLeft;
01492 fr= SonRight;
01493 toLeft= FBase->SonLeft;
01494 toRight= FBase->SonRight;
01495 // Cross connection of sons.
01496 if(!FBase->isRectangular())
01497 {
01498 // Case neigbhor is square.
01499 fl->FRight= toRight;
01500 fr->FLeft= toLeft;
01501 toLeft->FRight= fr;
01502 toRight->FLeft= fl;
01503 }
01504 else
01505 {
01506 // Case neigbhor is rectangular.
01507 fl->FRight= toLeft;
01508 fr->FLeft= toRight;
01509 toLeft->FLeft= fl;
01510 toRight->FLeft= fr;
01511 }
01512 }
01513 else if (propagateSplit)
01514 {
01515 // Warning: at each iteration, the pointer of FBase may change (because of split() which can change the neighbor
01516 // and so "this").
01517 while(FBase->isLeaf())
01518 FBase->split();
01519
01520 // There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.
01521 // And problems may arise because this face hasn't yet good connectivity.
01522 nlassert(SonLeft->isLeaf() && SonRight->isLeaf());
01523 }
01524
01525
01526 // 6. Must remove father from rdr list, and insert sons.
01527 //------------------------------------------------------
01528 // UGLY REFCOUNT SIDE EFFECT: do the append first.
01529 Patch->appendFaceToRenderList(SonLeft);
01530 Patch->appendFaceToRenderList(SonRight);
01531 Patch->removeFaceFromRenderList(this);
01532
01533
01534 // 7. Update priority list.
01535 //------------------------------------------------------
01536 // Since we are freshly splitted, unlink from any list, and link to the MergePriorityList, because must look
01537 // now when should merge.
01538 Patch->getLandscape()->_MergePriorityList.insert(0, 0, this);
01539
01540 // Since we are split, no need to test father for merge, because it cannot!
01541 if(Father)
01542 {
01543 // remove father from any priority list.
01544 Father->unlinkInPList();
01545 }
01546 }
|
|
|
Definition at line 911 of file tessellation.cpp. References NL3D::CLandscape::_MergePriorityList, NL3D::CPatch::appendFaceToRenderList(), NL3D::CPatch::appendFarVertexToRenderList(), changeNeighbor(), NL3D::CPatch::checkCreateVertexVBFar(), checkFillTileVB(), NL3D::CPatch::checkFillVertexVBFar(), computeNearLimit(), computeSplitPoint(), NL3D::CPatch::computeVertex(), NL3D::CTessVertex::EndPos, Father, FBase, FLeft, FRight, FVBase, FVLeft, FVRight, NL3D::CPatch::getLandscape(), NL3D::CParamCoord::getS(), NL3D::CParamCoord::getT(), IdUvBase, NL3D::CTessFacePriorityList::insert(), isLeaf(), isRectangular(), Level, NL3D::CTessVertex::MaxFaceSize, NL3D::CTessVertex::MaxNearLimit, NL3D::CLandscape::newTessFace(), NL3D::CLandscape::newTessFarVertex(), NL3D::CLandscape::newTessVertex(), nlassert, Patch, NL3D::CTessFarVertex::PCoord, NL3D::CTessVertex::Pos, PVBase, PVLeft, PVRight, NL3D::CPatch::removeFaceFromRenderList(), sint, Size, SonLeft, SonRight, split(), NL3D::CTessFarVertex::Src, NL3D::CTessVertex::StartPos, NL3D::CPatch::TileLimitLevel, NL3D::CTessFacePListNode::unlinkInPList(), VBase, VLeft, and VRight. Referenced by split().
00912 {
00913 CTessFace *f0= this;
00914 CTessFace *f1= FBase;
00915 // Rectangular case: FBase must exist.
00916 nlassert(f1);
00917
00918 // In rectangular case, we split at the same time this and FBase (f0 and f1).
00919
00920
00921 /*
00922 Tesselation is:
00923
00924 lt rt lt top rt
00925 --------------------- ---------------------
00926 |---- | |\ |\ |
00927 | ---- f1 | | \ f1l | \ f1r |
00928 | ---- | --> | \ | \ |
00929 | f0 ---- | | f0r \ | f0l \ |
00930 | ---| | \| \|
00931 --------------------- ---------------------
00932 lb rb lb bot rb
00933
00934 Why? For symetry and bind/split reasons: FBase->SonLeft->VBase is always the good vertex to take
00935 (see vertex binding).
00936 */
00937 CParamCoord pclt= f1->PVLeft;
00938 CParamCoord pclb= f0->PVBase;
00939 CParamCoord pcrt= f1->PVBase;
00940 CParamCoord pcrb= f1->PVRight;
00941 CTessVertex *vlt= f1->VLeft;
00942 CTessVertex *vlb= f0->VBase;
00943 CTessVertex *vrt= f1->VBase;
00944 CTessVertex *vrb= f1->VRight;
00945
00946 CTessFarVertex *farvlt= f1->FVLeft;
00947 CTessFarVertex *farvlb= f0->FVBase;
00948 CTessFarVertex *farvrt= f1->FVBase;
00949 CTessFarVertex *farvrb= f1->FVRight;
00950
00951
00952 // 1. create new vertices.
00953 //------------------------
00954
00955 // Create splitted vertices.
00956 CParamCoord pctop(f1->PVBase, f1->PVLeft);
00957 CParamCoord pcbot(f0->PVBase, f0->PVLeft);
00958 CTessVertex *vtop= NULL;
00959 CTessVertex *vbot= NULL;
00960 // Compute top.
00961 if(f1->FLeft==NULL || f1->FLeft->isLeaf())
00962 {
00963 // The base neighbor is a leaf or NULL. So must create the new vertex.
00964 vtop= Patch->getLandscape()->newTessVertex();
00965
00966 // Compute pos.
00967 vtop->StartPos= (f1->VLeft->EndPos + f1->VBase->EndPos)/2;
00968 vtop->EndPos= f1->Patch->computeVertex(pctop.getS(), pctop.getT());
00969 // Init Pos= InitialPos. Important in the case of enforced split.
00970 vtop->Pos= vtop->StartPos;
00971
00972 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
00973 vtop->MaxFaceSize= f1->Size;
00974 vtop->MaxNearLimit= f1->computeNearLimit();
00975 }
00976 else
00977 {
00978 // Else, get from neighbor.
00979 // NB: since *FLeft is not a leaf, FBase->SonLeft!=NULL...
00980 // NB: this work with both rectangular and square triangles.
00981 vtop= f1->FLeft->SonLeft->VBase;
00982
00983 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
00984 vtop->MaxFaceSize= max( vtop->MaxFaceSize, f1->Size);
00985 vtop->MaxNearLimit= max( vtop->MaxNearLimit, f1->computeNearLimit());
00986 }
00987 // Compute bot.
00988 if(f0->FLeft==NULL || f0->FLeft->isLeaf())
00989 {
00990 // The base neighbor is a leaf or NULL. So must create the new vertex.
00991 vbot= Patch->getLandscape()->newTessVertex();
00992
00993 // Compute pos.
00994 vbot->StartPos= (f0->VLeft->EndPos + f0->VBase->EndPos)/2;
00995 vbot->EndPos= Patch->computeVertex(pcbot.getS(), pcbot.getT());
00996 // Init Pos= InitialPos. Important in the case of enforced split.
00997 vbot->Pos= vbot->StartPos;
00998
00999 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
01000 vbot->MaxFaceSize= f0->Size;
01001 vbot->MaxNearLimit= f0->computeNearLimit();
01002 }
01003 else
01004 {
01005 // Else, get from neighbor.
01006 // NB: since *FLeft is not a leaf, FBase->SonLeft!=NULL...
01007 // NB: this work with both rectangular and square triangles.
01008 vbot= f0->FLeft->SonLeft->VBase;
01009
01010 // For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.
01011 vbot->MaxFaceSize= max( vbot->MaxFaceSize, f0->Size);
01012 vbot->MaxNearLimit= max( vbot->MaxNearLimit, f0->computeNearLimit());
01013 }
01014
01015 // In all case, must create new FarVertices, since rect split occurs on border!!
01016 CTessFarVertex *farvtop= Patch->getLandscape()->newTessFarVertex();
01017 CTessFarVertex *farvbot= Patch->getLandscape()->newTessFarVertex();
01018 farvtop->Src= vtop;
01019 farvbot->Src= vbot;
01020 farvtop->PCoord= pctop;
01021 farvbot->PCoord= pcbot;
01022 Patch->appendFarVertexToRenderList(farvtop);
01023 Patch->appendFarVertexToRenderList(farvbot);
01024 // May Allocate/Fill VB.
01025 // NB: vtop / vbot are well computed and ready for the fill in VB.
01026 Patch->checkCreateVertexVBFar(farvtop);
01027 Patch->checkFillVertexVBFar(farvtop);
01028 Patch->checkCreateVertexVBFar(farvbot);
01029 Patch->checkFillVertexVBFar(farvbot);
01030
01031 // For VertexProgram only, must refill the Far vertex of neighbor(s),
01032 // because MaxFaceSize, and MaxNearLimit may have change.
01033 if( CLandscapeGlobals::VertexProgramEnabled )
01034 {
01035 // f0
01036 if( ! (f0->FLeft==NULL || f0->FLeft->isLeaf()) )
01037 f0->FLeft->Patch->checkFillVertexVBFar(f0->FLeft->SonLeft->FVBase);
01038 // f1
01039 if( ! (f1->FLeft==NULL || f1->FLeft->isLeaf()) )
01040 f1->FLeft->Patch->checkFillVertexVBFar(f1->FLeft->SonLeft->FVBase);
01041 }
01042
01043
01044 // 2. Create sons, and update links.
01045 //----------------------------------
01046
01047 CTessFace *f0l, *f0r;
01048 CTessFace *f1l, *f1r;
01049
01050 // create and bind Sons.
01051 f0l= f0->SonLeft= Patch->getLandscape()->newTessFace();
01052 f0r= f0->SonRight= Patch->getLandscape()->newTessFace();
01053 f1l= f1->SonLeft= Patch->getLandscape()->newTessFace();
01054 f1r= f1->SonRight= Patch->getLandscape()->newTessFace();
01055
01056 // subdivision left.
01057 f0l->Patch= f0->Patch;
01058 f0l->Father= f0;
01059 f0l->Level= f0->Level+1;
01060 f0l->Size= f0->Size*0.5f;
01061 // subdivision right.
01062 f0r->Patch= f0->Patch;
01063 f0r->Father= f0;
01064 f0r->Level= f0->Level+1;
01065 f0r->Size= f0->Size*0.5f;
01066 // subdivision left.
01067 f1l->Patch= f1->Patch;
01068 f1l->Father= f1;
01069 f1l->Level= f1->Level+1;
01070 f1l->Size= f1->Size*0.5f;
01071 // subdivision right.
01072 f1r->Patch= f1->Patch;
01073 f1r->Father= f1;
01074 f1r->Level= f1->Level+1;
01075 f1r->Size= f1->Size*0.5f;
01076
01077 // Patch coordinates.
01078 f0r->PVRight= pclt;
01079 f0r->PVBase= pclb;
01080 f0r->PVLeft= pcbot;
01081 f1l->PVBase= pctop;
01082 f1l->PVLeft= f0r->PVRight;
01083 f1l->PVRight= f0r->PVLeft;
01084
01085 f0l->PVRight= pctop;
01086 f0l->PVBase= pcbot;
01087 f0l->PVLeft= pcrb;
01088 f1r->PVBase= pcrt;
01089 f1r->PVLeft= f0l->PVRight;
01090 f1r->PVRight= f0l->PVLeft;
01091
01092 // link existing vertex.
01093 f0r->VRight= vlt;
01094 f0r->VBase= vlb;
01095 f0r->VLeft= vbot;
01096 f1l->VBase= vtop;
01097 f1l->VLeft= f0r->VRight;
01098 f1l->VRight= f0r->VLeft;
01099
01100 f0l->VRight= vtop;
01101 f0l->VBase= vbot;
01102 f0l->VLeft= vrb;
01103 f1r->VBase= vrt;
01104 f1r->VLeft= f0l->VRight;
01105 f1r->VRight= f0l->VLeft;
01106
01107 // link Far vertices.
01108 f0r->FVRight= farvlt;
01109 f0r->FVBase= farvlb;
01110 f0r->FVLeft= farvbot;
01111 f1l->FVBase= farvtop;
01112 f1l->FVLeft= f0r->FVRight;
01113 f1l->FVRight= f0r->FVLeft;
01114
01115 f0l->FVRight= farvtop;
01116 f0l->FVBase= farvbot;
01117 f0l->FVLeft= farvrb;
01118 f1r->FVBase= farvrt;
01119 f1r->FVLeft= f0l->FVRight;
01120 f1r->FVRight= f0l->FVLeft;
01121
01122 // link neigbhor faces.
01123 f0r->FBase= f1l;
01124 f1l->FBase= f0r;
01125 f0l->FBase= f1r;
01126 f1r->FBase= f0l;
01127 f1l->FRight= f0l;
01128 f0l->FRight= f1l;
01129 f0r->FRight= f0->FRight;
01130 if(f0->FRight)
01131 f0->FRight->changeNeighbor(f0, f0r);
01132 f1r->FRight= f1->FRight;
01133 if(f1->FRight)
01134 f1->FRight->changeNeighbor(f1, f1r);
01135 // 4 links (all FLeft sons ) are stil invalid here.
01136 f0l->FLeft= NULL;
01137 f0r->FLeft= NULL;
01138 f1l->FLeft= NULL;
01139 f1r->FLeft= NULL;
01140
01141 // Neigbors pointers of undetermined splitted face are not changed. Must Doesn't change this.
01142 // Used and Updated in section 5. ...
01143
01144
01145 // 3. Update Tile infos.
01146 //----------------------
01147 // There is no update tileinfo with rectangular patch, since tiles are always squares. (TileLimitLevel>SquareLimitLevel).
01148
01149 // NB: but must test update of tile info for neighboring, ie 2 faces around the splits.
01150 // For Vertex program only
01151 if( CLandscapeGlobals::VertexProgramEnabled )
01152 {
01153 // if neighbor face splitted, and if 2 different patchs, we must update the Tile vertices
01154 // because MaxFaceSize and MaxNearLimit may have changed.
01155 if( f0->FLeft!=NULL && !f0->FLeft->isLeaf() && f0->FLeft->Patch!=Patch )
01156 {
01157 // If neighbors sons at tile level, must update their Tile vertices.
01158 if( f0->FLeft->SonLeft->Level >= f0->FLeft->Patch->TileLimitLevel )
01159 {
01160 f0->FLeft->SonLeft->checkFillTileVB(IdUvBase);
01161 f0->FLeft->SonRight->checkFillTileVB(IdUvBase);
01162 }
01163 }
01164 // idem for f1.
01165 if( f1->FLeft!=NULL && !f1->FLeft->isLeaf() && f1->FLeft->Patch!=Patch )
01166 {
01167 // If neighbors sons at tile level, must update their Tile vertices.
01168 if( f1->FLeft->SonLeft->Level >= f1->FLeft->Patch->TileLimitLevel )
01169 {
01170 f1->FLeft->SonLeft->checkFillTileVB(IdUvBase);
01171 f1->FLeft->SonRight->checkFillTileVB(IdUvBase);
01172 }
01173 }
01174 }
01175
01176
01177 // 4. Compute centers.
01178 //--------------------
01179 f0r->computeSplitPoint();
01180 f0l->computeSplitPoint();
01181 f1r->computeSplitPoint();
01182 f1l->computeSplitPoint();
01183
01184
01185 // 5. Propagate, or link sons of base.
01186 //------------------------------------
01187 for(sint i=0;i<2;i++)
01188 {
01189 CTessFace *f, *fl, *fr;
01190 // TOP face.
01191 if(i==0)
01192 {
01193 f= f1;
01194 fl= f1l;
01195 fr= f1r;
01196 }
01197 // then BOT face.
01198 else
01199 {
01200 f= f0;
01201 fl= f0l;
01202 fr= f0r;
01203 }
01204
01205 // If current face and FBase has sons, just links.
01206 if(f->FLeft==NULL)
01207 {
01208 // Just update sons neighbors.
01209 fl->FLeft= NULL;
01210 fr->FLeft= NULL;
01211 }
01212 else if(!f->FLeft->isLeaf())
01213 {
01214 CTessFace *toLeft, *toRight;
01215 toLeft= f->FLeft->SonLeft;
01216 toRight= f->FLeft->SonRight;
01217 // Cross connection of sons.
01218 if( !f->FLeft->isRectangular() )
01219 {
01220 // Case neigbhor is square.
01221 fl->FLeft= toLeft;
01222 fr->FLeft= toRight;
01223 toLeft->FRight= fl;
01224 toRight->FLeft= fr;
01225 }
01226 else
01227 {
01228 // Case neigbhor is rectangle.
01229 fl->FLeft= toRight;
01230 fr->FLeft= toLeft;
01231 toLeft->FLeft= fr;
01232 toRight->FLeft= fl;
01233 }
01234 }
01235 else if (propagateSplit)
01236 {
01237 // Warning: at each iteration, the pointer of FLeft may change (because of split() which can change the neighbor
01238 // and so f).
01239 while(f->FLeft->isLeaf())
01240 f->FLeft->split();
01241
01242 // There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.
01243 // And problems may arise because this face hasn't yet good connectivity (especially for rectangles!! :) ).
01244 nlassert(fl->isLeaf() && fr->isLeaf());
01245 }
01246 }
01247
01248
01249 // 6. Must remove father from rdr list, and insert sons.
01250 //------------------------------------------------------
01251 // UGLY REFCOUNT SIDE EFFECT: do the append first.
01252 Patch->appendFaceToRenderList(f0l);
01253 Patch->appendFaceToRenderList(f0r);
01254 Patch->appendFaceToRenderList(f1l);
01255 Patch->appendFaceToRenderList(f1r);
01256 Patch->removeFaceFromRenderList(f0);
01257 Patch->removeFaceFromRenderList(f1);
01258
01259
01260 // 7. Update priority list.
01261 //------------------------------------------------------
01262 // Since we are freshly splitted, unlink from any list, and link to the MergePriorityList, because must look
01263 // now when should merge.
01264 Patch->getLandscape()->_MergePriorityList.insert(0, 0, f0);
01265 Patch->getLandscape()->_MergePriorityList.insert(0, 0, f1);
01266
01267 // Since we are split, no need to test father for merge, because it cannot!
01268 if(f0->Father)
01269 {
01270 // remove father from any priority list.
01271 f0->Father->unlinkInPList();
01272 }
01273 if(f1->Father)
01274 {
01275 // remove father from any priority list.
01276 f1->Father->unlinkInPList();
01277 }
01278
01279 }
|
|
|
Definition at line 2274 of file tessellation.cpp. References changeNeighbor(), computeNearLimit(), FBase, FLeft, FRight, NL3D::CPatch::getLandscape(), isLeaf(), isRectangular(), NL3D::CTessVertex::MaxFaceSize, NL3D::CTessVertex::MaxNearLimit, NL3D::CLandscape::newTessVertex(), nlassert, Patch, Size, SonLeft, SonRight, updateNearFarVertices(), VBase, VLeft, and VRight. Referenced by NL3D::CPatch::unbind().
02275 {
02276 // NB: since CantMergeFace has a NULL patch ptr, it is unbound too.
02277
02278 // Square case.
02279 //=============
02280 if(!isRectangular())
02281 {
02282 // Change Left/Right neighbors.
02283 if(isLeaf())
02284 {
02285 // FLeft and FRight pointers are only valid in Leaves nodes.
02286 if(FLeft && FLeft->Patch!=Patch)
02287 {
02288 FLeft->changeNeighbor(this, NULL);
02289 FLeft= NULL;
02290 }
02291 if(FRight && FRight->Patch!=Patch)
02292 {
02293 FRight->changeNeighbor(this, NULL);
02294 FRight= NULL;
02295 }
02296 }
02297 // Change Base neighbors.
02298 if(FBase && FBase->Patch!=Patch)
02299 {
02300 CTessFace *oldNeigbhorFace= FBase;
02301
02302 FBase->changeNeighbor(this, NULL);
02303 FBase= NULL;
02304 if(!isLeaf())
02305 {
02306 // Duplicate the VBase of sons, so the unbind is correct and no vertices are shared.
02307 CTessVertex *old= SonLeft->VBase;
02308 SonLeft->VBase= Patch->getLandscape()->newTessVertex();
02309 *(SonLeft->VBase)= *old;
02310 SonRight->VBase= SonLeft->VBase;
02311
02312 // For geomorph (VertexProgram or soft), compute good MaxFaceSize and MaxNearLimit (change since unbinded)
02313 // update us.
02314 SonLeft->VBase->MaxFaceSize= Size;
02315 SonLeft->VBase->MaxNearLimit= computeNearLimit();
02316 // update our neigbhor, only if not a multiple patch face.
02317 if(oldNeigbhorFace->Patch)
02318 {
02319 old->MaxFaceSize= oldNeigbhorFace->Size;
02320 old->MaxNearLimit= oldNeigbhorFace->computeNearLimit();
02321 }
02322 }
02323 }
02324 }
02325 // Rectangular case.
02326 //==================
02327 else
02328 {
02329 // Doens't need to test FBase, since must be same patch.
02330 // In rectangular, FLeft has the behavior of FBase in square case.
02331 if(FLeft && FLeft->Patch!=Patch)
02332 {
02333 CTessFace *oldNeigbhorFace= FLeft;
02334
02335 FLeft->changeNeighbor(this, NULL);
02336 FLeft= NULL;
02337 if(!isLeaf())
02338 {
02339 // Duplicate the VBase of sons, so the unbind is correct and no vertices are shared.
02340 // NB: this code is a bit different from square case.
02341 CTessVertex *old= SonLeft->VBase;
02342 SonLeft->VBase= Patch->getLandscape()->newTessVertex();
02343 *(SonLeft->VBase)= *old;
02344 // This is the difference: (see rectangle tesselation rules).
02345 SonRight->VLeft= SonLeft->VBase;
02346 // Yoyo_patch_himself (12/02/2001): I forgot this one!!
02347 nlassert(FBase && FBase->SonLeft);
02348 FBase->SonLeft->VRight= SonLeft->VBase;
02349
02350
02351 // For geomorph (VertexProgram or soft), compute good MaxFaceSize and MaxNearLimit (change since unbinded)
02352 // update us.
02353 SonLeft->VBase->MaxFaceSize= Size;
02354 SonLeft->VBase->MaxNearLimit= computeNearLimit();
02355 // update our neigbhor, only if not a multiple patch face.
02356 if(oldNeigbhorFace->Patch)
02357 {
02358 old->MaxFaceSize= oldNeigbhorFace->Size;
02359 old->MaxNearLimit= oldNeigbhorFace->computeNearLimit();
02360 }
02361 }
02362 }
02363 // But FRight still valid in leaves nodes only.
02364 if(isLeaf())
02365 {
02366 if(FRight && FRight->Patch!=Patch)
02367 {
02368 FRight->changeNeighbor(this, NULL);
02369 FRight= NULL;
02370 }
02371 }
02372 }
02373
02374 // Propagate unbind.
02375 //==================
02376 if(!isLeaf())
02377 {
02378 // update sons vertex pointers (since they may have been updated by me or my grandfathers).
02379 if(!isRectangular())
02380 {
02381 SonLeft->VLeft= VBase;
02382 SonLeft->VRight= VLeft;
02383 SonRight->VLeft= VRight;
02384 SonRight->VRight= VBase;
02385 }
02386 else
02387 {
02388 // Rectangular case. Update only ptrs which may have changed.
02389 SonLeft->VLeft= VLeft;
02390 SonRight->VBase= VBase;
02391 SonRight->VRight= VRight;
02392 }
02393
02394 // Must re-create good Vertex links for Far and Near Vertices!!!
02395 SonLeft->updateNearFarVertices();
02396 SonRight->updateNearFarVertices();
02397 if(isRectangular())
02398 {
02399 //NB: must do this for Base neighbor (see unbind() rectangular case...).
02400 nlassert(FBase && FBase->SonLeft && FBase->SonRight);
02401 FBase->SonLeft->updateNearFarVertices();
02402 FBase->SonRight->updateNearFarVertices();
02403 }
02404
02405 // unbind the sons.
02406 SonLeft->unbind();
02407 SonRight->unbind();
02408 }
02409
02410 }
|
|
|
if linked, unlink this node from his list.
Definition at line 71 of file tess_face_priority_list.cpp. References NL3D::CTessFacePListNode::_NextTessFaceInPList, and NL3D::CTessFacePListNode::_PrecTessFaceInPList. Referenced by NL3D::CTessFacePriorityList::CRollingTable::clearRollTableEntry(), NL3D::CLandscape::deleteTessFace(), NL3D::CTessFacePriorityList::shift(), NL3D::CTessFacePriorityList::shiftAll(), split(), splitRectangular(), updateRefineSplit(), and NL3D::CTessFacePListNode::~CTessFacePListNode().
00072 {
00073 /*
00074 NB: if this node was empty (this, this), this is a No-Op.
00075 If this node was the last of a list, then the root correctly get (&root, &root) after this.
00076 */
00077 // unlink old list from me.
00078 _PrecTessFaceInPList->_NextTessFaceInPList= _NextTessFaceInPList;
00079 _NextTessFaceInPList->_PrecTessFaceInPList= _PrecTessFaceInPList;
00080
00081 // reset to empty node.
00082 _PrecTessFaceInPList= this;
00083 _NextTessFaceInPList= this;
00084 }
|
|
|
Definition at line 2860 of file tessellation.cpp. References FBase, FLeft, FRight, isLeaf(), SonLeft, SonRight, updateBindAndSplit(), and updateBindEdge(). Referenced by NL3D::CPatch::bind().
02861 {
02862 /*
02863 Remind that updateBind() is called ONLY on the patch which is binded (not the neighbors).
02864 Since updateBind() is called on the bintree, and that precedent propagated split may have occur, we may not
02865 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
02866 sons).
02867 Also, since we are splitted, and correctly linked (this may not be the case in updateBindAndSplit()), FBase IS
02868 correct. His FBase neighbor and him form a diamond. So we don't need to update him.
02869
02870 Same remarks for rectangular patchs.
02871 */
02872 if(isLeaf())
02873 {
02874 bool splitWanted= false;
02875 while(!updateBindEdge(FBase, splitWanted));
02876 // FLeft and FRight pointers are only valid in Leaves nodes.
02877 while(!updateBindEdge(FLeft, splitWanted));
02878 while(!updateBindEdge(FRight, splitWanted));
02879 if(splitWanted)
02880 updateBindAndSplit();
02881 }
02882
02883
02884 // Recurse to sons.
02885 if(!isLeaf())
02886 {
02887 // Update bind of sons.
02888 SonLeft->updateBind();
02889 SonRight->updateBind();
02890 }
02891 }
|
|
|
Definition at line 2643 of file tessellation.cpp. References CantMergeFace, changeNeighbor(), computeSplitPoint(), NL3D::CLandscape::deleteTessVertex(), NL3D::CTessVertex::EndPos, FBase, FLeft, FRight, NL3D::CPatch::getLandscape(), isLeaf(), isRectangular(), nlassert, Patch, NL3D::CTessVertex::Pos, sint, SonLeft, SonRight, split(), NL3D::CTessVertex::StartPos, updateBindEdge(), updateNearFarVertices(), VBase, and VRight. Referenced by updateBind().
02644 {
02645 bool splitWanted= false;
02646 CTessFace *f0= NULL;
02647 CTessFace *f1= NULL;
02648 /*
02649 Look at the callers, and you'll see that "this" is always a leaf.
02650 Therefore, FBase, FLeft and FRight are good pointers, and *FLeft and *FRight should be Ok too.
02651 */
02652 nlassert(isLeaf());
02653 while(!updateBindEdge(FBase, splitWanted));
02654 // FLeft and FRight pointers are only valid in Leaves nodes.
02655 while(!updateBindEdge(FLeft, splitWanted));
02656 while(!updateBindEdge(FRight, splitWanted));
02657 // In rectangular case, we MUST also update edges of FBase.
02658 // Because splitRectangular() split those two faces at the same time.
02659 if(isRectangular())
02660 {
02661 f0= this;
02662 f1= FBase;
02663 nlassert(FBase);
02664 nlassert(FBase->isLeaf());
02665 // Doesn't need to update FBase->FBase, since it's me!
02666 // FLeft and FRight pointers are only valid in Leaves nodes.
02667 while(!FBase->updateBindEdge(FBase->FLeft, splitWanted));
02668 while(!FBase->updateBindEdge(FBase->FRight, splitWanted));
02669 }
02670
02671
02672
02673 CTessFace *fmult= NULL;
02674 CTessFace *fmult0= NULL;
02675 CTessFace *fmult1= NULL;
02676 // If multipatch face case.
02677 //=========================
02678 if(!isRectangular())
02679 {
02680 // multipatch face case are detected when face->Patch==NULL !!!
02681 if(FBase && FBase->Patch==NULL)
02682 {
02683 fmult= FBase;
02684 // First, trick: FBase is NULL, so during the split. => no ptr problem.
02685 FBase= NULL;
02686 }
02687 }
02688 else
02689 {
02690 // multipatch face case are detected when face->Patch==NULL !!!
02691 if(f0->FLeft && f0->FLeft->Patch==NULL)
02692 {
02693 fmult0= f0->FLeft;
02694 // First, trick: neighbor is NULL, so during the split. => no ptr problem.
02695 f0->FLeft= NULL;
02696 }
02697 // multipatch face case are detected when face->Patch==NULL !!!
02698 if(f1->FLeft && f1->FLeft->Patch==NULL)
02699 {
02700 fmult1= f1->FLeft;
02701 // First, trick: neighbor is NULL, so during the split. => no ptr problem.
02702 f1->FLeft= NULL;
02703 }
02704 }
02705
02706 // Then split, and propagate.
02707 //===========================
02708 split(false);
02709 if(!isRectangular())
02710 {
02711 if(FBase)
02712 {
02713 while(FBase->isLeaf())
02714 FBase->updateBindAndSplit();
02715 }
02716 // There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.
02717 // And problems may arise because this face hasn't yet good connectivity.
02718 nlassert(SonLeft->isLeaf() && SonRight->isLeaf());
02719 }
02720 else
02721 {
02722 if(f0->FLeft)
02723 {
02724 while(f0->FLeft->isLeaf())
02725 f0->FLeft->updateBindAndSplit();
02726 }
02727 if(f1->FLeft)
02728 {
02729 while(f1->FLeft->isLeaf())
02730 f1->FLeft->updateBindAndSplit();
02731 }
02732 // There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.
02733 // And problems may arise because this face hasn't yet good connectivity.
02734 nlassert(f0->SonLeft->isLeaf() && f0->SonRight->isLeaf());
02735 nlassert(f1->SonLeft->isLeaf() && f1->SonRight->isLeaf());
02736 }
02737
02738
02739 // If multipatch face case, update neighbors.
02740 //===========================================
02741 if(!isRectangular() && fmult)
02742 {
02743 // Update good Face neighbors.
02744 //============================
02745 SonLeft->FRight= fmult->SonRight;
02746 fmult->SonRight->changeNeighbor(&CTessFace::MultipleBindFace, SonLeft);
02747
02748 SonRight->FLeft= fmult->SonLeft;
02749 fmult->SonLeft->changeNeighbor(&CTessFace::MultipleBindFace, SonRight);
02750
02751 // NB: this work auto with 1/2 or 1/4. See CPatch::bind(), to understand.
02752 // In 1/4 case, fmult->SonLeft and fmult->SonRight are themselves MultiPatch face. So it will recurse.
02753
02754 // Update good vertex pointer.
02755 //============================
02756 CTessVertex *vert= fmult->VBase;
02757
02758 // Copy the good coordinate: those splitted (because of noise).
02759 vert->Pos= vert->StartPos= vert->EndPos= SonLeft->VBase->EndPos;
02760 // But delete the pointer.
02761 Patch->getLandscape()->deleteTessVertex(SonLeft->VBase);
02762 // And update sons pointers, to good vertex.
02763 SonLeft->VBase= vert;
02764 SonRight->VBase= vert;
02765 // Compute correct centers.
02766 SonRight->computeSplitPoint();
02767 SonLeft->computeSplitPoint();
02768
02769
02770 // Update good Far vertex pointer.
02771 //================================
02772 // Because *->VBase may have been merged to the multiple bind face, Near/FarVertices which pointed on it must
02773 // be setup.
02774 // We do not have to propagate this vertex ptr change since sons are leaves!!
02775 nlassert(SonLeft->isLeaf() && SonRight->isLeaf());
02776 // update pointers on vertex.
02777 SonLeft->updateNearFarVertices();
02778 SonRight->updateNearFarVertices();
02779
02780
02781 // Bind FBase to a false face which indicate a bind 1/N.
02782 // This face prevent for "this" face to be merged...
02783 FBase= &CantMergeFace;
02784
02785 // Therefore, the vertex will be never deleted (since face not merged).
02786 // The only way to do this, is to unbind the patch from all (then the vertex is cloned), then the merge will be Ok.
02787 }
02788 // Else if rectangular.
02789 else if(fmult0 || fmult1)
02790 {
02791 CTessFace *f;
02792 sint i;
02793
02794 // Same reasoning for rectangular patchs, as above.
02795 for(i=0;i<2;i++)
02796 {
02797 if(i==0)
02798 f= f0, fmult= fmult0;
02799 else
02800 f= f1, fmult= fmult1;
02801 if(fmult)
02802 {
02803 // Update good Face neighbors (when I am a rectangle).
02804 //============================
02805 // Consider the fmult face as a square face.
02806 CTessFace *toLeft, *toRight;
02807 CTessFace *fl=f->SonLeft, *fr=f->SonRight;
02808 toLeft= fmult->SonLeft;
02809 toRight= fmult->SonRight;
02810 // Cross connection of sons.
02811 fl->FLeft= toLeft;
02812 fr->FLeft= toRight;
02813 toLeft->changeNeighbor(&CTessFace::MultipleBindFace, fl);
02814 toRight->changeNeighbor(&CTessFace::MultipleBindFace, fr);
02815
02816 // Update good vertex pointer.
02817 //============================
02818 CTessVertex *vert= fmult->VBase;
02819
02820 // Copy the good coordinate: those splitted (because of noise).
02821 // NB: this work too with rectangular patch (see tesselation rules).
02822 vert->Pos= vert->StartPos= vert->EndPos= fl->VBase->EndPos;
02823 // But delete the pointer.
02824 Patch->getLandscape()->deleteTessVertex(fl->VBase);
02825 // And update sons pointers, to good vertex (rectangular case, see tesselation rules).
02826 fl->VBase= vert;
02827 fr->VLeft= vert;
02828 f->FBase->SonLeft->VRight= vert;
02829
02830 // Point to a bind 1/N indicator.
02831 f->FLeft= &CantMergeFace;
02832 }
02833 }
02834 // After all updates done. recompute centers of both sons 's faces, and update far vertices pointers.
02835 for(i=0;i<2;i++)
02836 {
02837 if(i==0)
02838 f= f0;
02839 else
02840 f= f1;
02841 // Compute correct centers.
02842 f->SonRight->computeSplitPoint();
02843 f->SonLeft->computeSplitPoint();
02844
02845 // Update good Far vertex pointer.
02846 //================================
02847 // Because *->VBase may have been merged to the multiple bind face, Near/FarVertices which pointed on it must
02848 // be setup.
02849 // We do not have to propagate this vertex ptr change, since sons are leaves!!
02850 nlassert(f->SonLeft->isLeaf() && f->SonRight->isLeaf());
02851 // update pointers on vertex.
02852 f->SonLeft->updateNearFarVertices();
02853 f->SonRight->updateNearFarVertices();
02854 }
02855 }
02856 }
|
|
||||||||||||
|
Definition at line 2544 of file tessellation.cpp. References FBase, FLeft, FRight, isLeaf(), isRectangular(), nlstop, Patch, SonLeft, and SonRight. Referenced by updateBind(), and updateBindAndSplit().
02545 {
02546 // Return true, when the bind should be Ok, or if a split has occured.
02547 // Return false only if pointers are updated, without splits.
02548
02549 if(edgeFace==NULL)
02550 return true;
02551
02552 if(edgeFace->isLeaf())
02553 return true;
02554
02555 /*
02556 Look at the callers, and you'll see that "this" is always a leaf.
02557 Therefore, edgeFace is a valid pointer (either if it is FLeft, FRight or FBase).
02558 */
02559
02560 // MultiPatch face case.
02561 //======================
02562 // If neighbor is a multiple face.
02563 if(edgeFace->Patch==NULL && edgeFace->FBase==this)
02564 {
02565 splitWanted= true;
02566 return true;
02567 }
02568
02569
02570 // neighbor is a "Square face" case.
02571 //==================================
02572 if(!edgeFace->isRectangular())
02573 {
02574 // NB: this code works either if I AM a rectangular face or a square face.
02575
02576 // If the neighbor is splitted on ourself, split...
02577 if(edgeFace->FBase==this)
02578 {
02579 splitWanted= true;
02580 return true;
02581 }
02582 else
02583 {
02584 // Just update pointers...
02585 if(edgeFace->FLeft==this)
02586 {
02587 CTessFace *sonLeft= edgeFace->SonLeft;
02588 sonLeft->FBase= this;
02589 edgeFace= sonLeft;
02590 }
02591 else if(edgeFace->FRight==this)
02592 {
02593 CTessFace *sonRight= edgeFace->SonRight;
02594 sonRight->FBase= this;
02595 edgeFace= sonRight;
02596 }
02597 else
02598 {
02599 // Look at the callers, and you'll see that "this" is always a leaf.
02600 // Therefore, we should never be here.
02601 nlstop;
02602 }
02603 }
02604 }
02605 // neighbor is a "Rectangle face" case.
02606 //=====================================
02607 else
02608 {
02609 // NB: this code works either if I AM a rectangular face or a square face.
02610
02611 // If the neighbor is splitted on ourself, split...
02612 // Test FLeft because of rectangular case... :)
02613 // FBase should be tested too. If edgeFace->FBase==this, I should be myself a rectangular face.
02614 if(edgeFace->FLeft==this || edgeFace->FBase==this)
02615 {
02616 splitWanted= true;
02617 return true;
02618 }
02619 else
02620 {
02621 if(edgeFace->FRight==this)
02622 {
02623 // See rectangular tesselation rules, too know why we do this.
02624 CTessFace *sonRight= edgeFace->SonRight;
02625 sonRight->FRight= this;
02626 edgeFace= sonRight;
02627 }
02628 else
02629 {
02630 // Look at the callers, and you'll see that "this" is always a leaf.
02631 // Therefore, we should never be here.
02632 nlstop;
02633 }
02634 }
02635 }
02636
02637 return false;
02638 }
|
|
|
Definition at line 278 of file tessellation.cpp. References computeTileErrorMetric(), ErrorMetric, ErrorMetricDate, MaxDistToSplitPoint, SplitPoint, NLMISC::sqr(), NLMISC::CVector::sqrnorm(), and NL3D::CPatch::TileLimitLevel. Referenced by canMerge(), refineAll(), updateRefineMerge(), and updateRefineSplit().
00279 {
00280 // If already updated for this pass...
00281 if(ErrorMetricDate>= CLandscapeGlobals::CurrentDate)
00282 return;
00283
00284 CVector viewdir= SplitPoint - CLandscapeGlobals::RefineCenter;
00285 float sqrdist= viewdir.sqrnorm();
00286
00287 // trivial formula.
00288 //-----------------
00289 ErrorMetric= Size/ sqrdist;
00290
00291
00292 // Hoppe97 formula: k²= a² * ("v-e"² - ((v-e).n)²) / "v-e"^4.
00293 //-----------------
00294 // Can't do it because geomorph is made on Graphic card, so the simplier is the better.
00295
00296
00297 // TileMode Impact.
00298 //-----------------
00299 /* TileMode Impact. We must split at least at TileLimitLevel, but only if the triangle
00300 has a chance to enter in the TileDistFar sphere.
00301 */
00302 if( Level<Patch->TileLimitLevel && sqrdist < sqr(CLandscapeGlobals::TileDistFar+MaxDistToSplitPoint) )
00303 {
00304 computeTileErrorMetric();
00305 }
00306
00307 ErrorMetricDate= CLandscapeGlobals::CurrentDate;
00308 }
|
|
|
Definition at line 873 of file tessellation.cpp. References NL3D::CPatch::checkFillVertexVBFar(), NL3D::CPatch::checkFillVertexVBNear(), FVBase, FVLeft, FVRight, IdUvBase, IdUvLeft, IdUvRight, NL3D_MAX_TILE_FACE, nlassert, PVBase, PVLeft, PVRight, sint, NL3D::CTessNearVertex::Src, TileFaces, NL3D::CTileFace::V, VBase, VLeft, and VRight. Referenced by unbind(), and updateBindAndSplit().
00874 {
00875 nlassert(VBase && FVBase);
00876 nlassert(VLeft && FVLeft);
00877 nlassert(VRight && FVRight);
00878
00879 FVBase->Src= VBase;
00880 FVLeft->Src= VLeft;
00881 FVRight->Src= VRight;
00882 FVBase->PCoord= PVBase;
00883 FVLeft->PCoord= PVLeft;
00884 FVRight->PCoord= PVRight;
00885
00886 // Update VB for far vertices (if needed)
00887 Patch->checkFillVertexVBFar(FVBase);
00888 Patch->checkFillVertexVBFar(FVLeft);
00889 Patch->checkFillVertexVBFar(FVRight);
00890
00891 // Near Vertices update (Src only).
00892 for(sint i=0; i<NL3D_MAX_TILE_FACE; i++)
00893 {
00894 if(TileFaces[i])
00895 {
00896 TileFaces[i]->V[IdUvBase]->Src= VBase;
00897 TileFaces[i]->V[IdUvLeft]->Src= VLeft;
00898 TileFaces[i]->V[IdUvRight]->Src= VRight;
00899
00900 // Update VB for near vertices (if needed)
00901 Patch->checkFillVertexVBNear(TileFaces[i]->V[IdUvBase]);
00902 Patch->checkFillVertexVBNear(TileFaces[i]->V[IdUvLeft]);
00903 Patch->checkFillVertexVBNear(TileFaces[i]->V[IdUvRight]);
00904 }
00905 }
00906
00907 }
|
|
|
TileDistFar to +oo. TileDistNear to TileDistFar. 0 to TileDistNear. Definition at line 2108 of file tessellation.cpp. References NL3D::CLandscape::_MergePriorityList, canMerge(), computeNearLimit(), computeTileEMForUpdateRefine(), NL3D::CTessVertex::EndPos, ErrorMetric, NL3D::CPatch::getLandscape(), NL3D::CTessFacePriorityList::insert(), isLeaf(), merge(), min, NL3D_PROFILE_LAND_ADD, NL3D_REFINE_MERGE_THRESHOLD, nlassert, NL3D::ProfNRefineFaces, NL3D::ProfNRefineInTileTransition, SplitPoint, NL3D::CPatch::TileLimitLevel, uint, updateErrorMetric(), VBase, VLeft, and VRight. Referenced by NL3D::CLandscape::refine().
02109 {
02110 NL3D_PROFILE_LAND_ADD(ProfNRefineFaces, 1);
02111
02112 nlassert(Patch);
02113 // The face must be splitted, because tested for merge.
02114 nlassert(!isLeaf());
02115
02116 /*
02117 NB: see above for some updateRefine*** doc.
02118 */
02119
02120 // Test for merge.
02121 //-----------------------
02122 bool merged= false;
02123 {
02124 updateErrorMetric();
02125 float ps=ErrorMetric;
02126 ps*= CLandscapeGlobals::OORefineThreshold;
02127 // 1.0f is the point of split().
02128 // 2.0f is the end of geomorph.
02129
02130
02131 // Test merge.
02132 //---------------------
02133 // Else, must merge ??
02134 if(ps<1.0f)
02135 {
02136 // Merge only if agree, and neighbors agree.
02137 // canMerge() test all the good thing: FBase==CantMergeFace, or this is rectangular etc...
02138 // The test is propagated to neighbors.
02139 if(canMerge(true))
02140 {
02141 merge();
02142
02143 // NB: here, merge() is not propagated to fathers (supposed to be not very usefull).
02144
02145 if(isLeaf())
02146 {
02147 merged= true;
02148 }
02149 }
02150 }
02151 }
02152
02153
02154 // Insert the face in the priority list.
02155 //-----------------------
02156 // If merged, then insertion in Landscape->SplitPriorityList at 0 has been done. so nothing to update.
02157 // Else, must compute when whe should re-test.
02158 if(!merged)
02159 {
02160 // the face is splitted here.
02161 nlassert(!isLeaf());
02162
02163 float minDeltaDistToUpdate;
02164
02165
02166 // The distance of SplitPoint to center.
02167 float distSplitPoint= (SplitPoint - CLandscapeGlobals::RefineCenter).norm();
02168 // Compute distance from refineCenter to normal split/merge (ie without tile transition).
02169 float distNormalSplitMerge= (float)sqrt(Size*CLandscapeGlobals::OORefineThreshold);
02170
02171
02172 // If the face is at its max subdivision
02173 if(Level>=Patch->TileLimitLevel+CLandscapeGlobals::TileMaxSubdivision)
02174 {
02175 // since the face is splitted, then must test always this face, because we must merge it (as soon as it is possible).
02176 minDeltaDistToUpdate= 0;
02177 }
02178 else if(Level>=Patch->TileLimitLevel)
02179 {
02180 // Always normal ErrorMetric. Because Faces at Tile level decide to split or merge their sons independently
02181 // of "Tile ErrorMetric".
02182 // since splitted, compute distance to merge.
02183 minDeltaDistToUpdate= distNormalSplitMerge - distSplitPoint;
02184 // NB: it is possible that minDeltaDistToUpdate<0. A good example is when we are enforced split.
02185 // Then, distSplitMerge may be < distSplitPoint, meaning we should have not split, but a neigbhor has enforced us.
02186 // So now, must test every frame if we can merge....
02187 minDeltaDistToUpdate= max( 0.f, minDeltaDistToUpdate );
02188 }
02189 else
02190 {
02191 // Compute Distance of the face from RefineCenter. It is the min of the 3 points, as in computeTileErrorMetric().
02192 float s0= (VBase->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
02193 float s1= (VLeft->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
02194 float s2= (VRight->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm();
02195 float distMinFace= (float)sqrt( minof(s0, s1, s2) );
02196
02197 // compute the delta distance to the normal split point. See above for doc.
02198 float normalEMDeltaDist;
02199 normalEMDeltaDist= distNormalSplitMerge - distSplitPoint;
02200 normalEMDeltaDist= max( 0.f, normalEMDeltaDist );
02201
02202
02203 /*
02204 There is 3 possibles cases, according to level, and the distances minFaceDist:
02205 */
02207 if( distMinFace > CLandscapeGlobals::TileDistFar )
02208 {
02209 // normal geomorph. Any face compute the distance to the SplitPoint, and take min with distance to
02210 // the TileDistFar sphere.
02211 minDeltaDistToUpdate= normalEMDeltaDist;
02212
02213 // We must know when we enter in TileErrorMetric zone, because the computing is different.
02214 minDeltaDistToUpdate= min(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistFar);
02215 }
02217 else if( distMinFace > CLandscapeGlobals::TileDistNear )
02218 {
02219 // Profile
02220 NL3D_PROFILE_LAND_ADD(ProfNRefineInTileTransition, 1);
02221
02222
02223 // Compute distance to split/Merge in TileTransition
02224 float distTileTransSplitMerge;
02225 float maxDeltaDist= 8;
02226 float minDeltaDist= 0;
02227 uint nbRecurs= 6;
02228 float nearLimit;
02229 nearLimit= CLandscapeGlobals::RefineThreshold * computeNearLimit();
02230 // Since splitted, compute distance to merge.
02231 // search the distance recursively.
02232 for(uint i=0; i< nbRecurs; i++)
02233 {
02234 float pivotDeltaDist= (maxDeltaDist-minDeltaDist)/2;
02235 // If the em computed with this distance is still >1 (ie splitted), then we can move further.
02236 if ( computeTileEMForUpdateRefine(distSplitPoint+pivotDeltaDist, distMinFace+pivotDeltaDist, nearLimit ) > 1)
02237 minDeltaDist= pivotDeltaDist;
02238 // else we must move not as far
02239 else
02240 maxDeltaDist= pivotDeltaDist;
02241 }
02242 // And so take the minimum resulting delta distance
02243 distTileTransSplitMerge= minDeltaDist;
02244
02245 // take the min with distance of distMinFace to the TileDistNear and TileDistFar sphere, because formula change at
02246 // those limits.
02247 minDeltaDistToUpdate= min(distTileTransSplitMerge, CLandscapeGlobals::TileDistFar - distMinFace );
02248 minDeltaDistToUpdate= min(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistNear);
02249 }
02251 else
02252 {
02253 // because the face is not a Tile Level (ie Level<Patch->TileLimitLevel), it should be splitted,
02254 // and won't merge until reaching at least the TileDistNear sphere.
02255 // Since splitted, Must enter in TileErrorMetric area to know when to merge.
02256 minDeltaDistToUpdate= CLandscapeGlobals::TileDistNear - distMinFace;
02257 }
02258
02259 }
02260
02261 // Merge Refine Threshold: because of enforced splits, we have lot of faces whit minDeltaDistToUpdate<0, because
02262 // they alwayas want to merge. To avoid this, add a delta, which delay the test for merge.
02263 // The caveat is that faces which do not need this may merge later. But 2 meters won't add too many faces.
02264 minDeltaDistToUpdate+= NL3D_REFINE_MERGE_THRESHOLD;
02265
02266 // insert in the Merge priority list.
02267 // Until the RefineCenter move under minDeltaDistToUpdate, we don't need to test face.
02268 Patch->getLandscape()->_MergePriorityList.insert(0, minDeltaDistToUpdate, this);
02269 }
02270 }
|
|
|
TileDistFar to +oo. TileDistNear to TileDistFar. 0 to TileDistNear. Definition at line 1900 of file tessellation.cpp. References NL3D::CLandscape::_SplitPriorityList, computeNearLimit(), computeTileEMForUpdateRefine(), NL3D::CTessVertex::EndPos, ErrorMetric, NL3D::CPatch::getLandscape(), NL3D::CTessFacePriorityList::getQuadrantDirection(), NL3D::CTessFacePriorityList::insert(), isLeaf(), min, NL3D_PROFILE_LAND_ADD, NL3D_TESS_USE_QUADRANT_THRESHOLD, nlassert, NLMISC::CVector::norm(), NL3D::ProfNRefineFaces, NL3D::ProfNRefineInTileTransition, NL3D::ProfNRefineWithLowDistance, NL3D::CTessFacePriorityList::selectQuadrant(), split(), SplitPoint, NLMISC::CVector::sqrnorm(), NL3D::CPatch::TileLimitLevel, uint, NL3D::CTessFacePListNode::unlinkInPList(), updateErrorMetric(), VBase, VLeft, and VRight. Referenced by NL3D::CLandscape::refine().
01901 {
01902 NL3D_PROFILE_LAND_ADD(ProfNRefineFaces, 1);
01903
01904 nlassert(Patch);
01905 // The face must be not splitted, because tested for split.
01906 nlassert(isLeaf());
01907
01908 /*
01909 NB: see above for some updateRefine*** doc.
01910 */
01911
01912 // Test for Split.
01913 //-----------------------
01914 bool splitted= false;
01915 {
01916 updateErrorMetric();
01917 float ps=ErrorMetric;
01918 ps*= CLandscapeGlobals::OORefineThreshold;
01919 // 1.0f is the point of split().
01920 // 2.0f is the end of geomorph.
01921
01922
01923 // Test split.
01924 //---------------------
01925 // If wanted and limit not reached, split().
01926 if(ps>1.0f && Level< (Patch->TileLimitLevel + CLandscapeGlobals::TileMaxSubdivision) )
01927 {
01928 split();
01929
01930 // if split ok
01931 if(!isLeaf())
01932 {
01933 splitted= true;
01934 }
01935 }
01936 }
01937
01938
01939 // Insert the face in the priority list.
01940 //-----------------------
01941 // If splitted, then insertion in Landscape->MergePriorityList at 0 has been done. so nothing to update.
01942 // Else, must compute when whe should re-test.
01943 if(!splitted)
01944 {
01945 // the face is not splitted here.
01946 nlassert(isLeaf());
01947
01948 float minDeltaDistToUpdate;
01949
01950 // by default insert in the quadrant-less rolling table.
01951 uint quadrantId= 0;
01952
01953
01954 CVector dirToSplitPoint= SplitPoint - CLandscapeGlobals::RefineCenter;
01955 // The distance of SplitPoint to center.
01956 float distSplitPoint= dirToSplitPoint.norm();
01957 // The distance where we should split/merge. see updateRefin() doc.
01958 float distNormalSplitMerge= (float)sqrt(Size*CLandscapeGlobals::OORefineThreshold);
01959
01960
01961 // If the face is at its max subdivision
01962 if(Level>=Patch->TileLimitLevel+CLandscapeGlobals::TileMaxSubdivision)
01963 {
01964 // special case: the face do not need to be tested for splitting, because Max subdivision reached.
01965 // Hence just unlink from any list, and return.
01966 unlinkInPList();
01967 return;
01968 }
01969 else if(Level>=Patch->TileLimitLevel)
01970 {
01971 // Always normal ErrorMetric. Because Faces at Tile level decide to split or merge their sons independently
01972 // of "Tile ErrorMetric".
01973
01974 // The test is "when do we enter in the Split area?", so we can use Quadrant PriorityList
01975 quadrantId= Patch->getLandscape()->_SplitPriorityList.selectQuadrant(dirToSplitPoint);
01976
01977 // compute distance to split as default "No Quadrant"
01978 minDeltaDistToUpdate= distSplitPoint - distNormalSplitMerge;
01979
01980 // If a quadrant is selected, try to use it
01981 if(quadrantId>0)
01982 {
01983 const CVector &quadrantDir= Patch->getLandscape()->_SplitPriorityList.getQuadrantDirection(quadrantId);
01984
01985 // We must not approach the SplitPoint at distNormalSplitMerge
01986 float dMin= quadrantDir*dirToSplitPoint - distNormalSplitMerge;
01987
01988 // If the dist with quadrant is too small then use the std way (without quadrant).
01989 if( dMin<NL3D_TESS_USE_QUADRANT_THRESHOLD )
01990 quadrantId= 0;
01991 // else ok, use quadrant behavior
01992 else
01993 minDeltaDistToUpdate= dMin;
01994 }
01995 }
01996 else
01997 {
01998 // Compute Distance of the face from RefineCenter. It is the min of the 3 points, as in computeTileErrorMetric().
01999 CVector dirToV0= VBase->EndPos - CLandscapeGlobals::RefineCenter;
02000 CVector dirToV1= VLeft->EndPos - CLandscapeGlobals::RefineCenter;
02001 CVector dirToV2= VRight->EndPos - CLandscapeGlobals::RefineCenter;
02002 float s0= dirToV0.sqrnorm();
02003 float s1= dirToV1.sqrnorm();
02004 float s2= dirToV2.sqrnorm();
02005 float distMinFace= (float)sqrt( minof(s0, s1, s2) );
02006
02007 // compute the delta distance to the normal split point. See above for doc.
02008 float normalEMDeltaDist;
02009 normalEMDeltaDist= distSplitPoint - distNormalSplitMerge;
02010
02011
02012 /*
02013 There is 3 possibles cases, according to level, and the distances minFaceDist:
02014 */
02016 if( distMinFace > CLandscapeGlobals::TileDistFar )
02017 {
02018 // The test is "when do we enter in the Split area OR in TileDistFar area?", so we can use Quadrant PriorityList
02019 quadrantId= Patch->getLandscape()->_SplitPriorityList.selectQuadrant(dirToSplitPoint);
02020
02021 // compute deltaDist as default "Direction less quadrant"
02022 minDeltaDistToUpdate= normalEMDeltaDist;
02023 // We must know when we enter in TileErrorMetric zone, because the computing is different.
02024 minDeltaDistToUpdate= min(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistFar);
02025
02026 // try with quadrant if > 0.
02027 if(quadrantId>0)
02028 {
02029 const CVector &quadrantDir= Patch->getLandscape()->_SplitPriorityList.getQuadrantDirection(quadrantId);
02030
02031 // We must not approach the SplitPoint at distNormalSplitMerge
02032 float dMin= quadrantDir*dirToSplitPoint - distNormalSplitMerge;
02033 // and we must not reach one of the 3 sphere (Vi, TileDistFar).
02034 float d0 = quadrantDir*dirToV0 - CLandscapeGlobals::TileDistFar;
02035 float d1 = quadrantDir*dirToV1 - CLandscapeGlobals::TileDistFar;
02036 float d2 = quadrantDir*dirToV2 - CLandscapeGlobals::TileDistFar;
02037 // take min dist
02038 dMin= minof(dMin, d0, d1, d2);
02039
02040 // If the dist with quadrant is too small then use the std way (without quadrant).
02041 if( dMin<NL3D_TESS_USE_QUADRANT_THRESHOLD )
02042 quadrantId= 0;
02043 // else ok, use quadrant behavior
02044 else
02045 minDeltaDistToUpdate= dMin;
02046 }
02047 }
02049 else if( distMinFace > CLandscapeGlobals::TileDistNear )
02050 {
02051 // NB: can't use quadrant behavior here. Leave quadrantId at 0.
02052
02053 // Profile
02054 NL3D_PROFILE_LAND_ADD(ProfNRefineInTileTransition, 1);
02055
02056 // Compute distance to split/Merge in TileTransition
02057 float distTileTransSplitMerge;
02058 float maxDeltaDist= 8;
02059 float minDeltaDist= 0;
02060 uint nbRecurs= 6;
02061 float nearLimit;
02062 nearLimit= CLandscapeGlobals::RefineThreshold * computeNearLimit();
02063 // search the distance to split recursively.
02064 for(uint i=0; i< nbRecurs; i++)
02065 {
02066 float pivotDeltaDist= (maxDeltaDist-minDeltaDist)/2;
02067 // If the em computed with this distance is still <1 (ie merged), then we can move further.
02068 if ( computeTileEMForUpdateRefine(distSplitPoint-pivotDeltaDist, distMinFace-pivotDeltaDist, nearLimit ) < 1)
02069 minDeltaDist= pivotDeltaDist;
02070 // else we must move not as far
02071 else
02072 maxDeltaDist= pivotDeltaDist;
02073 }
02074 // And so take the minimum resulting delta distance
02075 distTileTransSplitMerge= minDeltaDist;
02076
02077 // take the min with distance of distMinFace to the TileDistNear and TileDistFar sphere, because formula change at
02078 // those limits.
02079 minDeltaDistToUpdate= min(distTileTransSplitMerge, CLandscapeGlobals::TileDistFar - distMinFace );
02080 minDeltaDistToUpdate= min(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistNear);
02081 }
02083 else
02084 {
02085 // because the face is not a Tile Level (ie Level<Patch->TileLimitLevel), it should be splitted,
02086 // and won't merge until reaching at least the TileDistNear sphere.
02087 // if not splited (should not arise), force the split next time.
02088 minDeltaDistToUpdate= 0;
02089 }
02090
02091 }
02092
02093 // Profile.
02094 if(minDeltaDistToUpdate<0.0625)
02095 {
02096 NL3D_PROFILE_LAND_ADD(ProfNRefineWithLowDistance, 1);
02097 }
02098
02099
02100 // insert in the Split priority list.
02101 // Until the RefineCenter move under minDeltaDistToUpdate, we don't need to test face.
02102 Patch->getLandscape()->_SplitPriorityList.insert(quadrantId, minDeltaDistToUpdate, this);
02103 }
02104 }
|
|
|
Definition at line 156 of file tessellation.cpp. Referenced by averageTesselationVertices(), canMerge(), forceMerge(), forceMergeAtTileLevel(), and updateBindAndSplit(). |
|
|
Definition at line 276 of file tessellation.h. Referenced by canMerge(), computeTileErrorMetric(), refineAll(), updateErrorMetric(), updateRefineMerge(), and updateRefineSplit(). |
|
|
Definition at line 273 of file tessellation.h. Referenced by CTessFace(), and updateErrorMetric(). |
|
|
Definition at line 243 of file tessellation.h. Referenced by split(), and splitRectangular(). |
|
|
Definition at line 242 of file tessellation.h. Referenced by averageTesselationVertices(), NL3D::CPatch::bind(), canMerge(), changeNeighbor(), computeTileMaterial(), CTessFace(), deleteTileUvs(), doMerge(), forceMerge(), heritTileMaterial(), linkTessFaceWithEdge(), NL3D::CPatch::makeRoots(), releaseTileMaterial(), split(), splitRectangular(), unbind(), updateBind(), updateBindAndSplit(), and updateBindEdge(). |
|
|
Definition at line 242 of file tessellation.h. Referenced by averageTesselationVertices(), NL3D::CPatch::bind(), canMerge(), NL3D::CPatch::changeEdgeNeighbor(), changeNeighbor(), CTessFace(), doMerge(), forceMerge(), linkTessFaceWithEdge(), NL3D::CPatch::makeRoots(), NL3D::CPatch::release(), split(), splitRectangular(), unbind(), NL3D::CPatch::unbind(), updateBind(), updateBindAndSplit(), and updateBindEdge(). |
|
|
Definition at line 242 of file tessellation.h. Referenced by NL3D::CPatch::bind(), NL3D::CPatch::changeEdgeNeighbor(), changeNeighbor(), CTessFace(), doMerge(), linkTessFaceWithEdge(), NL3D::CPatch::makeRoots(), NL3D::CPatch::release(), split(), splitRectangular(), unbind(), NL3D::CPatch::unbind(), updateBind(), updateBindAndSplit(), and updateBindEdge(). |
|
|
Definition at line 282 of file tessellation.h. Referenced by NL3D::CPatch::bind(), doMerge(), NL3D::CPatch::makeRoots(), NL3D::CTessBlock::refillFaceVectorFar0(), NL3D::CTessBlock::refillFaceVectorFar1(), split(), splitRectangular(), and updateNearFarVertices(). |
|
|
Definition at line 282 of file tessellation.h. Referenced by NL3D::CPatch::bind(), NL3D::CPatch::makeRoots(), NL3D::CTessBlock::refillFaceVectorFar0(), NL3D::CTessBlock::refillFaceVectorFar1(), split(), splitRectangular(), and updateNearFarVertices(). |
|
|
Definition at line 282 of file tessellation.h. Referenced by NL3D::CPatch::bind(), NL3D::CPatch::makeRoots(), NL3D::CTessBlock::refillFaceVectorFar0(), NL3D::CTessBlock::refillFaceVectorFar1(), split(), splitRectangular(), and updateNearFarVertices(). |
|
|
Definition at line 247 of file tessellation.h. Referenced by NL3D::CPatch::appendFaceToRenderList(), computeTileMaterial(), deleteTileUvs(), doMerge(), NL3D::CPatch::extendTessBlockWithEndPos(), NL3D::CPatch::makeRoots(), recreateTileUvs(), releaseTileMaterial(), NL3D::CPatch::removeFaceFromRenderList(), split(), and splitRectangular(). |
|
|
Definition at line 277 of file tessellation.h. Referenced by computeSplitPoint(), and updateErrorMetric(). |
|
|
Definition at line 157 of file tessellation.cpp. |
|
|
|
Definition at line 240 of file tessellation.h. Referenced by averageTesselationVertices(), NL3D::CZoneLighter::buildZoneInformation(), computeTileMaterial(), doMerge(), NL3D::CPatch::makeRoots(), sameTile(), split(), splitRectangular(), unbind(), updateBindAndSplit(), and updateBindEdge(). |
|
|
Definition at line 43 of file tess_list.h. Referenced by NL3D::CTessNodeList::CTessNodeList(). |
|
|
|
|
|
Definition at line 249 of file tessellation.h. Referenced by canMerge(), and CTessFace(). |
|
|
Definition at line 250 of file tessellation.h. Referenced by CTessFace(), and forceMerge(). |
|
|
Definition at line 286 of file tessellation.h. Referenced by NL3D::CLandscape::appendToShadowPolyReceiver(), CTessFace(), NL3D::CLandscape::removeFromShadowPolyReceiver(), and ~CTessFace(). |
|
|
Definition at line 274 of file tessellation.h. Referenced by NL3D::CPatch::makeRoots(), split(), splitRectangular(), and unbind(). |
|
|
|
|
Definition at line 275 of file tessellation.h. Referenced by computeSplitPoint(), updateErrorMetric(), updateRefineMerge(), and updateRefineSplit(). |
|
|
Definition at line 261 of file tessellation.h. Referenced by allocTileUv(), NL3D::CPatch::appendFaceToTileRenderList(), buildTileFaces(), checkCreateFillTileVB(), checkFillTileVB(), computeTileMaterial(), copyTileUv(), CTessFace(), deleteTileFaces(), deleteTileUv(), emptyTileFaces(), heritTileUv(), NL3D::CPatch::removeFaceFromTileRenderList(), and updateNearFarVertices(). |
|
|
Definition at line 257 of file tessellation.h. Referenced by computeTileMaterial(), heritTileMaterial(), initTileUvRGBA(), and sameTile(). |
|
|
Definition at line 259 of file tessellation.h. Referenced by NL3D::CPatch::appendFaceToTileRenderList(), computeTileMaterial(), deleteTileUvs(), heritTileMaterial(), releaseTileMaterial(), and NL3D::CPatch::removeFaceFromTileRenderList(). |
|
|
|
1.3.6