#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(). |
|
|
|