From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/a03476.html | 6167 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6167 insertions(+) create mode 100644 docs/doxygen/nel/a03476.html (limited to 'docs/doxygen/nel/a03476.html') diff --git a/docs/doxygen/nel/a03476.html b/docs/doxygen/nel/a03476.html new file mode 100644 index 00000000..bf8ced51 --- /dev/null +++ b/docs/doxygen/nel/a03476.html @@ -0,0 +1,6167 @@ + + +NeL: NL3D::CTessFace class Reference + + + +
+

NL3D::CTessFace Class Reference

#include <tessellation.h> +

+

Inheritance diagram for NL3D::CTessFace: +

+ +NL3D::CTessNodeList +NL3D::CTessFacePListNode + +

Detailed Description

+A Landscape Triangle. MemSize: 28*4 octets. => for 100K faces, it takes 11.2 Mo.
Author:
Lionel Berenguier

+Nevrax France

+
Date:
2000
+ +

+ +

+Definition at line 233 of file tessellation.h. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Tile Material Infos (uvs...).

enum  TTileUvId { IdUvBase = 0, +IdUvLeft, +IdUvRight + }
CTileFaceTileFaces [NL3D_MAX_TILE_FACE]
uint8 TileId
CTileMaterialTileMaterial

Public Types


Public Member Functions

void appendPList (CTessFacePListNode &root)
void appendTessellationLeaves (std::vector< const CTessFace * > &leaves) const
void averageTesselationVertices ()
void changeNeighbor (CTessFace *from, CTessFace *to)
float computeNearLimit ()
void computeSplitPoint ()
void computeTileMaterial ()
 CTessFace ()
void deleteTileUvs ()
void forceMerge ()
void forceMergeAtTileLevel ()
void getTesselatedPos (const CUV &uv, bool verifInclusion, CVector &ret)
bool hasEdge (CTessVertex *v0, CTessVertex *v1) const
bool hasVertex (CTessVertex *v) const
bool isLeaf () const
bool isRectangular () const
void linkInPList (CTessFacePListNode &root)
 unlinkInPList, then link this node to the root of a list.

CTessFacelinkTessFaceWithEdge (const NLMISC::CVector2f &uv0, const NLMISC::CVector2f &uv1, CTessFace *linkTo)
bool merge ()
CTessFacePListNodenextInPList () const
CTessFacePListNodeprecInPList () const
 get next ptr. next==this if list empty.

void recreateTileUvs ()
void refineAll ()
 refine the node, and his sons. Refine all nodes.

void refreshTesselationGeometry ()
void releaseTileMaterial ()
void split (bool propagateSplit=true)
void unbind ()
void unlinkInPList ()
 if linked, unlink this node from his list.

void updateBind ()
void updateBindAndSplit ()
bool updateBindEdge (CTessFace *&edgeFace, bool &splitWanted)
void updateErrorMetric ()
void updateRefineMerge ()
void updateRefineSplit ()
 ~CTessFace ()

Data Fields

CTessFarVertexFVBase
CTessFarVertexFVLeft
CTessFarVertexFVRight
CTessNodeListNext
CTessNodeListPrec
sint ShadowMapTriId
Error metric.
float ErrorMetric
sint ErrorMetricDate
float MaxDistToSplitPoint
float Size
CVector SplitPoint
geometric tesselation.
CTessFaceFather
CTessFaceFBase
CTessFaceFLeft
CTessFaceFRight
uint8 Level
CPatchPatch
CParamCoord PVBase
CParamCoord PVLeft
CParamCoord PVRight
bool RecursMarkCanMerge
bool RecursMarkForceMerge
CTessFaceSonLeft
CTessFaceSonRight
CTessVertexVBase
CTessVertexVLeft
CTessVertexVRight

Static Public Attributes

CTessFace MultipleBindFace

Private Member Functions

bool canMerge (bool testEm)
void computeTesselatedPos (const CUV &uv, CVector &ret)
float computeTileEMForUpdateRefine (float distSplitPoint, float distMinFace, float nearLimit)
void computeTileErrorMetric ()
void doMerge ()
void heritTileMaterial ()
void initTileUvDLM (CParamCoord pointCoord, CUV &uv)
void initTileUvLightmap (CParamCoord pointCoord, CParamCoord middleCoord, CUV &uv)
void initTileUvRGBA (sint pass, bool alpha, CParamCoord pointCoord, CParamCoord middleCoord, CUV &uv)
void splitRectangular (bool propagateSplit)
void updateNearFarVertices ()
UV mgt.
void allocTileUv (TTileUvId id)
void buildTileFaces ()
void checkCreateFillTileVB (TTileUvId id)
void checkFillTileVB (TTileUvId id)
void copyTileUv (TTileUvId id, CTessFace *srcFace, TTileUvId srcId)
void deleteTileFaces ()
void deleteTileUv (TTileUvId id)
bool emptyTileFaces ()
void heritTileUv (CTessFace *baseFace)

Static Private Member Functions

bool sameTile (const CTessFace *a, const CTessFace *b)

Static Private Attributes

CTessFace CantMergeFace
+


Member Enumeration Documentation

+

+ + + + +
+ + +
enum NL3D::CTessFace::TTileUvId +
+
+ + + + + +
+   + + +

+

Enumeration values:
+ + + + +
IdUvBase  +
IdUvLeft  +
IdUvRight  +
+
+ +

+Definition at line 264 of file tessellation.h. +

+

00264 {IdUvBase=0, IdUvLeft, IdUvRight};
+
+


Constructor & Destructor Documentation

+

+ + + + +
+ + + + + + + + + +
NL3D::CTessFace::CTessFace  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
NL3D::CTessFace::~CTessFace  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+


Member Function Documentation

+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFace::allocTileUv TTileUvId  id  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFacePListNode::appendPList CTessFacePListNode root  )  [inherited]
+
+ + + + + +
+   + + +

+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 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFace::appendTessellationLeaves std::vector< const CTessFace * > &  leaves  )  const
+
+ + + + + +
+   + + +

+ +

+Definition at line 3194 of file tessellation.cpp. +

+References isLeaf(), SonLeft, and SonRight. +

+Referenced by NL3D::CPatch::appendTessellationLeaves(). +

+

03195 {
+03196         if(isLeaf())
+03197                 leaves.push_back(this);
+03198         else
+03199         {
+03200                 SonLeft->appendTessellationLeaves(leaves);
+03201                 SonRight->appendTessellationLeaves(leaves);
+03202         }
+03203 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::averageTesselationVertices  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::buildTileFaces  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + +
bool NL3D::CTessFace::canMerge bool  testEm  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CTessFace::changeNeighbor CTessFace from,
CTessFace to
[inline]
+
+ + + + + +
+   + + +

+ +

+Definition at line 298 of file tessellation.h. +

+References FBase, FLeft, FRight, and from. +

+Referenced by doMerge(), split(), splitRectangular(), unbind(), and updateBindAndSplit(). +

+

00299         {
+00300                 if(FBase==from) FBase=to;
+00301                 if(FLeft==from) FLeft=to;
+00302                 if(FRight==from) FRight=to;
+00303         }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFace::checkCreateFillTileVB TTileUvId  id  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFace::checkFillTileVB TTileUvId  id  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
float NL3D::CTessFace::computeNearLimit  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::computeSplitPoint  ) 
+
+ + + + + +
+   + + +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CTessFace::computeTesselatedPos const CUV uv,
CVector ret
[private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
float NL3D::CTessFace::computeTileEMForUpdateRefine float  distSplitPoint,
float  distMinFace,
float  nearLimit
[inline, private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::computeTileErrorMetric  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::computeTileMaterial  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CTessFace::copyTileUv TTileUvId  id,
CTessFace srcFace,
TTileUvId  srcId
[private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::deleteTileFaces  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFace::deleteTileUv TTileUvId  id  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::deleteTileUvs  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::doMerge  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CTessFace::emptyTileFaces  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::forceMerge  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::forceMergeAtTileLevel  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CTessFace::getTesselatedPos const CUV uv,
bool  verifInclusion,
CVector ret
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
bool NL3D::CTessFace::hasEdge CTessVertex v0,
CTessVertex v1
const [inline]
+
+ + + + + +
+   + + +

+ +

+Definition at line 297 of file tessellation.h. +

+References hasVertex(). +

+

00297 {return hasVertex(v0) && hasVertex(v1);}
+
+

+ + + + +
+ + + + + + + + + + +
bool NL3D::CTessFace::hasVertex CTessVertex v  )  const [inline]
+
+ + + + + +
+   + + +

+ +

+Definition at line 296 of file tessellation.h. +

+References v, VBase, VLeft, and VRight. +

+Referenced by hasEdge(). +

+

00296 {return VBase==v || VLeft==v || VRight==v;}
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::heritTileMaterial  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFace::heritTileUv CTessFace baseFace  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
void NL3D::CTessFace::initTileUvDLM CParamCoord  pointCoord,
CUV uv
[private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CTessFace::initTileUvLightmap CParamCoord  pointCoord,
CParamCoord  middleCoord,
CUV uv
[private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void NL3D::CTessFace::initTileUvRGBA sint  pass,
bool  alpha,
CParamCoord  pointCoord,
CParamCoord  middleCoord,
CUV uv
[private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CTessFace::isLeaf  )  const [inline]
+
+ + + + + +
+   + + +

+ +

+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;}
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CTessFace::isRectangular  )  const
+
+ + + + + +
+   + + +

+ +

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

+

02955 {
+02956         return Level<Patch->SquareLimitLevel;
+02957 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFacePListNode::linkInPList CTessFacePListNode root  )  [inherited]
+
+ + + + + +
+   + + +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CTessFace * NL3D::CTessFace::linkTessFaceWithEdge const NLMISC::CVector2f uv0,
const NLMISC::CVector2f uv1,
CTessFace linkTo
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
bool NL3D::CTessFace::merge  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
CTessFacePListNode* NL3D::CTessFacePListNode::nextInPList  )  const [inline, inherited]
+
+ + + + + +
+   + + +

+ +

+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;}
+
+

+ + + + +
+ + + + + + + + + +
CTessFacePListNode* NL3D::CTessFacePListNode::precInPList  )  const [inline, inherited]
+
+ + + + + +
+   + + +

+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;}
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::recreateTileUvs  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::refineAll  ) 
+
+ + + + + +
+   + + +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::refreshTesselationGeometry  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::releaseTileMaterial  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
bool NL3D::CTessFace::sameTile const CTessFace a,
const CTessFace b
[inline, static, private]
+
+ + + + + +
+   + + +

+ +

+Definition at line 368 of file tessellation.h. +

+References Patch, and TileId. +

+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         }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFace::split bool  propagateSplit = true  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + +
void NL3D::CTessFace::splitRectangular bool  propagateSplit  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::unbind  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFacePListNode::unlinkInPList  )  [inherited]
+
+ + + + + +
+   + + +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::updateBind  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::updateBindAndSplit  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + + + + + + + + + + + +
bool NL3D::CTessFace::updateBindEdge CTessFace *&  edgeFace,
bool &  splitWanted
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::updateErrorMetric  ) 
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::updateNearFarVertices  )  [private]
+
+ + + + + +
+   + + +

+ +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::updateRefineMerge  ) 
+
+ + + + + +
+   + + +

+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 }
+
+

+ + + + +
+ + + + + + + + + +
void NL3D::CTessFace::updateRefineSplit  ) 
+
+ + + + + +
+   + + +

+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 }
+
+


Field Documentation

+

+ + + + +
+ + +
CTessFace NL3D::CTessFace::CantMergeFace [static, private] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 156 of file tessellation.cpp. +

+Referenced by averageTesselationVertices(), canMerge(), forceMerge(), forceMergeAtTileLevel(), and updateBindAndSplit().

+

+ + + + +
+ + +
float NL3D::CTessFace::ErrorMetric +
+
+ + + + + +
+   + + +

+ +

+Definition at line 276 of file tessellation.h. +

+Referenced by canMerge(), computeTileErrorMetric(), refineAll(), updateErrorMetric(), updateRefineMerge(), and updateRefineSplit().

+

+ + + + +
+ + +
sint NL3D::CTessFace::ErrorMetricDate +
+
+ + + + + +
+   + + +

+ +

+Definition at line 273 of file tessellation.h. +

+Referenced by CTessFace(), and updateErrorMetric().

+

+ + + + +
+ + +
CTessFace* NL3D::CTessFace::Father +
+
+ + + + + +
+   + + +

+ +

+Definition at line 243 of file tessellation.h. +

+Referenced by split(), and splitRectangular().

+

+ + + + +
+ + +
CTessFace* NL3D::CTessFace::FBase +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
CTessFace * NL3D::CTessFace::FLeft +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
CTessFace * NL3D::CTessFace::FRight +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
CTessFarVertex* NL3D::CTessFace::FVBase +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
CTessFarVertex * NL3D::CTessFace::FVLeft +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
CTessFarVertex * NL3D::CTessFace::FVRight +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
uint8 NL3D::CTessFace::Level +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
float NL3D::CTessFace::MaxDistToSplitPoint +
+
+ + + + + +
+   + + +

+ +

+Definition at line 277 of file tessellation.h. +

+Referenced by computeSplitPoint(), and updateErrorMetric().

+

+ + + + +
+ + +
CTessFace NL3D::CTessFace::MultipleBindFace [static] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 157 of file tessellation.cpp.

+

+ + + + +
+ + +
CTessNodeList* NL3D::CTessNodeList::Next [inherited] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 44 of file tess_list.h. +

+Referenced by NL3D::CVegetableManager::addInstance(), NL3D::CLandscape::computeDynamicLighting(), NL3D::CPatch::computeGeomorphAlphaFar1VertexListVB(), NL3D::CPatch::computeGeomorphFar0VertexListVB(), NL3D::CPatch::computeGeomorphTileVertexListVB(), NL3D::CPatch::computeGeomorphVertexList(), NL3D::CPatch::debugAllocationMarkIndicesFarList(), NL3D::CPatch::debugAllocationMarkIndicesNearList(), NL3D::CPatch::fillFar0DLMUvOnlyVertexListVB(), NL3D::CPatch::fillFar0VertexListVB(), NL3D::CPatch::fillFar1DLMUvOnlyVertexListVB(), NL3D::CPatch::fillFar1VertexListVB(), NL3D::CPatch::fillTileVertexListVB(), NL3D::CLandscape::getDynamicLightingMemoryLoad(), NL3D::CTessBlock::refillFaceVectorFar0(), NL3D::CTessBlock::refillFaceVectorFar1(), NL3D::CTessBlock::refillFaceVectorTile(), NL3D::CLandscape::refine(), NL3D::CVegetableManager::render(), NL3D::CLandscape::render(), NL3D::CPatch::updateFar0VBAlloc(), NL3D::CPatch::updateFar1VBAlloc(), NL3D::CVegetableSortBlock::updateSortBlock(), and NL3D::CPatch::updateTileVBAlloc().

+

+ + + + +
+ + +
CPatch* NL3D::CTessFace::Patch +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
CTessNodeList* NL3D::CTessNodeList::Prec [inherited] +
+
+ + + + + +
+   + + +

+ +

+Definition at line 43 of file tess_list.h. +

+Referenced by NL3D::CTessNodeList::CTessNodeList().

+

+ + + + +
+ + +
CParamCoord NL3D::CTessFace::PVBase +
+
+ + + + + +
+   + + +

+ +

+Definition at line 245 of file tessellation.h. +

+Referenced by NL3D::CZoneLighter::addTriangles(), averageTesselationVertices(), NL3D::CZoneLighter::buildZoneInformation(), computeTesselatedPos(), computeTileMaterial(), NL3D::CPatch::getNumTessBlock(), getTesselatedPos(), linkTessFaceWithEdge(), NL3D::CPatch::makeRoots(), refreshTesselationGeometry(), split(), splitRectangular(), and updateNearFarVertices().

+

+ + + + +
+ + +
CParamCoord NL3D::CTessFace::PVLeft +
+
+ + + + + +
+   + + +

+ +

+Definition at line 245 of file tessellation.h. +

+Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CZoneLighter::buildZoneInformation(), computeTesselatedPos(), computeTileMaterial(), NL3D::CPatch::getNumTessBlock(), getTesselatedPos(), linkTessFaceWithEdge(), NL3D::CPatch::makeRoots(), split(), splitRectangular(), and updateNearFarVertices().

+

+ + + + +
+ + +
CParamCoord NL3D::CTessFace::PVRight +
+
+ + + + + +
+   + + +

+ +

+Definition at line 245 of file tessellation.h. +

+Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CZoneLighter::buildZoneInformation(), computeTesselatedPos(), computeTileMaterial(), NL3D::CPatch::getNumTessBlock(), getTesselatedPos(), linkTessFaceWithEdge(), NL3D::CPatch::makeRoots(), split(), splitRectangular(), and updateNearFarVertices().

+

+ + + + +
+ + +
bool NL3D::CTessFace::RecursMarkCanMerge +
+
+ + + + + +
+   + + +

+ +

+Definition at line 249 of file tessellation.h. +

+Referenced by canMerge(), and CTessFace().

+

+ + + + +
+ + +
bool NL3D::CTessFace::RecursMarkForceMerge +
+
+ + + + + +
+   + + +

+ +

+Definition at line 250 of file tessellation.h. +

+Referenced by CTessFace(), and forceMerge().

+

+ + + + +
+ + +
sint NL3D::CTessFace::ShadowMapTriId +
+
+ + + + + +
+   + + +

+ +

+Definition at line 286 of file tessellation.h. +

+Referenced by NL3D::CLandscape::appendToShadowPolyReceiver(), CTessFace(), NL3D::CLandscape::removeFromShadowPolyReceiver(), and ~CTessFace().

+

+ + + + +
+ + +
float NL3D::CTessFace::Size +
+
+ + + + + +
+   + + +

+ +

+Definition at line 274 of file tessellation.h. +

+Referenced by NL3D::CPatch::makeRoots(), split(), splitRectangular(), and unbind().

+

+ + + + +
+ + +
CTessFace * NL3D::CTessFace::SonLeft +
+
+ + + + + +
+   + + +

+ +

+Definition at line 243 of file tessellation.h. +

+Referenced by appendTessellationLeaves(), averageTesselationVertices(), NL3D::CPatch::bind(), canMerge(), CTessFace(), deleteTileUvs(), doMerge(), forceMerge(), forceMergeAtTileLevel(), getTesselatedPos(), heritTileMaterial(), isLeaf(), linkTessFaceWithEdge(), recreateTileUvs(), refineAll(), refreshTesselationGeometry(), split(), splitRectangular(), unbind(), updateBind(), updateBindAndSplit(), and updateBindEdge().

+

+ + + + +
+ + +
CTessFace * NL3D::CTessFace::SonRight +
+
+ + + + + +
+   + + +

+ +

+Definition at line 243 of file tessellation.h. +

+Referenced by appendTessellationLeaves(), averageTesselationVertices(), NL3D::CPatch::bind(), canMerge(), CTessFace(), deleteTileUvs(), doMerge(), forceMerge(), forceMergeAtTileLevel(), getTesselatedPos(), heritTileMaterial(), linkTessFaceWithEdge(), recreateTileUvs(), refineAll(), refreshTesselationGeometry(), split(), splitRectangular(), unbind(), updateBind(), updateBindAndSplit(), and updateBindEdge().

+

+ + + + +
+ + +
CVector NL3D::CTessFace::SplitPoint +
+
+ + + + + +
+   + + +

+ +

+Definition at line 275 of file tessellation.h. +

+Referenced by computeSplitPoint(), updateErrorMetric(), updateRefineMerge(), and updateRefineSplit().

+

+ + + + +
+ + +
CTileFace* NL3D::CTessFace::TileFaces[NL3D_MAX_TILE_FACE] +
+
+ + + + + +
+   + + +

+ +

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

+

+ + + + +
+ + +
uint8 NL3D::CTessFace::TileId +
+
+ + + + + +
+   + + +

+ +

+Definition at line 257 of file tessellation.h. +

+Referenced by computeTileMaterial(), heritTileMaterial(), initTileUvRGBA(), and sameTile().

+

+ + + + +
+ + +
CTileMaterial* NL3D::CTessFace::TileMaterial +
+
+ + + + + +
+   + + +

+ +

+Definition at line 259 of file tessellation.h. +

+Referenced by NL3D::CPatch::appendFaceToTileRenderList(), computeTileMaterial(), deleteTileUvs(), heritTileMaterial(), releaseTileMaterial(), and NL3D::CPatch::removeFaceFromTileRenderList().

+

+ + + + +
+ + +
CTessVertex* NL3D::CTessFace::VBase +
+
+ + + + + +
+   + + +

+ +

+Definition at line 241 of file tessellation.h. +

+Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), allocTileUv(), NL3D::CPatch::appendFaceToRenderList(), NL3D::CLandscape::appendToShadowPolyReceiver(), averageTesselationVertices(), NL3D::CPatch::bind(), NL3D::CZoneLighter::buildZoneInformation(), computeSplitPoint(), computeTesselatedPos(), computeTileErrorMetric(), CTessFace(), doMerge(), NL3D::CPatch::extendTessBlockWithEndPos(), NL3D::CPatch::getRootVertexForEdge(), hasVertex(), NL3D::CPatch::makeRoots(), refreshTesselationGeometry(), split(), splitRectangular(), unbind(), updateBindAndSplit(), updateNearFarVertices(), updateRefineMerge(), and updateRefineSplit().

+

+ + + + +
+ + +
CTessVertex * NL3D::CTessFace::VLeft +
+
+ + + + + +
+   + + +

+ +

+Definition at line 241 of file tessellation.h. +

+Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), allocTileUv(), NL3D::CPatch::appendFaceToRenderList(), NL3D::CLandscape::appendToShadowPolyReceiver(), NL3D::CZoneLighter::buildZoneInformation(), computeSplitPoint(), computeTesselatedPos(), computeTileErrorMetric(), CTessFace(), NL3D::CPatch::extendTessBlockWithEndPos(), NL3D::CPatch::getRootVertexForEdge(), hasVertex(), NL3D::CPatch::makeRoots(), split(), splitRectangular(), unbind(), updateNearFarVertices(), updateRefineMerge(), and updateRefineSplit().

+

+ + + + +
+ + +
CTessVertex * NL3D::CTessFace::VRight +
+
+ + + + + +
+   + + +

+ +

+Definition at line 241 of file tessellation.h. +

+Referenced by NL3D::CZoneLighter::addTriangles(), NL3D::CInstanceLighter::addTriangles(), allocTileUv(), NL3D::CPatch::appendFaceToRenderList(), NL3D::CLandscape::appendToShadowPolyReceiver(), NL3D::CZoneLighter::buildZoneInformation(), computeSplitPoint(), computeTesselatedPos(), computeTileErrorMetric(), CTessFace(), NL3D::CPatch::extendTessBlockWithEndPos(), NL3D::CPatch::getRootVertexForEdge(), hasVertex(), NL3D::CPatch::makeRoots(), split(), splitRectangular(), unbind(), updateBindAndSplit(), updateNearFarVertices(), updateRefineMerge(), and updateRefineSplit().

+


The documentation for this class was generated from the following files: +
Generated on Tue Mar 16 07:48:38 2004 for NeL by + +doxygen +1.3.6
+ + -- cgit v1.2.1