diff options
Diffstat (limited to 'docs/doxygen/nel/tessellation_8cpp-source.html')
-rw-r--r-- | docs/doxygen/nel/tessellation_8cpp-source.html | 3263 |
1 files changed, 3263 insertions, 0 deletions
diff --git a/docs/doxygen/nel/tessellation_8cpp-source.html b/docs/doxygen/nel/tessellation_8cpp-source.html new file mode 100644 index 00000000..1aec2208 --- /dev/null +++ b/docs/doxygen/nel/tessellation_8cpp-source.html @@ -0,0 +1,3263 @@ +<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> +<HTML> +<HEAD> + <TITLE>nevrax.org : docs</TITLE> + <LINK REL=stylesheet TYPE="text/css" HREF="http://www.nevrax.org/inc/css/nevrax.css"> + <link href="doxygen.css" rel="stylesheet" type="text/css"> +</HEAD> +<BODY MARGINHEIGHT="0" MARGINWIDTH="0"> + +<!-- uplinks --> +<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0> + <TR> + <TD WIDTH=16><IMG SRC="http://www.nevrax.org/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD> + <TD WIDTH=140 BGCOLOR=#dddddd><IMG SRC="http://www.nevrax.org/inc/img/pixel.gif" WIDTH="140" HEIGHT="16" BORDER=0 ALT=""></TD> + <TD WIDTH=16><IMG SRC="http://www.nevrax.org/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD> + <TD><IMG width=6 height=14 SRC="http://www.nevrax.org/inc/img/reddots.gif" ALT="#" VSPACE=2 HSPACE=2 BORDER=0 ></TD><TD VALIGN=middle> <A CLASS=uplinks HREF=http://www.nevrax.org><b>Home</B></FONT></A> </TD> + <TD><IMG width=6 height=14 SRC="http://www.nevrax.org/inc/img/reddots.gif" ALT="#" VSPACE=2 HSPACE=2 BORDER=0 ></TD><TD VALIGN=middle> <A CLASS=uplinks HREF=http://www.nevrax.com><b>nevrax.com</B></FONT></A> </TD> + </TR> +</TABLE> + +<!-- banner Nevrax --> +<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%> + <TR><TD BGCOLOR="#000000" BACKGROUND="http://www.nevrax.org/inc/img/black_banner.jpg"><A HREF="http://www.nevrax.org"><IMG SRC="http://www.nevrax.org/inc/img/nevrax.gif" WIDTH="170" HEIGHT="45" BORDER=0 ALT="Nevrax" ></A></TD></TR> +</TABLE> + +<!-- main table --> +<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 height=100%> + <TR> + <TD WIDTH=16><IMG SRC="http://www.nevrax.org/inc/img/pixel.gif" WIDTH="16" HEIGHT="10" BORDER=0 ALT=""></TD> + <TD WIDTH=140 BGCOLOR=#dddddd VALIGN=TOP ALIGN=middle><IMG SRC="http://www.nevrax.org/inc/img/pixel.gif" WIDTH="140" HEIGHT="10" BORDER=0 ALT=""> + + <!------ Begin Box ------> + <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 BGCOLOR=black><TR><TD><TABLE border=0 cellspacing=2 cellpadding=0 width=120><tr><TD ALIGN=middle bgcolor=black> + <FONT COLOR=white FACE="sans-serif"><B>Nevrax.org</B></FONT></TD></TR><tr><td colspan=2 bgcolor=#FFFFFF> + <TABLE cellspacing=0 cellpadding=1 border=0> + <tr><td ALIGN=middle><a class='linkbox' href="http://www.nevrax.org/news/" TITLE="Rubrique news"><img width=13 height=15 hspace=5 border=0 src=http://www.nevrax.org/inc/img/picto-news.gif ALT=#></A></td><td><a class='linkbox' href="http://www.nevrax.org/news/" TITLE="News">News</a></td></tr> + <tr><td ALIGN=middle><a class='linkbox' href="http://www.nevrax.org/mail/" TITLE="Rubrique mail"><img width=15 height=11 hspace=5 border=0 src=http://www.nevrax.org/inc/img/picto-mail.gif ALT=#></A></td><td><a class='linkbox' href="http://www.nevrax.org/mail/" TITLE="Mailing list archive">Mailing-list</a></td></tr> + <tr><td ALIGN=middle><a class='linkbox' href="http://www.nevrax.org/docs/" TITLE="Rubrique docs"><img width=14 height=16 hspace=5 border=0 src=http://www.nevrax.org/inc/img/picto-docs.gif ALT=#></A></td><td><a class='linkbox' href="http://www.nevrax.org/docs/" TITLE="Documentation">Documentation</a></td></tr> + <tr><td ALIGN=middle><a class='linkbox' href="http://www.nevrax.org/cvs/" TITLE="Rubrique cvs"><img width=13 height=17 hspace=5 border=0 src=http://www.nevrax.org/inc/img/picto-cvs.gif ALT=#></A></td><td><a class='linkbox' href="http://www.nevrax.org/cvs/" TITLE="CVS Web">CVS</a></td></tr> + <tr><td ALIGN=middle><a class='linkbox' href="http://www.nevrax.org/bugs/" TITLE="Rubrique bugs"><img width=20 height=16 hspace=5 border=0 src=http://www.nevrax.org/inc/img/picto-bugs.gif ALT=#></A></td><td><a class='linkbox' href="http://www.nevrax.org/bugs/" TITLE="Bugtracking">Bugs</a></td></tr> + <tr><td ALIGN=middle><a class='linkbox' href="http://www.nevrax.org/GPL.php3" TITLE="Rubrique license"><img width=18 height=12 hspace=5 border=0 src=http://www.nevrax.org/inc/img/picto-gpl.gif ALT=#></A></td><td><a class='linkbox' href="http://www.nevrax.org/GPL.php3" TITLE="License">License</a></td></tr> + </TABLE> + </TD></TR></TABLE></TD></TR></TABLE> + <!------ End Box ------> + + </TD> + <TD WIDTH=15><IMG SRC="http://www.nevrax.org/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD> + <TD ALIGN=left valign=top><IMG SRC="http://www.nevrax.org/inc/img/pixel.gif" WIDTH="140" HEIGHT="10" BORDER=0 ALT=""> + +<!-- title --> +<TABLE background="http://www.nevrax.org/inc/img/redline.gif" CELLSPACING=0 CELLPADDING=0 BORDER=0 width=100%><tr><td> +<A HREF="http://www.nevrax.org/docs/"><img src="http://www.nevrax.org/inc/img/t_docs.gif" ALT="Docs" HEIGHT=20 BORDER=0></A> +</td><td><IMG SRC="http://www.nevrax.org/inc/img/pixel.gif" WIDTH="1" HEIGHT="1" BORDER=0 ALT=""> +</td></tr></table> + + +<!-- block --> +<TABLE bgcolor="#dddddd" CELLSPACING=0 CELLPADDING=0 BORDER=0 width=100%><tr><td width=1% valign=middle><img width=6 height=14 hspace=2 vspace=2 src="http://www.nevrax.org/inc/img/reddots.gif"></TD> + <TD><B>Documentation</B></TD> + <TD ALIGN=RIGHT> </td> +</tr></table> +<!-- Generated by Doxygen 1.2.14 --> +<center> +<a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="namespaces.html">Namespace List</a> <a class="qindex" href="hierarchy.html">Class Hierarchy</a> <a class="qindex" href="classes.html">Alphabetical List</a> <a class="qindex" href="annotated.html">Compound List</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="namespacemembers.html">Namespace Members</a> <a class="qindex" href="functions.html">Compound Members</a> <a class="qindex" href="globals.html">File Members</a> <a class="qindex" href="pages.html">Related Pages</a> <a class="qindexRef" doxygen="_cgi:http://www.nevrax.org/cgi-bin/nel-search.cgi" href="http://www.nevrax.org/cgi-bin/nel-search.cgi">Search</a> </center> +<hr><h1>tessellation.cpp</h1><a href="tessellation_8cpp.html">Go to the documentation of this file.</a><div class="fragment"><pre>00001 +00008 <font class="comment">/* Copyright, 2000 Nevrax Ltd.</font> +00009 <font class="comment"> *</font> +00010 <font class="comment"> * This file is part of NEVRAX NEL.</font> +00011 <font class="comment"> * NEVRAX NEL is free software; you can redistribute it and/or modify</font> +00012 <font class="comment"> * it under the terms of the GNU General Public License as published by</font> +00013 <font class="comment"> * the Free Software Foundation; either version 2, or (at your option)</font> +00014 <font class="comment"> * any later version.</font> +00015 <font class="comment"></font> +00016 <font class="comment"> * NEVRAX NEL is distributed in the hope that it will be useful, but</font> +00017 <font class="comment"> * WITHOUT ANY WARRANTY; without even the implied warranty of</font> +00018 <font class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU</font> +00019 <font class="comment"> * General Public License for more details.</font> +00020 <font class="comment"></font> +00021 <font class="comment"> * You should have received a copy of the GNU General Public License</font> +00022 <font class="comment"> * along with NEVRAX NEL; see the file COPYING. If not, write to the</font> +00023 <font class="comment"> * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,</font> +00024 <font class="comment"> * MA 02111-1307, USA.</font> +00025 <font class="comment"> */</font> +00026 +00027 <font class="preprocessor">#include "<a class="code" href="std3d_8h.html">std3d.h</a>"</font> +00028 +00029 <font class="preprocessor">#include "<a class="code" href="tessellation_8h.html">3d/tessellation.h</a>"</font> +00030 <font class="preprocessor">#include "<a class="code" href="patch_8h.html">3d/patch.h</a>"</font> +00031 <font class="preprocessor">#include "<a class="code" href="src_23d_2zone_8h.html">3d/zone.h</a>"</font> +00032 <font class="preprocessor">#include "<a class="code" href="common_8h.html">nel/misc/common.h</a>"</font> +00033 <font class="preprocessor">#include "<a class="code" href="landscape__profile_8h.html">3d/landscape_profile.h</a>"</font> +00034 <font class="preprocessor">#include "<a class="code" href="landscape_8h.html">3d/landscape.h</a>"</font> +00035 <font class="preprocessor">#include "<a class="code" href="patchdlm__context_8h.html">3d/patchdlm_context.h</a>"</font> +00036 <font class="keyword">using</font> <font class="keyword">namespace </font>NLMISC; +00037 <font class="keyword">using</font> <font class="keyword">namespace </font>std; +00038 +00039 +00040 <font class="keyword">namespace </font>NL3D +00041 { +00042 +00043 +00044 <font class="comment">// ***************************************************************************</font> +<a name="l00045"></a><a class="code" href="tessellation_8cpp.html#a0">00045</a> <font class="preprocessor">#define NL3D_TESS_USE_QUADRANT_THRESHOLD 0.1f</font> +00046 <font class="preprocessor"></font> +00047 +00048 <font class="comment">// ***************************************************************************</font> +00049 <font class="comment">// The normal Uvs format.</font> +00050 <font class="keyword">const</font> uint8 <a class="code" href="namespaceNL3D.html#a238">TileUvFmtNormal1</a>= 0; +00051 <font class="keyword">const</font> uint8 <a class="code" href="namespaceNL3D.html#a239">TileUvFmtNormal2</a>= 1; +00052 <font class="keyword">const</font> uint8 <a class="code" href="namespaceNL3D.html#a240">TileUvFmtNormal3</a>= 2; +00053 <font class="keyword">const</font> uint8 <a class="code" href="namespaceNL3D.html#a241">TileUvFmtNormal4</a>= 3; +00054 <font class="keyword">const</font> uint8 <a class="code" href="namespaceNL3D.html#a242">TileUvFmtNormal5</a>= 4; +00055 +00056 +00057 <font class="comment">// ***************************************************************************</font> +00058 <font class="comment">// \todo yoyo: may change this.</font> +00059 <font class="keyword">const</font> <font class="keywordtype">float</font> <a class="code" href="namespaceNL3D.html#a243">TileSize</a>= 128; +00060 +00061 +00062 +00063 +00064 <font class="comment">// ***************************************************************************</font> +00065 <font class="comment">// ***************************************************************************</font> +00066 <font class="comment">// CTileMaterial</font> +00067 <font class="comment">// ***************************************************************************</font> +00068 <font class="comment">// ***************************************************************************</font> +00069 +00070 +00071 <font class="comment">// ***************************************************************************</font> +<a name="l00072"></a><a class="code" href="structNL3D_1_1CTileMaterial.html#a0">00072</a> CTileMaterial::CTileMaterial() +00073 { +00074 <font class="comment">// By default, all pass are NULL.</font> +00075 <font class="keywordflow">for</font>(uint i=0; i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>; i++) +00076 { +00077 <a class="code" href="structNL3D_1_1CTileMaterial.html#m4">TileFaceVectors</a>[i]= NULL; +00078 } +00079 } +00080 +00081 +00082 <font class="comment">// ***************************************************************************</font> +<a name="l00083"></a><a class="code" href="structNL3D_1_1CTileMaterial.html#a1">00083</a> <font class="keywordtype">void</font> CTileMaterial::appendTileToEachRenderPass(uint patchNumRenderableFaces) +00084 { +00085 <font class="keywordflow">for</font>(uint i=0;i<<a class="code" href="landscape__def_8h.html#a0">NL3D_MAX_TILE_PASS</a>;i++) +00086 { +00087 <font class="comment">// If RdrPass exist, add this Material Id</font> +00088 CPatchRdrPass *rdrPass= <a class="code" href="structNL3D_1_1CTileMaterial.html#m2">Pass</a>[i].PatchRdrPass; +00089 <font class="keywordflow">if</font>(rdrPass!=NULL) +00090 { +00091 <font class="comment">/* enlarge the capacity of the pass so it can renders the tile faces of this patch.</font> +00092 <font class="comment"> * NumRenderableFaces is really too big since the tile-material surely doesn't use all</font> +00093 <font class="comment"> * faces of the patch (except if same texture...)</font> +00094 <font class="comment"> * But doesn't matter. Even if all the visible Tile Surface (80m*80m) is in the same pass,</font> +00095 <font class="comment"> * it leads to only 76K final in CLandscapeGlobals::PassTriArray:</font> +00096 <font class="comment"> * 80*80(Visible surface at 80m max) /4 (2m*2m) *2(triangles) *2 (over-estimate) *3*4(triSize)=</font> +00097 <font class="comment"> * 76800</font> +00098 <font class="comment"> */</font> +00099 rdrPass->appendRdrPatchTile(i, &<a class="code" href="structNL3D_1_1CTileMaterial.html#m2">Pass</a>[i], patchNumRenderableFaces); +00100 } +00101 } +00102 } +00103 +00104 +00105 <font class="comment">// ***************************************************************************</font> +00106 <font class="comment">// ***************************************************************************</font> +00107 <font class="comment">// CTessVertex</font> +00108 <font class="comment">// ***************************************************************************</font> +00109 <font class="comment">// ***************************************************************************</font> +00110 +00111 +00112 <font class="comment">// ***************************************************************************</font> +<a name="l00113"></a><a class="code" href="classNL3D_1_1CTessVertex.html#a1">00113</a> <font class="keywordtype">void</font> CTessVertex::computeGeomPos() +00114 { +00115 <font class="comment">// Compute Basic ErrorMetric.</font> +00116 <font class="keywordtype">float</font> sqrDist= (<a class="code" href="classNL3D_1_1CTessVertex.html#m1">StartPos</a> - CLandscapeGlobals::RefineCenter).sqrnorm(); +00117 <font class="keywordtype">float</font> pgeom= <a class="code" href="classNL3D_1_1CTessVertex.html#m3">MaxFaceSize</a> * CLandscapeGlobals::OORefineThreshold / sqrDist; +00118 +00119 <font class="comment">// Compute ErrorMetric modified by TileNear transition, only if TileNear transition.</font> +00120 <font class="keywordflow">if</font>( sqrDist< CLandscapeGlobals::TileDistFarSqr ) +00121 { +00122 <font class="comment">// Soft optim: do it only if necessary, ie result of max(errorMetric, errorMetricModified) is foreseeable here.</font> +00123 <font class="keywordflow">if</font>(pgeom < <a class="code" href="classNL3D_1_1CTessVertex.html#m4">MaxNearLimit</a>) +00124 { +00125 <font class="keywordtype">float</font> f= (CLandscapeGlobals::TileDistFarSqr - sqrDist) * CLandscapeGlobals::OOTileDistDeltaSqr; +00126 <a class="code" href="namespaceNLMISC.html#a215">clamp</a>(f, 0, 1); +00127 <font class="comment">// ^4 gives better smooth result</font> +00128 f= <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(f); +00129 f= <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(f); +00130 <font class="comment">// interpolate the errorMetric</font> +00131 pgeom= <a class="code" href="classNL3D_1_1CTessVertex.html#m4">MaxNearLimit</a>*f + pgeom*(1-f); +00132 } +00133 } +00134 +00135 <font class="comment">// Interpolate StartPos to EndPos, between 1 and 2.</font> +00136 <font class="keywordflow">if</font>(pgeom<=1.0f) +00137 <a class="code" href="classNL3D_1_1CTessVertex.html#m0">Pos</a>= <a class="code" href="classNL3D_1_1CTessVertex.html#m1">StartPos</a>; +00138 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(pgeom>=2.0f) +00139 <a class="code" href="classNL3D_1_1CTessVertex.html#m0">Pos</a>= <a class="code" href="classNL3D_1_1CTessVertex.html#m2">EndPos</a>; +00140 <font class="keywordflow">else</font> +00141 { +00142 <font class="keywordtype">float</font> f= pgeom - 1.0f; +00143 <a class="code" href="classNL3D_1_1CTessVertex.html#m0">Pos</a>= f * (<a class="code" href="classNL3D_1_1CTessVertex.html#m2">EndPos</a>-<a class="code" href="classNL3D_1_1CTessVertex.html#m1">StartPos</a>) + <a class="code" href="classNL3D_1_1CTessVertex.html#m1">StartPos</a>; +00144 } +00145 } +00146 +00147 +00148 <font class="comment">// ***************************************************************************</font> +00149 <font class="comment">// ***************************************************************************</font> +00150 <font class="comment">// CTessFace</font> +00151 <font class="comment">// ***************************************************************************</font> +00152 <font class="comment">// ***************************************************************************</font> +00153 +00154 +00155 <font class="comment">// ***************************************************************************</font> +<a name="l00156"></a><a class="code" href="classNL3D_1_1CTessFace.html#r0">00156</a> CTessFace CTessFace::CantMergeFace; +<a name="l00157"></a><a class="code" href="classNL3D_1_1CTessFace.html#p0">00157</a> CTessFace CTessFace::MultipleBindFace; +00158 +00159 +00160 <font class="comment">// ***************************************************************************</font> +<a name="l00161"></a><a class="code" href="classNL3D_1_1CTessFace.html#a0">00161</a> CTessFace::CTessFace() +00162 { +00163 <font class="comment">// Don't modify any of it!!</font> +00164 <font class="comment">// Patch, SonLeft and SonRight nullity are very usefull for MultiplePatch faces, and CantMergeFace.</font> +00165 +00166 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>= NULL; +00167 <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>= NULL; +00168 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>= NULL; +00169 <a class="code" href="classNL3D_1_1CTessFace.html#z819_7">Father</a>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>= NULL; +00170 <a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>=0; +00171 <a class="code" href="classNL3D_1_1CTessFace.html#z821_0">ErrorMetricDate</a>= 0; +00172 <font class="comment">// Size, Center, paramcoord undetermined.</font> +00173 +00174 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>= NULL; +00175 <font class="comment">// Very important (for split reasons). Init Tilefaces to NULL.</font> +00176 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00177 { +00178 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]=NULL; +00179 } +00180 +00181 <a class="code" href="classNL3D_1_1CTessFace.html#z819_14">RecursMarkCanMerge</a>=<font class="keyword">false</font>; +00182 <a class="code" href="classNL3D_1_1CTessFace.html#z819_15">RecursMarkForceMerge</a>=<font class="keyword">false</font>; +00183 +00184 +00185 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a73">ProfNTessFace</a>, 1); +00186 } +00187 +00188 +00189 <font class="comment">// ***************************************************************************</font> +<a name="l00190"></a><a class="code" href="classNL3D_1_1CTessFace.html#a1">00190</a> CTessFace::~CTessFace() +00191 { +00192 <font class="comment">// Old Code. This is not sufficient to clear the CTessFace.</font> +00193 <font class="comment">// Vertices and Uvs must be correctly cleared too (but difficult because of sharing).</font> +00194 <font class="comment">/*</font> +00195 <font class="comment"> Patch->getLandscape()->deleteTessFace(SonLeft);</font> +00196 <font class="comment"> Patch->getLandscape()->deleteTessFace(SonRight);</font> +00197 <font class="comment"></font> +00198 <font class="comment"> // update neighbors.</font> +00199 <font class="comment"> if(FBase) FBase->changeNeighbor(this, NULL);</font> +00200 <font class="comment"> if(FLeft) FLeft->changeNeighbor(this, NULL);</font> +00201 <font class="comment"> if(FRight) FRight->changeNeighbor(this, NULL);</font> +00202 <font class="comment"></font> +00203 <font class="comment"> FBase=FLeft=FRight= NULL;</font> +00204 <font class="comment"> */</font> +00205 +00206 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a73">ProfNTessFace</a>, -1); +00207 } +00208 +00209 +00210 <font class="comment">// ***************************************************************************</font> +<a name="l00211"></a><a class="code" href="classNL3D_1_1CTessFace.html#a9">00211</a> <font class="keywordtype">float</font> CTessFace::computeNearLimit() +00212 { +00213 <font class="comment">// General formula for Level, function of Size, treshold etc...:</font> +00214 <font class="comment">// WantedLevel= log2(BaseSize / sqrdist / RefineThreshold);</font> +00215 <font class="comment">// <=> WantedLevel= log2( CurSize*2^Level / sqrdist / RefineThreshold).</font> +00216 <font class="comment">// <=> WantedLevel= log2( ProjectedSize* 2^Level / RefineThreshold).</font> +00217 <font class="comment">// <=> 2^WantedLevel= ProjectedSize* 2^Level / RefineThreshold.</font> +00218 <font class="comment">// <=> ProjectedSize= (2^WantedLevel) * RefineThreshold / (2^Level);</font> +00219 <font class="comment">// <=> ProjectedSize= (1<<WantedLevel) * RefineThreshold / (1<<Level);</font> +00220 <font class="comment">// UnOptimised formula: limit= (1<<Patch->TileLimitLevel) / (1<<Level);</font> +00221 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a><=20); +00222 <font class="keyword">static</font> <font class="keyword">const</font> uint BigValue= 1<<20; +00223 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">float</font> OOBigValue= 1.0f / BigValue; +00224 <font class="keywordflow">return</font> (1<<<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) * (OOBigValue*(BigValue>><a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>)); +00225 } +00226 +00227 +00228 <font class="comment">// ***************************************************************************</font> +<a name="l00229"></a><a class="code" href="classNL3D_1_1CTessFace.html#c0">00229</a> <font class="keywordtype">void</font> CTessFace::computeTileErrorMetric() +00230 { +00231 <font class="comment">// We must take a more correct errometric here: We must have sons face which have</font> +00232 <font class="comment">// lower projectedsize than father. This is not the case if Center of face is taken (but when not in</font> +00233 <font class="comment">// tile mode this is nearly the case). So take the min dist from 3 points.</font> +00234 <font class="keywordtype">float</font> s0= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm(); +00235 <font class="keywordtype">float</font> s1= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm(); +00236 <font class="keywordtype">float</font> s2= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm(); +00237 <font class="keywordtype">float</font> sqrdist= minof(s0, s1, s2); +00238 <font class="comment">// It is also VERY important to take the min of 3, to ensure the split in TileMode when Far1 vertex begin</font> +00239 <font class="comment">// to blend (see Patch::renderFar1() render).</font> +00240 +00241 <font class="comment">// NB: VertexProgram geomorph take sqrdist= (SplitPoint - RefineCenter).sqrnorm();</font> +00242 <font class="comment">// It's OK because geomorph will start "far" after the split.</font> +00243 +00244 <font class="keywordflow">if</font>(sqrdist< CLandscapeGlobals::TileDistFarSqr) +00245 { +00246 <font class="keywordtype">float</font> nearLimit; +00247 nearLimit= CLandscapeGlobals::RefineThreshold * <a class="code" href="classNL3D_1_1CTessFace.html#a9">computeNearLimit</a>(); +00248 <font class="comment">// If we are not so subdivided.</font> +00249 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a><nearLimit) +00250 { +00251 <font class="keywordflow">if</font>(sqrdist< CLandscapeGlobals::TileDistNearSqr) +00252 { +00253 <a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a>=nearLimit; +00254 } +00255 <font class="keywordflow">else</font> +00256 { +00257 <font class="comment">// Smooth transition to the nearLimit of tesselation.</font> +00258 <font class="keywordtype">float</font> f= ( CLandscapeGlobals::TileDistFarSqr - sqrdist ) * CLandscapeGlobals::OOTileDistDeltaSqr; +00259 <font class="comment">// sqr gives better result, by smoothing more the start of transition.</font> +00260 f= <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(f); +00261 f= <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(f); +00262 <a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a> + (nearLimit-<a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a>)*f; +00263 +00264 <font class="comment">// If threshold is big like 0.5, transition is still hard, and pops occurs. But The goal is </font> +00265 <font class="comment">// 0.005 and less, so don't bother. </font> +00266 } +00267 } +00268 } +00269 } +00270 +00271 +00272 <font class="comment">// ***************************************************************************</font> +<a name="l00273"></a><a class="code" href="classNL3D_1_1CTessFace.html#a10">00273</a> <font class="keywordtype">void</font> CTessFace::updateErrorMetric() +00274 { +00275 <font class="comment">// If already updated for this pass...</font> +00276 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z821_0">ErrorMetricDate</a>>= CLandscapeGlobals::CurrentDate) +00277 <font class="keywordflow">return</font>; +00278 +00279 CVector viewdir= <a class="code" href="classNL3D_1_1CTessFace.html#z821_2">SplitPoint</a> - CLandscapeGlobals::RefineCenter; +00280 <font class="keywordtype">float</font> sqrdist= viewdir.sqrnorm(); +00281 +00282 <font class="comment">// trivial formula.</font> +00283 <font class="comment">//-----------------</font> +00284 <a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>/ sqrdist; +00285 +00286 +00287 <font class="comment">// Hoppe97 formula: k²= a² * ("v-e"² - ((v-e).n)²) / "v-e"^4.</font> +00288 <font class="comment">//-----------------</font> +00289 <font class="comment">// Can't do it because geomorph is made on Graphic card, so the simplier is the better.</font> +00290 +00291 +00292 <font class="comment">// TileMode Impact.</font> +00293 <font class="comment">//-----------------</font> +00294 <font class="comment">/* TileMode Impact. We must split at least at TileLimitLevel, but only if the triangle</font> +00295 <font class="comment"> has a chance to enter in the TileDistFar sphere.</font> +00296 <font class="comment"> */</font> +00297 <font class="keywordflow">if</font>( <a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a><<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel && sqrdist < <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(CLandscapeGlobals::TileDistFar+<a class="code" href="classNL3D_1_1CTessFace.html#z821_4">MaxDistToSplitPoint</a>) ) +00298 { +00299 <a class="code" href="classNL3D_1_1CTessFace.html#c0">computeTileErrorMetric</a>(); +00300 } +00301 +00302 <a class="code" href="classNL3D_1_1CTessFace.html#z821_0">ErrorMetricDate</a>= CLandscapeGlobals::CurrentDate; +00303 } +00304 +00305 +00306 <font class="comment">// ***************************************************************************</font> +<a name="l00307"></a><a class="code" href="classNL3D_1_1CTessFace.html#c1">00307</a> <font class="keyword">inline</font> <font class="keywordtype">float</font> CTessFace::computeTileEMForUpdateRefine(<font class="keywordtype">float</font> distSplitPoint, <font class="keywordtype">float</font> distMinFace, <font class="keywordtype">float</font> nearLimit) +00308 { +00309 <font class="keywordtype">float</font> ema; +00310 <font class="comment">// Normal ErrorMetric simulation.</font> +00311 ema= <a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a> / <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(distSplitPoint); +00312 +00313 <font class="comment">// TileErrorMetric simulation.</font> +00314 <font class="keywordflow">if</font>(distMinFace < CLandscapeGlobals::TileDistFar) +00315 { +00316 <font class="comment">// If we are not so subdivided.</font> +00317 <font class="keywordflow">if</font>( ema<nearLimit ) +00318 { +00319 <font class="keywordflow">if</font>( distMinFace< CLandscapeGlobals::TileDistNear) +00320 { +00321 ema= nearLimit; +00322 } +00323 <font class="keywordflow">else</font> +00324 { +00325 <font class="comment">// Smooth transition to the nearLimit of tesselation.</font> +00326 <font class="keywordtype">float</font> f= ( CLandscapeGlobals::TileDistFarSqr - <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(distMinFace) ) * CLandscapeGlobals::OOTileDistDeltaSqr; +00327 <font class="comment">// sqr gives better result, by smoothing more the start of transition.</font> +00328 f= <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(f); +00329 f= <a class="code" href="namespaceNLMISC.html#a214">sqr</a>(f); +00330 ema= ema + (nearLimit-ema)*f; +00331 } +00332 } +00333 } +00334 +00335 <font class="keywordflow">return</font> ema * CLandscapeGlobals::OORefineThreshold; +00336 } +00337 +00338 +00339 <font class="comment">// ***************************************************************************</font> +<a name="l00340"></a><a class="code" href="classNL3D_1_1CTessFace.html#a16">00340</a> <font class="keywordtype">void</font> CTessFace::computeSplitPoint() +00341 { +00342 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +00343 { +00344 <font class="comment">// If it is a rectangular triangle, it will be splitted on the middle of VBase/VLeft.</font> +00345 <font class="comment">// see splitRectangular() conventions.</font> +00346 <font class="comment">// So for good geomorph compute per vertex, we must have this SplitPoint on this middle.</font> +00347 <a class="code" href="classNL3D_1_1CTessFace.html#z821_2">SplitPoint</a>= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->EndPos + <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->EndPos)/2; +00348 } +00349 <font class="keywordflow">else</font> +00350 { +00351 <font class="comment">// If it is a square triangle, it will be splitted on middle of VLeft/VRight. </font> +00352 <font class="comment">// So for good geomorph compute per vertex, we must have this SplitPoint on this middle.</font> +00353 <a class="code" href="classNL3D_1_1CTessFace.html#z821_2">SplitPoint</a>= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->EndPos + <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->EndPos)/2; +00354 } +00355 +00356 <font class="comment">// compute MaxDistToSplitPoint</font> +00357 <font class="keywordtype">float</font> d0= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->EndPos - <a class="code" href="classNL3D_1_1CTessFace.html#z821_2">SplitPoint</a>).sqrnorm(); +00358 <font class="keywordtype">float</font> d1= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->EndPos - <a class="code" href="classNL3D_1_1CTessFace.html#z821_2">SplitPoint</a>).sqrnorm(); +00359 <font class="keywordtype">float</font> d2= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->EndPos - <a class="code" href="classNL3D_1_1CTessFace.html#z821_2">SplitPoint</a>).sqrnorm(); +00360 <a class="code" href="classNL3D_1_1CTessFace.html#z821_4">MaxDistToSplitPoint</a>= max(d0, d1); +00361 <a class="code" href="classNL3D_1_1CTessFace.html#z821_4">MaxDistToSplitPoint</a>= max(<a class="code" href="classNL3D_1_1CTessFace.html#z821_4">MaxDistToSplitPoint</a>, d2); +00362 <font class="comment">// Get the distance.</font> +00363 <a class="code" href="classNL3D_1_1CTessFace.html#z821_4">MaxDistToSplitPoint</a>= sqrtf(<a class="code" href="classNL3D_1_1CTessFace.html#z821_4">MaxDistToSplitPoint</a>); +00364 } +00365 +00366 <font class="comment">// ***************************************************************************</font> +<a name="l00367"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_0">00367</a> <font class="keywordtype">void</font> CTessFace::allocTileUv(TTileUvId <a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>) +00368 { +00369 <font class="comment">// TileFaces must have been build.</font> +00370 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]); +00371 +00372 <font class="comment">// what src??</font> +00373 CTessVertex *vertexSrc; +00374 <font class="keywordflow">switch</font>(id) +00375 { +00376 <font class="keywordflow">case</font> <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>: vertexSrc= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>; <font class="keywordflow">break</font>; +00377 <font class="keywordflow">case</font> <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>: vertexSrc= <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>; <font class="keywordflow">break</font>; +00378 <font class="keywordflow">case</font> <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>: vertexSrc= <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>; <font class="keywordflow">break</font>; +00379 <font class="keywordflow">default</font>: <a class="code" href="debug_8h.html#a12">nlstop</a>; +00380 }; +00381 +00382 <font class="comment">// Do it for all possible pass</font> +00383 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00384 { +00385 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]) +00386 { +00387 CTessNearVertex *newNear= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessNearVertex(); +00388 newNear->Src= vertexSrc; +00389 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>]= newNear; +00390 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendNearVertexToRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>, newNear); +00391 +00392 <font class="comment">// May Allocate/Fill VB. Do it after allocTileUv, because UVs are not comuted yet.</font> +00393 } +00394 } +00395 } +00396 +00397 <font class="comment">// ***************************************************************************</font> +<a name="l00398"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_4">00398</a> <font class="keywordtype">void</font> CTessFace::checkCreateFillTileVB(TTileUvId <a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>) +00399 { +00400 <font class="comment">// TileFaces must have been build.</font> +00401 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]); +00402 +00403 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00404 { +00405 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]) +00406 { +00407 CTessNearVertex *vertNear; +00408 vertNear= <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>]; +00409 +00410 <font class="comment">// May Allocate/Fill VB.</font> +00411 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkCreateVertexVBNear(vertNear); +00412 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBNear(vertNear); +00413 } +00414 } +00415 } +00416 +00417 +00418 <font class="comment">// ***************************************************************************</font> +<a name="l00419"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_5">00419</a> <font class="keywordtype">void</font> CTessFace::checkFillTileVB(TTileUvId <a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>) +00420 { +00421 <font class="comment">// TileFaces must have been build.</font> +00422 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]); +00423 +00424 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00425 { +00426 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]) +00427 { +00428 CTessNearVertex *vertNear; +00429 vertNear= <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>]; +00430 +00431 <font class="comment">// May Fill VB.</font> +00432 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBNear(vertNear); +00433 } +00434 } +00435 } +00436 +00437 +00438 <font class="comment">// ***************************************************************************</font> +<a name="l00439"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_1">00439</a> <font class="keywordtype">void</font> CTessFace::deleteTileUv(TTileUvId <a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>) +00440 { +00441 <font class="comment">// TileFaces must still exist.</font> +00442 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]); +00443 +00444 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00445 { +00446 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]) +00447 { +00448 CTessNearVertex *oldNear; +00449 oldNear= <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>]; +00450 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="driver__opengl__extension__def_8h.html#a356">id</a>]=NULL; +00451 +00452 <font class="comment">// May delete this vertex from VB.</font> +00453 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkDeleteVertexVBNear(oldNear); +00454 +00455 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeNearVertexFromRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>, oldNear); +00456 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessNearVertex(oldNear); +00457 } +00458 } +00459 } +00460 <font class="comment">// ***************************************************************************</font> +<a name="l00461"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_2">00461</a> <font class="keywordtype">void</font> CTessFace::copyTileUv(TTileUvId dstId, CTessFace *srcFace, TTileUvId srcId) +00462 { +00463 <font class="comment">// TileFaces must have been build.</font> +00464 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]); +00465 +00466 <font class="comment">// Since this a ptr-copy, no need to add/remove the renderlist of near vertices.</font> +00467 +00468 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00469 { +00470 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]) +00471 { +00472 <font class="comment">// The srcface should have the same tileFaces enabled.</font> +00473 <a class="code" href="debug_8h.html#a6">nlassert</a>(srcFace->TileFaces[i]); +00474 +00475 <font class="comment">// copy from src.</font> +00476 CTessNearVertex *copyNear; +00477 copyNear= srcFace->TileFaces[i]->V[srcId]; +00478 +00479 <font class="comment">// copy to dst.</font> +00480 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[dstId]= copyNear; +00481 } +00482 } +00483 } +00484 <font class="comment">// ***************************************************************************</font> +<a name="l00485"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_3">00485</a> <font class="keywordtype">void</font> CTessFace::heritTileUv(CTessFace *baseFace) +00486 { +00487 <font class="comment">// TileFaces must have been build.</font> +00488 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]); +00489 +00490 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00491 { +00492 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]) +00493 { +00494 <font class="comment">// The baseface should have the same tileFaces enabled.</font> +00495 <a class="code" href="debug_8h.html#a6">nlassert</a>(baseFace->TileFaces[i]); +00496 <font class="comment">// VBase should be allocated.</font> +00497 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]); +00498 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]->initMiddleUv( +00499 *baseFace->TileFaces[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>], *baseFace->TileFaces[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>]); +00500 } +00501 } +00502 } +00503 +00504 +00505 <font class="comment">// ***************************************************************************</font> +<a name="l00506"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_6">00506</a> <font class="keywordtype">void</font> CTessFace::buildTileFaces() +00507 { +00508 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>); +00509 +00510 <font class="comment">// Do nothgin for lightmap pass, of course.</font> +00511 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00512 { +00513 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->Pass[i].PatchRdrPass) +00514 { +00515 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTileFace(); +00516 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]= NULL; +00517 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>]= NULL; +00518 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>]= NULL; +00519 } +00520 } +00521 } +00522 <font class="comment">// ***************************************************************************</font> +<a name="l00523"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_7">00523</a> <font class="keywordtype">void</font> CTessFace::deleteTileFaces() +00524 { +00525 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>); +00526 +00527 <font class="comment">// Do nothgin for lightmap pass, of course.</font> +00528 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00529 { +00530 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->Pass[i].PatchRdrPass) +00531 { +00532 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]); +00533 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTileFace(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]); +00534 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]= NULL; +00535 } +00536 <font class="keywordflow">else</font> +00537 { +00538 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]==NULL); +00539 } +00540 } +00541 } +00542 +00543 <font class="comment">// ***************************************************************************</font> +<a name="l00544"></a><a class="code" href="classNL3D_1_1CTessFace.html#z822_8">00544</a> <font class="keywordtype">bool</font> CTessFace::emptyTileFaces() +00545 { +00546 <font class="comment">// Do nothgin for lightmap pass, of course.</font> +00547 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00548 { +00549 <font class="comment">// Some TileFace exist??</font> +00550 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]) +00551 <font class="keywordflow">return</font> <font class="keyword">false</font>; +00552 } +00553 +00554 <font class="keywordflow">return</font> <font class="keyword">true</font>; +00555 } +00556 +00557 +00558 +00559 <font class="comment">// ***************************************************************************</font> +<a name="l00560"></a><a class="code" href="classNL3D_1_1CTessFace.html#c6">00560</a> <font class="keywordtype">void</font> CTessFace::initTileUvRGBA(sint pass, <font class="keywordtype">bool</font> <a class="code" href="driver__opengl__extension__def_8h.html#a420">alpha</a>, CParamCoord pointCoord, CParamCoord middle, CUV &uv) +00561 { +00562 <font class="comment">// Get good coordinate according to patch orientation.</font> +00563 uv.U= pointCoord.S<=middle.S? 0.0f: 1.0f; +00564 uv.V= pointCoord.T<=middle.T? 0.0f: 1.0f; +00565 +00566 <font class="comment">// Get Tile Uv info: orientation and scale.</font> +00567 uint8 orient; +00568 CVector uvScaleBias; +00569 <font class="keywordtype">bool</font> is256; +00570 uint8 uvOff; +00571 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getTileUvInfo(<a class="code" href="classNL3D_1_1CTessFace.html#z820_1">TileId</a>, pass, <a class="code" href="driver__opengl__extension__def_8h.html#a420">alpha</a>, orient, uvScaleBias, is256, uvOff); +00572 +00573 <font class="comment">// Orient the UV.</font> +00574 <font class="keywordtype">float</font> u= uv.U; +00575 <font class="keywordtype">float</font> <a class="code" href="driver__opengl__extension__def_8h.html#a368">v</a>= uv.V; +00576 <font class="comment">// Speed rotation.</font> +00577 <font class="keywordflow">switch</font>(orient) +00578 { +00579 <font class="keywordflow">case</font> 0: +00580 uv.U= u; +00581 uv.V= <a class="code" href="driver__opengl__extension__def_8h.html#a368">v</a>; +00582 <font class="keywordflow">break</font>; +00583 <font class="keywordflow">case</font> 1: +00584 uv.U= 1-<a class="code" href="driver__opengl__extension__def_8h.html#a368">v</a>; +00585 uv.V= u; +00586 <font class="keywordflow">break</font>; +00587 <font class="keywordflow">case</font> 2: +00588 uv.U= 1-u; +00589 uv.V= 1-<a class="code" href="driver__opengl__extension__def_8h.html#a368">v</a>; +00590 <font class="keywordflow">break</font>; +00591 <font class="keywordflow">case</font> 3: +00592 uv.U= <a class="code" href="driver__opengl__extension__def_8h.html#a368">v</a>; +00593 uv.V= 1-u; +00594 <font class="keywordflow">break</font>; +00595 } +00596 +00597 <font class="comment">// Do the 256x256.</font> +00598 <font class="keywordflow">if</font>(is256) +00599 { +00600 uv*= 0.5; +00601 <font class="keywordflow">if</font>(uvOff==2 || uvOff==3) +00602 uv.U+= 0.5; +00603 <font class="keywordflow">if</font>(uvOff==1 || uvOff==2) +00604 uv.V+= 0.5; +00605 } +00606 +00607 +00608 <font class="comment">// Do the HalfPixel scale bias.</font> +00609 <font class="keywordtype">float</font> hBiasXY, hBiasZ; +00610 <font class="keywordflow">if</font>(is256) +00611 { +00612 hBiasXY= CLandscapeGlobals::TilePixelBias256; +00613 hBiasZ = CLandscapeGlobals::TilePixelScale256; +00614 } +00615 <font class="keywordflow">else</font> +00616 { +00617 hBiasXY= CLandscapeGlobals::TilePixelBias128; +00618 hBiasZ = CLandscapeGlobals::TilePixelScale128; +00619 } +00620 +00621 +00622 <font class="comment">// Scale the UV.</font> +00623 uv.U*= uvScaleBias.z*hBiasZ; +00624 uv.V*= uvScaleBias.z*hBiasZ; +00625 uv.U+= uvScaleBias.x+hBiasXY; +00626 uv.V+= uvScaleBias.y+hBiasXY; +00627 } +00628 +00629 +00630 <font class="comment">// ***************************************************************************</font> +<a name="l00631"></a><a class="code" href="classNL3D_1_1CTessFace.html#c7">00631</a> <font class="keywordtype">void</font> CTessFace::initTileUvLightmap(CParamCoord pointCoord, CParamCoord middle, CUV &uv) +00632 { +00633 <font class="comment">// Get good coordinate according to patch orientation.</font> +00634 uv.U= pointCoord.S<=middle.S? 0.0f: 1.0f; +00635 uv.V= pointCoord.T<=middle.T? 0.0f: 1.0f; +00636 +00637 <font class="comment">// Get Tile Lightmap Uv info: bias and scale.</font> +00638 CVector uvScaleBias; +00639 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getTileLightMapUvInfo(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->TileS, <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->TileT, uvScaleBias); +00640 +00641 <font class="comment">// Scale the UV.</font> +00642 uv.U*= uvScaleBias.z; +00643 uv.V*= uvScaleBias.z; +00644 uv.U+= uvScaleBias.x; +00645 uv.V+= uvScaleBias.y; +00646 } +00647 +00648 +00649 <font class="comment">// ***************************************************************************</font> +<a name="l00650"></a><a class="code" href="classNL3D_1_1CTessFace.html#c8">00650</a> <font class="keywordtype">void</font> CTessFace::initTileUvDLM(CParamCoord pointCoord, CUV &uv) +00651 { +00652 <font class="comment">// get the dlm context from the patch.</font> +00653 CPatchDLMContext *dlmCtx= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->_DLMContext; +00654 <font class="comment">// mmust exist at creation of the tile.</font> +00655 <a class="code" href="debug_8h.html#a6">nlassert</a>(dlmCtx); +00656 +00657 <font class="comment">// get coord in 0..1 range, along the patch.</font> +00658 uv.U= pointCoord.getS(); +00659 uv.V= pointCoord.getT(); +00660 +00661 <font class="comment">// ScaleBias according to the context.</font> +00662 uv.U*= dlmCtx->DLMUScale; +00663 uv.V*= dlmCtx->DLMVScale; +00664 uv.U+= dlmCtx->DLMUBias; +00665 uv.V+= dlmCtx->DLMVBias; +00666 } +00667 +00668 +00669 <font class="comment">// ***************************************************************************</font> +<a name="l00670"></a><a class="code" href="classNL3D_1_1CTessFace.html#a7">00670</a> <font class="keywordtype">void</font> CTessFace::computeTileMaterial() +00671 { +00672 <font class="comment">// 0. Compute TileId.</font> +00673 <font class="comment">//-------------------</font> +00674 <font class="comment">// Square Order Patch assumption: assume that when a CTessFace become a tile, his base can ONLY be diagonal...</font> +00675 <font class="comment">/* a Patch:</font> +00676 <font class="comment"> A ________</font> +00677 <font class="comment"> |\ /|</font> +00678 <font class="comment"> | \ / |</font> +00679 <font class="comment"> C|__\B_/ |</font> +00680 <font class="comment"> | / \ |</font> +00681 <font class="comment"> | / \ |</font> +00682 <font class="comment"> |/______\|</font> +00683 <font class="comment"></font> +00684 <font class="comment"> Here, if OrderS*OrderT=2*2, ABC is a new CTessFace of a Tile, and AB is the diagonal of the tile.</font> +00685 <font class="comment"> Hence the middle of the tile is the middle of AB.</font> +00686 <font class="comment"></font> +00687 <font class="comment"> C must be created, but A and B may be created or copied from neighbor.</font> +00688 <font class="comment"> */</font> +00689 CParamCoord middle(<a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>,<a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>); +00690 sint ts= ((sint)middle.S * (sint)<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->OrderS) / 0x8000; +00691 sint tt= ((sint)middle.T * (sint)<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->OrderT) / 0x8000; +00692 <a class="code" href="classNL3D_1_1CTessFace.html#z820_1">TileId</a>= tt*<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->OrderS + ts; +00693 +00694 +00695 <font class="comment">// 1. Compute Tile Material.</font> +00696 <font class="comment">//--------------------------</font> +00697 <font class="comment">// if base neighbor is already at TileLimitLevel just ptr-copy, else create the TileMaterial...</font> +00698 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> || <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a> || <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Level<=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel); +00699 <font class="keywordtype">bool</font> copyFromBase; +00700 copyFromBase= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch==<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>); +00701 copyFromBase= copyFromBase && (<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Level==<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->TileMaterial!=NULL); +00702 <font class="comment">// NB: because of delete/recreateTileUvs(), FBase->TileMaterial may be NULL, even if face is at good TileLimitLevel.</font> +00703 <font class="keywordflow">if</font>(copyFromBase) +00704 { +00705 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->TileMaterial; +00706 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->TileId== <a class="code" href="classNL3D_1_1CTessFace.html#z820_1">TileId</a>); +00707 } +00708 <font class="keywordflow">else</font> +00709 { +00710 sint i; +00711 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTileMaterial(); +00712 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->TileS= ts; +00713 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->TileT= tt; +00714 +00715 <font class="comment">// Add this new material to the render list.</font> +00716 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendTileMaterialToRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>); +00717 +00718 <font class="comment">// First, get a lightmap for this tile. NB: important to do this after appendTileMaterialToRenderList(), </font> +00719 <font class="comment">// because use TessBlocks.</font> +00720 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getTileLightMap(ts, tt, <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->Pass[<a class="code" href="landscape__def_8h.html#a6">NL3D_TILE_PASS_LIGHTMAP</a>].PatchRdrPass); +00721 +00722 <font class="comment">// Fill pass of multi pass material.</font> +00723 <font class="keywordflow">for</font>(i=0;i<<a class="code" href="landscape__def_8h.html#a0">NL3D_MAX_TILE_PASS</a>;i++) +00724 { +00725 <font class="comment">// Get the correct render pass, according to the tile number, and the pass.</font> +00726 <font class="keywordflow">if</font>(i!=<a class="code" href="landscape__def_8h.html#a6">NL3D_TILE_PASS_LIGHTMAP</a>) +00727 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->Pass[i].PatchRdrPass= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getTileRenderPass(<a class="code" href="classNL3D_1_1CTessFace.html#z820_1">TileId</a>, i); +00728 } +00729 +00730 <font class="comment">// Fill Pass Info.</font> +00731 <font class="keywordflow">for</font>(i=0;i<<a class="code" href="landscape__def_8h.html#a0">NL3D_MAX_TILE_PASS</a>;i++) +00732 { +00733 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->Pass[i].TileMaterial= <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>; +00734 } +00735 +00736 <font class="comment">// Do not append this tile to each RenderPass, done in preRender().</font> +00737 } +00738 +00739 +00740 <font class="comment">// 2. Compute Uvs.</font> +00741 <font class="comment">//----------------</font> +00742 <font class="comment">// NB: TileMaterial is already setup. Usefull for initTileUvLightmap() and initTileUvRGBA().</font> +00743 +00744 <font class="comment">// First, must create The TileFaces, according to the TileMaterial passes.</font> +00745 <a class="code" href="classNL3D_1_1CTessFace.html#z822_6">buildTileFaces</a>(); +00746 +00747 <font class="comment">// Must allocate the Base, and insert into list.</font> +00748 <a class="code" href="classNL3D_1_1CTessFace.html#z822_0">allocTileUv</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +00749 +00750 +00751 <font class="comment">// Init LightMap UV, in RGB0 pass, UV1..</font> +00752 <a class="code" href="classNL3D_1_1CTessFace.html#c7">initTileUvLightmap</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]->PUv1); +00753 <font class="comment">// Init DLM Uv, in RGB0 pass, UV2.</font> +00754 <a class="code" href="classNL3D_1_1CTessFace.html#c8">initTileUvDLM</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]->PUv2); +00755 +00756 <font class="comment">// Init UV RGBA, for all pass (but lightmap).</font> +00757 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00758 { +00759 <a class="code" href="debug_8h.html#a6">nlassert</a>(i!=<a class="code" href="landscape__def_8h.html#a6">NL3D_TILE_PASS_LIGHTMAP</a>); +00760 <font class="comment">// If pass is valid</font> +00761 <font class="keywordflow">if</font>( <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->Pass[i].PatchRdrPass) +00762 { +00763 <font class="comment">// Face must exist.</font> +00764 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]); +00765 <font class="comment">// Compute RGB UV in UV0.</font> +00766 <a class="code" href="classNL3D_1_1CTessFace.html#c6">initTileUvRGBA</a>(i, <font class="keyword">false</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]->PUv0); +00767 <font class="comment">// If transition tile, compute alpha UV in UV1. </font> +00768 <font class="comment">// Do it also for Additive, because may have Transition</font> +00769 <font class="keywordflow">if</font>(i== <a class="code" href="landscape__def_8h.html#a3">NL3D_TILE_PASS_RGB1</a> || i==<a class="code" href="landscape__def_8h.html#a4">NL3D_TILE_PASS_RGB2</a> || i==<a class="code" href="landscape__def_8h.html#a5">NL3D_TILE_PASS_ADD</a>) +00770 <a class="code" href="classNL3D_1_1CTessFace.html#c6">initTileUvRGBA</a>(i, <font class="keyword">true</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]->PUv1); +00771 } +00772 } +00773 +00774 <font class="comment">// UVs are computed, may create and fill VB.</font> +00775 <a class="code" href="classNL3D_1_1CTessFace.html#z822_4">checkCreateFillTileVB</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +00776 +00777 +00778 <font class="comment">// if base neighbor is already at TileLimitLevel just ptr-copy, else create the left/right TileUvs...</font> +00779 <font class="keywordflow">if</font>(copyFromBase) +00780 { +00781 <font class="comment">// Just cross-copy the pointers.</font> +00782 <font class="comment">// Make Left near vertices be the Right vertices of FBase</font> +00783 <a class="code" href="classNL3D_1_1CTessFace.html#z822_2">copyTileUv</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>); +00784 <font class="comment">// Make Right near vertices be the Left vertices of FBase</font> +00785 <a class="code" href="classNL3D_1_1CTessFace.html#z822_2">copyTileUv</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>); +00786 } +00787 <font class="keywordflow">else</font> +00788 { +00789 <font class="comment">// Must allocate the left/right uv (and insert into list).</font> +00790 <a class="code" href="classNL3D_1_1CTessFace.html#z822_0">allocTileUv</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>); +00791 <a class="code" href="classNL3D_1_1CTessFace.html#z822_0">allocTileUv</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>); +00792 +00793 +00794 <font class="comment">// Init LightMap UV, in UvPass 0, UV1..</font> +00795 <a class="code" href="classNL3D_1_1CTessFace.html#c7">initTileUvLightmap</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>]->PUv1); +00796 <a class="code" href="classNL3D_1_1CTessFace.html#c7">initTileUvLightmap</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>]->PUv1); +00797 <font class="comment">// Init DLM Uv, in RGB0 pass, UV2.</font> +00798 <a class="code" href="classNL3D_1_1CTessFace.html#c8">initTileUvDLM</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>]->PUv2); +00799 <a class="code" href="classNL3D_1_1CTessFace.html#c8">initTileUvDLM</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[<a class="code" href="landscape__def_8h.html#a2">NL3D_TILE_PASS_RGB0</a>]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>]->PUv2); +00800 +00801 <font class="comment">// Init UV RGBA!</font> +00802 <font class="keywordflow">for</font>(sint i=0;i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>;i++) +00803 { +00804 <a class="code" href="debug_8h.html#a6">nlassert</a>(i!=<a class="code" href="landscape__def_8h.html#a6">NL3D_TILE_PASS_LIGHTMAP</a>); +00805 <font class="comment">// If pass is valid</font> +00806 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->Pass[i].PatchRdrPass) +00807 { +00808 <font class="comment">// Face must exist.</font> +00809 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]); +00810 <font class="comment">// Compute RGB UV in UV0.</font> +00811 <a class="code" href="classNL3D_1_1CTessFace.html#c6">initTileUvRGBA</a>(i, <font class="keyword">false</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>]->PUv0); +00812 <a class="code" href="classNL3D_1_1CTessFace.html#c6">initTileUvRGBA</a>(i, <font class="keyword">false</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>]->PUv0); +00813 <font class="comment">// If transition tile, compute alpha UV in UV1.</font> +00814 <font class="comment">// Do it also for Additive, because may have Transition</font> +00815 <font class="keywordflow">if</font>(i== <a class="code" href="landscape__def_8h.html#a3">NL3D_TILE_PASS_RGB1</a> || i==<a class="code" href="landscape__def_8h.html#a4">NL3D_TILE_PASS_RGB2</a> || i==<a class="code" href="landscape__def_8h.html#a5">NL3D_TILE_PASS_ADD</a>) +00816 { +00817 <a class="code" href="classNL3D_1_1CTessFace.html#c6">initTileUvRGBA</a>(i, <font class="keyword">true</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>]->PUv1); +00818 <a class="code" href="classNL3D_1_1CTessFace.html#c6">initTileUvRGBA</a>(i, <font class="keyword">true</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>, middle, <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>]->PUv1); +00819 } +00820 } +00821 } +00822 +00823 <font class="comment">// UVs are computed, may create and fill VB.</font> +00824 <a class="code" href="classNL3D_1_1CTessFace.html#z822_4">checkCreateFillTileVB</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>); +00825 <a class="code" href="classNL3D_1_1CTessFace.html#z822_4">checkCreateFillTileVB</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>); +00826 } +00827 +00828 } +00829 <font class="comment">// ***************************************************************************</font> +<a name="l00830"></a><a class="code" href="classNL3D_1_1CTessFace.html#a8">00830</a> <font class="keywordtype">void</font> CTessFace::releaseTileMaterial() +00831 { +00832 <font class="comment">// Hence, must release the tile. TileUvBase is differnet for each of leaves.</font> +00833 <a class="code" href="classNL3D_1_1CTessFace.html#z822_1">deleteTileUv</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +00834 +00835 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> || <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Level<=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel); +00836 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Level==<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->TileMaterial!=NULL) +00837 { +00838 <font class="comment">// Do not release Uvs, since neighbor need it...</font> +00839 <font class="comment">// But release faces.</font> +00840 <a class="code" href="classNL3D_1_1CTessFace.html#z822_7">deleteTileFaces</a>(); +00841 <font class="comment">// Do not release TileMaterial, since neighbor need it...</font> +00842 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>= NULL; +00843 } +00844 <font class="keywordflow">else</font> +00845 { +00846 <font class="comment">// release Uvs.</font> +00847 <a class="code" href="classNL3D_1_1CTessFace.html#z822_1">deleteTileUv</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>); +00848 <a class="code" href="classNL3D_1_1CTessFace.html#z822_1">deleteTileUv</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>); +00849 +00850 <font class="comment">// After, release Tile faces.</font> +00851 <a class="code" href="classNL3D_1_1CTessFace.html#z822_7">deleteTileFaces</a>(); +00852 +00853 <font class="comment">// Release the tile lightmap part. Do it before removeTileMaterialFromRenderList().</font> +00854 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->releaseTileLightMap(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->TileS, <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>->TileT); +00855 +00856 <font class="comment">// Remove this material from the render list. DO it before deletion of course :).</font> +00857 <font class="comment">// NB: TileS/TileT still valid.</font> +00858 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeTileMaterialFromRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>); +00859 +00860 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTileMaterial(<a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>); +00861 <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>= NULL; +00862 } +00863 } +00864 +00865 +00866 +00867 <font class="comment">// ***************************************************************************</font> +<a name="l00868"></a><a class="code" href="classNL3D_1_1CTessFace.html#c9">00868</a> <font class="keywordtype">void</font> CTessFace::updateNearFarVertices() +00869 { +00870 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a> && <a class="code" href="classNL3D_1_1CTessFace.html#m0">FVBase</a>); +00871 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a> && <a class="code" href="classNL3D_1_1CTessFace.html#m1">FVLeft</a>); +00872 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a> && <a class="code" href="classNL3D_1_1CTessFace.html#m2">FVRight</a>); +00873 +00874 <a class="code" href="classNL3D_1_1CTessFace.html#m0">FVBase</a>->Src= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>; +00875 <a class="code" href="classNL3D_1_1CTessFace.html#m1">FVLeft</a>->Src= <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>; +00876 <a class="code" href="classNL3D_1_1CTessFace.html#m2">FVRight</a>->Src= <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>; +00877 <a class="code" href="classNL3D_1_1CTessFace.html#m0">FVBase</a>->PCoord= <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>; +00878 <a class="code" href="classNL3D_1_1CTessFace.html#m1">FVLeft</a>->PCoord= <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>; +00879 <a class="code" href="classNL3D_1_1CTessFace.html#m2">FVRight</a>->PCoord= <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>; +00880 +00881 <font class="comment">// Update VB for far vertices (if needed)</font> +00882 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBFar(<a class="code" href="classNL3D_1_1CTessFace.html#m0">FVBase</a>); +00883 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBFar(<a class="code" href="classNL3D_1_1CTessFace.html#m1">FVLeft</a>); +00884 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBFar(<a class="code" href="classNL3D_1_1CTessFace.html#m2">FVRight</a>); +00885 +00886 <font class="comment">// Near Vertices update (Src only).</font> +00887 <font class="keywordflow">for</font>(sint i=0; i<<a class="code" href="landscape__def_8h.html#a1">NL3D_MAX_TILE_FACE</a>; i++) +00888 { +00889 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]) +00890 { +00891 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]->Src= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>; +00892 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>]->Src= <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>; +00893 <a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>]->Src= <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>; +00894 +00895 <font class="comment">// Update VB for near vertices (if needed)</font> +00896 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBNear(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>]); +00897 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBNear(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>]); +00898 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBNear(<a class="code" href="classNL3D_1_1CTessFace.html#z820_3">TileFaces</a>[i]->V[<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>]); +00899 } +00900 } +00901 +00902 } +00903 +00904 +00905 <font class="comment">// ***************************************************************************</font> +<a name="l00906"></a><a class="code" href="classNL3D_1_1CTessFace.html#c3">00906</a> <font class="keywordtype">void</font> CTessFace::splitRectangular(<font class="keywordtype">bool</font> propagateSplit) +00907 { +00908 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *f0= <font class="keyword">this</font>; +00909 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *f1= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>; +00910 <font class="comment">// Rectangular case: FBase must exist.</font> +00911 <a class="code" href="debug_8h.html#a6">nlassert</a>(f1); +00912 +00913 <font class="comment">// In rectangular case, we split at the same time this and FBase (f0 and f1).</font> +00914 +00915 +00916 <font class="comment">/*</font> +00917 <font class="comment"> Tesselation is:</font> +00918 <font class="comment"> </font> +00919 <font class="comment"> lt rt lt top rt</font> +00920 <font class="comment"> --------------------- ---------------------</font> +00921 <font class="comment"> |---- | |\ |\ |</font> +00922 <font class="comment"> | ---- f1 | | \ f1l | \ f1r |</font> +00923 <font class="comment"> | ---- | --> | \ | \ |</font> +00924 <font class="comment"> | f0 ---- | | f0r \ | f0l \ |</font> +00925 <font class="comment"> | ---| | \| \|</font> +00926 <font class="comment"> --------------------- ---------------------</font> +00927 <font class="comment"> lb rb lb bot rb</font> +00928 <font class="comment"></font> +00929 <font class="comment"> Why? For symetry and bind/split reasons: FBase->SonLeft->VBase is always the good vertex to take </font> +00930 <font class="comment"> (see vertex binding).</font> +00931 <font class="comment"> */</font> +00932 CParamCoord pclt= f1->PVLeft; +00933 CParamCoord pclb= f0->PVBase; +00934 CParamCoord pcrt= f1->PVBase; +00935 CParamCoord pcrb= f1->PVRight; +00936 CTessVertex *vlt= f1->VLeft; +00937 CTessVertex *vlb= f0->VBase; +00938 CTessVertex *vrt= f1->VBase; +00939 CTessVertex *vrb= f1->VRight; +00940 +00941 CTessFarVertex *farvlt= f1->FVLeft; +00942 CTessFarVertex *farvlb= f0->FVBase; +00943 CTessFarVertex *farvrt= f1->FVBase; +00944 CTessFarVertex *farvrb= f1->FVRight; +00945 +00946 +00947 <font class="comment">// 1. create new vertices.</font> +00948 <font class="comment">//------------------------</font> +00949 +00950 <font class="comment">// Create splitted vertices.</font> +00951 CParamCoord pctop(f1->PVBase, f1->PVLeft); +00952 CParamCoord pcbot(f0->PVBase, f0->PVLeft); +00953 CTessVertex *vtop= NULL; +00954 CTessVertex *vbot= NULL; +00955 <font class="comment">// Compute top.</font> +00956 <font class="keywordflow">if</font>(f1->FLeft==NULL || f1->FLeft->isLeaf()) +00957 { +00958 <font class="comment">// The base neighbor is a leaf or NULL. So must create the new vertex.</font> +00959 vtop= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessVertex(); +00960 +00961 <font class="comment">// Compute pos.</font> +00962 vtop->StartPos= (f1->VLeft->EndPos + f1->VBase->EndPos)/2; +00963 vtop->EndPos= f1->Patch->computeVertex(pctop.getS(), pctop.getT()); +00964 <font class="comment">// Init Pos= InitialPos. Important in the case of enforced split.</font> +00965 vtop->Pos= vtop->StartPos; +00966 +00967 <font class="comment">// For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.</font> +00968 vtop->MaxFaceSize= f1->Size; +00969 vtop->MaxNearLimit= f1->computeNearLimit(); +00970 } +00971 <font class="keywordflow">else</font> +00972 { +00973 <font class="comment">// Else, get from neighbor.</font> +00974 <font class="comment">// NB: since *FLeft is not a leaf, FBase->SonLeft!=NULL...</font> +00975 <font class="comment">// NB: this work with both rectangular and square triangles.</font> +00976 vtop= f1->FLeft->SonLeft->VBase; +00977 +00978 <font class="comment">// For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.</font> +00979 vtop->MaxFaceSize= max( vtop->MaxFaceSize, f1->Size); +00980 vtop->MaxNearLimit= max( vtop->MaxNearLimit, f1->computeNearLimit()); +00981 } +00982 <font class="comment">// Compute bot.</font> +00983 <font class="keywordflow">if</font>(f0->FLeft==NULL || f0->FLeft->isLeaf()) +00984 { +00985 <font class="comment">// The base neighbor is a leaf or NULL. So must create the new vertex.</font> +00986 vbot= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessVertex(); +00987 +00988 <font class="comment">// Compute pos.</font> +00989 vbot->StartPos= (f0->VLeft->EndPos + f0->VBase->EndPos)/2; +00990 vbot->EndPos= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->computeVertex(pcbot.getS(), pcbot.getT()); +00991 <font class="comment">// Init Pos= InitialPos. Important in the case of enforced split.</font> +00992 vbot->Pos= vbot->StartPos; +00993 +00994 <font class="comment">// For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.</font> +00995 vbot->MaxFaceSize= f0->Size; +00996 vbot->MaxNearLimit= f0->computeNearLimit(); +00997 } +00998 <font class="keywordflow">else</font> +00999 { +01000 <font class="comment">// Else, get from neighbor.</font> +01001 <font class="comment">// NB: since *FLeft is not a leaf, FBase->SonLeft!=NULL...</font> +01002 <font class="comment">// NB: this work with both rectangular and square triangles.</font> +01003 vbot= f0->FLeft->SonLeft->VBase; +01004 +01005 <font class="comment">// For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.</font> +01006 vbot->MaxFaceSize= max( vbot->MaxFaceSize, f0->Size); +01007 vbot->MaxNearLimit= max( vbot->MaxNearLimit, f0->computeNearLimit()); +01008 } +01009 +01010 <font class="comment">// In all case, must create new FarVertices, since rect split occurs on border!!</font> +01011 CTessFarVertex *farvtop= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFarVertex(); +01012 CTessFarVertex *farvbot= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFarVertex(); +01013 farvtop->Src= vtop; +01014 farvbot->Src= vbot; +01015 farvtop->PCoord= pctop; +01016 farvbot->PCoord= pcbot; +01017 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFarVertexToRenderList(farvtop); +01018 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFarVertexToRenderList(farvbot); +01019 <font class="comment">// May Allocate/Fill VB.</font> +01020 <font class="comment">// NB: vtop / vbot are well computed and ready for the fill in VB.</font> +01021 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkCreateVertexVBFar(farvtop); +01022 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBFar(farvtop); +01023 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkCreateVertexVBFar(farvbot); +01024 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBFar(farvbot); +01025 +01026 <font class="comment">// For VertexProgram only, must refill the Far vertex of neighbor(s), </font> +01027 <font class="comment">// because MaxFaceSize, and MaxNearLimit may have change.</font> +01028 <font class="keywordflow">if</font>( CLandscapeGlobals::VertexProgramEnabled ) +01029 { +01030 <font class="comment">// f0</font> +01031 <font class="keywordflow">if</font>( ! (f0->FLeft==NULL || f0->FLeft->isLeaf()) ) +01032 f0->FLeft->Patch->checkFillVertexVBFar(f0->FLeft->SonLeft->FVBase); +01033 <font class="comment">// f1</font> +01034 <font class="keywordflow">if</font>( ! (f1->FLeft==NULL || f1->FLeft->isLeaf()) ) +01035 f1->FLeft->Patch->checkFillVertexVBFar(f1->FLeft->SonLeft->FVBase); +01036 } +01037 +01038 +01039 <font class="comment">// 2. Create sons, and update links.</font> +01040 <font class="comment">//----------------------------------</font> +01041 +01042 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *f0l, *f0r; +01043 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *f1l, *f1r; +01044 +01045 <font class="comment">// create and bind Sons.</font> +01046 f0l= f0->SonLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFace(); +01047 f0r= f0->SonRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFace(); +01048 f1l= f1->SonLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFace(); +01049 f1r= f1->SonRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFace(); +01050 +01051 <font class="comment">// subdivision left.</font> +01052 f0l->Patch= f0->Patch; +01053 f0l->Father= f0; +01054 f0l->Level= f0->Level+1; +01055 f0l->Size= f0->Size*0.5f; +01056 <font class="comment">// subdivision right.</font> +01057 f0r->Patch= f0->Patch; +01058 f0r->Father= f0; +01059 f0r->Level= f0->Level+1; +01060 f0r->Size= f0->Size*0.5f; +01061 <font class="comment">// subdivision left.</font> +01062 f1l->Patch= f1->Patch; +01063 f1l->Father= f1; +01064 f1l->Level= f1->Level+1; +01065 f1l->Size= f1->Size*0.5f; +01066 <font class="comment">// subdivision right.</font> +01067 f1r->Patch= f1->Patch; +01068 f1r->Father= f1; +01069 f1r->Level= f1->Level+1; +01070 f1r->Size= f1->Size*0.5f; +01071 +01072 <font class="comment">// Patch coordinates.</font> +01073 f0r->PVRight= pclt; +01074 f0r->PVBase= pclb; +01075 f0r->PVLeft= pcbot; +01076 f1l->PVBase= pctop; +01077 f1l->PVLeft= f0r->PVRight; +01078 f1l->PVRight= f0r->PVLeft; +01079 +01080 f0l->PVRight= pctop; +01081 f0l->PVBase= pcbot; +01082 f0l->PVLeft= pcrb; +01083 f1r->PVBase= pcrt; +01084 f1r->PVLeft= f0l->PVRight; +01085 f1r->PVRight= f0l->PVLeft; +01086 +01087 <font class="comment">// link existing vertex.</font> +01088 f0r->VRight= vlt; +01089 f0r->VBase= vlb; +01090 f0r->VLeft= vbot; +01091 f1l->VBase= vtop; +01092 f1l->VLeft= f0r->VRight; +01093 f1l->VRight= f0r->VLeft; +01094 +01095 f0l->VRight= vtop; +01096 f0l->VBase= vbot; +01097 f0l->VLeft= vrb; +01098 f1r->VBase= vrt; +01099 f1r->VLeft= f0l->VRight; +01100 f1r->VRight= f0l->VLeft; +01101 +01102 <font class="comment">// link Far vertices.</font> +01103 f0r->FVRight= farvlt; +01104 f0r->FVBase= farvlb; +01105 f0r->FVLeft= farvbot; +01106 f1l->FVBase= farvtop; +01107 f1l->FVLeft= f0r->FVRight; +01108 f1l->FVRight= f0r->FVLeft; +01109 +01110 f0l->FVRight= farvtop; +01111 f0l->FVBase= farvbot; +01112 f0l->FVLeft= farvrb; +01113 f1r->FVBase= farvrt; +01114 f1r->FVLeft= f0l->FVRight; +01115 f1r->FVRight= f0l->FVLeft; +01116 +01117 <font class="comment">// link neigbhor faces.</font> +01118 f0r->FBase= f1l; +01119 f1l->FBase= f0r; +01120 f0l->FBase= f1r; +01121 f1r->FBase= f0l; +01122 f1l->FRight= f0l; +01123 f0l->FRight= f1l; +01124 f0r->FRight= f0->FRight; +01125 <font class="keywordflow">if</font>(f0->FRight) +01126 f0->FRight->changeNeighbor(f0, f0r); +01127 f1r->FRight= f1->FRight; +01128 <font class="keywordflow">if</font>(f1->FRight) +01129 f1->FRight->changeNeighbor(f1, f1r); +01130 <font class="comment">// 4 links (all FLeft sons ) are stil invalid here.</font> +01131 f0l->FLeft= NULL; +01132 f0r->FLeft= NULL; +01133 f1l->FLeft= NULL; +01134 f1r->FLeft= NULL; +01135 +01136 <font class="comment">// Neigbors pointers of undetermined splitted face are not changed. Must Doesn't change this. </font> +01137 <font class="comment">// Used and Updated in section 5. ...</font> +01138 +01139 +01140 <font class="comment">// 3. Update Tile infos.</font> +01141 <font class="comment">//----------------------</font> +01142 <font class="comment">// There is no update tileinfo with rectangular patch, since tiles are always squares. (TileLimitLevel>SquareLimitLevel).</font> +01143 +01144 <font class="comment">// NB: but must test update of tile info for neighboring, ie 2 faces around the splits.</font> +01145 <font class="comment">// For Vertex program only</font> +01146 <font class="keywordflow">if</font>( CLandscapeGlobals::VertexProgramEnabled ) +01147 { +01148 <font class="comment">// if neighbor face splitted, and if 2 different patchs, we must update the Tile vertices</font> +01149 <font class="comment">// because MaxFaceSize and MaxNearLimit may have changed.</font> +01150 <font class="keywordflow">if</font>( f0->FLeft!=NULL && !f0->FLeft->isLeaf() && f0->FLeft->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a> ) +01151 { +01152 <font class="comment">// If neighbors sons at tile level, must update their Tile vertices.</font> +01153 <font class="keywordflow">if</font>( f0->FLeft->SonLeft->Level >= f0->FLeft->Patch->TileLimitLevel ) +01154 { +01155 f0->FLeft->SonLeft->checkFillTileVB(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +01156 f0->FLeft->SonRight->checkFillTileVB(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +01157 } +01158 } +01159 <font class="comment">// idem for f1.</font> +01160 <font class="keywordflow">if</font>( f1->FLeft!=NULL && !f1->FLeft->isLeaf() && f1->FLeft->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a> ) +01161 { +01162 <font class="comment">// If neighbors sons at tile level, must update their Tile vertices.</font> +01163 <font class="keywordflow">if</font>( f1->FLeft->SonLeft->Level >= f1->FLeft->Patch->TileLimitLevel ) +01164 { +01165 f1->FLeft->SonLeft->checkFillTileVB(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +01166 f1->FLeft->SonRight->checkFillTileVB(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +01167 } +01168 } +01169 } +01170 +01171 +01172 <font class="comment">// 4. Compute centers.</font> +01173 <font class="comment">//--------------------</font> +01174 f0r->computeSplitPoint(); +01175 f0l->computeSplitPoint(); +01176 f1r->computeSplitPoint(); +01177 f1l->computeSplitPoint(); +01178 +01179 +01180 <font class="comment">// 5. Propagate, or link sons of base.</font> +01181 <font class="comment">//------------------------------------</font> +01182 <font class="keywordflow">for</font>(sint i=0;i<2;i++) +01183 { +01184 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *f, *fl, *fr; +01185 <font class="comment">// TOP face.</font> +01186 <font class="keywordflow">if</font>(i==0) +01187 { +01188 f= f1; +01189 fl= f1l; +01190 fr= f1r; +01191 } +01192 <font class="comment">// then BOT face.</font> +01193 <font class="keywordflow">else</font> +01194 { +01195 f= f0; +01196 fl= f0l; +01197 fr= f0r; +01198 } +01199 +01200 <font class="comment">// If current face and FBase has sons, just links.</font> +01201 <font class="keywordflow">if</font>(f->FLeft==NULL) +01202 { +01203 <font class="comment">// Just update sons neighbors.</font> +01204 fl->FLeft= NULL; +01205 fr->FLeft= NULL; +01206 } +01207 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(!f->FLeft->isLeaf()) +01208 { +01209 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *toLeft, *toRight; +01210 toLeft= f->FLeft->SonLeft; +01211 toRight= f->FLeft->SonRight; +01212 <font class="comment">// Cross connection of sons.</font> +01213 <font class="keywordflow">if</font>( !f->FLeft->isRectangular() ) +01214 { +01215 <font class="comment">// Case neigbhor is square.</font> +01216 fl->FLeft= toLeft; +01217 fr->FLeft= toRight; +01218 toLeft->FRight= fl; +01219 toRight->FLeft= fr; +01220 } +01221 <font class="keywordflow">else</font> +01222 { +01223 <font class="comment">// Case neigbhor is rectangle.</font> +01224 fl->FLeft= toRight; +01225 fr->FLeft= toLeft; +01226 toLeft->FLeft= fr; +01227 toRight->FLeft= fl; +01228 } +01229 } +01230 <font class="keywordflow">else</font> <font class="keywordflow">if</font> (propagateSplit) +01231 { +01232 <font class="comment">// Warning: at each iteration, the pointer of FLeft may change (because of split() which can change the neighbor </font> +01233 <font class="comment">// and so f).</font> +01234 <font class="keywordflow">while</font>(f->FLeft->isLeaf()) +01235 f->FLeft->split(); +01236 +01237 <font class="comment">// There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.</font> +01238 <font class="comment">// And problems may arise because this face hasn't yet good connectivity (especially for rectangles!! :) ).</font> +01239 <a class="code" href="debug_8h.html#a6">nlassert</a>(fl->isLeaf() && fr->isLeaf()); +01240 } +01241 } +01242 +01243 +01244 <font class="comment">// 6. Must remove father from rdr list, and insert sons.</font> +01245 <font class="comment">//------------------------------------------------------</font> +01246 <font class="comment">// UGLY REFCOUNT SIDE EFFECT: do the append first.</font> +01247 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToRenderList(f0l); +01248 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToRenderList(f0r); +01249 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToRenderList(f1l); +01250 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToRenderList(f1r); +01251 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFaceFromRenderList(f0); +01252 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFaceFromRenderList(f1); +01253 +01254 +01255 <font class="comment">// 7. Update priority list.</font> +01256 <font class="comment">//------------------------------------------------------</font> +01257 <font class="comment">// Since we are freshly splitted, unlink from any list, and link to the MergePriorityList, because must look </font> +01258 <font class="comment">// now when should merge.</font> +01259 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_MergePriorityList.insert(0, 0, f0); +01260 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_MergePriorityList.insert(0, 0, f1); +01261 +01262 <font class="comment">// Since we are split, no need to test father for merge, because it cannot!</font> +01263 <font class="keywordflow">if</font>(f0->Father) +01264 { +01265 <font class="comment">// remove father from any priority list.</font> +01266 f0->Father->unlinkInPList(); +01267 } +01268 <font class="keywordflow">if</font>(f1->Father) +01269 { +01270 <font class="comment">// remove father from any priority list.</font> +01271 f1->Father->unlinkInPList(); +01272 } +01273 +01274 } +01275 +01276 +01277 <font class="comment">// ***************************************************************************</font> +<a name="l01278"></a><a class="code" href="classNL3D_1_1CTessFace.html#a11">01278</a> <font class="keywordtype">void</font> CTessFace::split(<font class="keywordtype">bool</font> propagateSplit) +01279 { +01280 +01281 <font class="comment">// 0. Some easy ending.</font> +01282 <font class="comment">//---------------------</font> +01283 <font class="comment">// Already splitted??</font> +01284 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +01285 <font class="keywordflow">return</font>; +01286 <font class="comment">// Don't do this!!!</font> +01287 <font class="comment">//if(Level>=LS_MAXLEVEL)</font> +01288 <font class="comment">// return;</font> +01289 <font class="comment">// since split() may reach LS_MAXLEVEL, but enforce splits which outpass this stage!!</font> +01290 +01291 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a80">ProfNSplits</a>, 1); +01292 +01293 +01294 <font class="comment">// Special Rectangular case.</font> +01295 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +01296 { +01297 <a class="code" href="classNL3D_1_1CTessFace.html#c3">splitRectangular</a>(propagateSplit); +01298 <font class="keywordflow">return</font>; +01299 } +01300 +01301 <font class="comment">// 1. Create sons, and update links.</font> +01302 <font class="comment">//----------------------------------</font> +01303 +01304 <font class="comment">// create and bind Sons.</font> +01305 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFace(); +01306 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFace(); +01307 +01308 <font class="comment">// subdivision left.</font> +01309 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Patch= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>; +01310 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Father= <font class="keyword">this</font>; +01311 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level= <a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>+1; +01312 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Size= <a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>*0.5f; +01313 <font class="comment">// subdivision right.</font> +01314 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->Patch= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>; +01315 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->Father= <font class="keyword">this</font>; +01316 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->Level= <a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>+1; +01317 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->Size= <a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>*0.5f; +01318 +01319 +01320 <font class="comment">// link Left Son.</font> +01321 <font class="comment">// link neighbor face.</font> +01322 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>; +01323 <font class="keywordflow">if</font>(FLeft) <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->changeNeighbor(<font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>); +01324 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>; +01325 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FRight= NULL; <font class="comment">// Temporary. updated later.</font> +01326 <font class="comment">// link neighbor vertex.</font> +01327 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>; +01328 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>; +01329 <font class="comment">// link neighbor Far vertex.</font> +01330 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVLeft= <a class="code" href="classNL3D_1_1CTessFace.html#m0">FVBase</a>; +01331 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVRight= <a class="code" href="classNL3D_1_1CTessFace.html#m1">FVLeft</a>; +01332 <font class="comment">// Patch coordinates.</font> +01333 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase= CParamCoord(<a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>); +01334 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>; +01335 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>; +01336 +01337 <font class="comment">// linkRight Son.</font> +01338 <font class="comment">// link neighbor face.</font> +01339 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>; +01340 <font class="keywordflow">if</font>(FRight) <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>->changeNeighbor(<font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>); +01341 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FLeft= NULL; <font class="comment">// Temporary. updated later.</font> +01342 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>; +01343 <font class="comment">// link neighbor vertex.</font> +01344 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>; +01345 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>; +01346 <font class="comment">// link neighbor Far vertex.</font> +01347 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FVLeft= <a class="code" href="classNL3D_1_1CTessFace.html#m2">FVRight</a>; +01348 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FVRight= <a class="code" href="classNL3D_1_1CTessFace.html#m0">FVBase</a>; +01349 <font class="comment">// Patch coordinates.</font> +01350 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->PVBase= CParamCoord(<a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>); +01351 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->PVLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>; +01352 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->PVRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>; +01353 +01354 +01355 <font class="comment">// FBase->FBase==this. Must Doesn't change this. Used and Updated in section 5. ...</font> +01356 +01357 +01358 <font class="comment">// 2. Update/Create Vertex infos.</font> +01359 <font class="comment">//-------------------------------</font> +01360 +01361 <font class="comment">// Must create/link *->VBase.</font> +01362 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>==NULL || <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()) +01363 { +01364 <font class="comment">// The base neighbor is a leaf or NULL. So must create the new vertex.</font> +01365 CTessVertex *newVertex= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessVertex(); +01366 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VBase= newVertex; +01367 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase= newVertex; +01368 +01369 <font class="comment">// Compute pos.</font> +01370 newVertex->StartPos= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->EndPos + <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->EndPos)/2; +01371 newVertex->EndPos= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->computeVertex(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase.getT()); +01372 +01373 <font class="comment">// Init Pos= InitialPos. Important in the case of enforced split.</font> +01374 newVertex->Pos= newVertex->StartPos; +01375 +01376 <font class="comment">// For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.</font> +01377 newVertex->MaxFaceSize= <a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>; +01378 newVertex->MaxNearLimit= <a class="code" href="classNL3D_1_1CTessFace.html#a9">computeNearLimit</a>(); +01379 } +01380 <font class="keywordflow">else</font> +01381 { +01382 <font class="comment">// Else, get from neighbor.</font> +01383 <font class="comment">// NB: since *FBase is not a leaf, FBase->SonLeft!=NULL...</font> +01384 <font class="comment">// NB: this work with both rectangular and square triangles (see splitRectangular()).</font> +01385 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->VBase; +01386 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->VBase; +01387 +01388 <font class="comment">// For geomorph (VertexProgram or soft), compute MaxFaceSize and MaxNearLimit.</font> +01389 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->MaxFaceSize= max( <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->MaxFaceSize, <a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>); +01390 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->MaxNearLimit= max( <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->MaxNearLimit, <a class="code" href="classNL3D_1_1CTessFace.html#a9">computeNearLimit</a>()); +01391 } +01392 +01393 +01394 <font class="comment">// Must create/link *->FVBase.</font> +01395 <font class="comment">// HERE, we must create a FarVertex too if the neighbor is not of the same patch as me.</font> +01396 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>==NULL || <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf() || <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>) +01397 { +01398 <font class="comment">// The base neighbor is a leaf or NULL. So must create the new far vertex.</font> +01399 CTessFarVertex *newFar= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessFarVertex(); +01400 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FVBase= newFar; +01401 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVBase= newFar; +01402 +01403 <font class="comment">// Compute.</font> +01404 newFar->Src= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase; +01405 newFar->PCoord= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase; +01406 +01407 <font class="comment">// Append.</font> +01408 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFarVertexToRenderList(newFar); +01409 +01410 <font class="comment">// May Allocate/Fill VB.</font> +01411 <font class="comment">// NB: SonLeft->VBase->Pos is well computed and ready for the fill in VB.</font> +01412 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkCreateVertexVBFar(newFar); +01413 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkFillVertexVBFar(newFar); +01414 +01415 <font class="comment">// For VertexProgram only, must refill the Far vertex of neighbor, </font> +01416 <font class="comment">// because MaxFaceSize, and MaxNearLimit may have change.</font> +01417 <font class="keywordflow">if</font>( CLandscapeGlobals::VertexProgramEnabled && ! (<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>==NULL || <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()) ) +01418 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch->checkFillVertexVBFar(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->FVBase); +01419 } +01420 <font class="keywordflow">else</font> +01421 { +01422 <font class="comment">// Else, get from neighbor.</font> +01423 <font class="comment">// NB: since *FBase is not a leaf, FBase->SonLeft!=NULL...</font> +01424 <font class="comment">// NB: this work with both rectangular and square triangles (see splitRectangular()).</font> +01425 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FVBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->FVBase; +01426 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->FVBase; +01427 +01428 <font class="comment">// NB For VertexProgram only: no need to refill the Far vertex of neighbor, because neighbor is of same Patch</font> +01429 <font class="comment">// So MaxNearLimit and MaxFaceSize should be the same.</font> +01430 } +01431 +01432 +01433 <font class="comment">// 3. Update Tile infos.</font> +01434 <font class="comment">//----------------------</font> +01435 <font class="comment">// NB: must do it before appendFaceToRenderList().</font> +01436 <font class="comment">// NB: must do it after compute of SonLeft->VBase->Pos for good filling in VBuffer.</font> +01437 <font class="comment">// There is no problem with rectangular patch, since tiles are always squares.</font> +01438 <font class="comment">// If new tile ....</font> +01439 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level==<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +01440 { +01441 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->computeTileMaterial(); +01442 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->computeTileMaterial(); +01443 } +01444 <font class="comment">// else Tile herit.</font> +01445 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level > <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +01446 { +01447 <a class="code" href="classNL3D_1_1CTessFace.html#c5">heritTileMaterial</a>(); +01448 } +01449 +01450 <font class="comment">// For Vertex program only</font> +01451 <font class="keywordflow">if</font>( CLandscapeGlobals::VertexProgramEnabled ) +01452 { +01453 <font class="comment">// if neighbor face splitted, and if 2 different patchs, we must update the Tile vertices</font> +01454 <font class="comment">// because MaxFaceSize and MaxNearLimit may have changed.</font> +01455 <font class="keywordflow">if</font>( <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>!=NULL && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf() && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a> ) +01456 { +01457 <font class="comment">// If neighbors sons at tile level, must update their Tile vertices.</font> +01458 <font class="keywordflow">if</font>( <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->Level >= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch->TileLimitLevel ) +01459 { +01460 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->checkFillTileVB(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +01461 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonRight->checkFillTileVB(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +01462 } +01463 } +01464 } +01465 +01466 +01467 <font class="comment">// 4. Compute centers.</font> +01468 <font class="comment">//--------------------</font> +01469 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->computeSplitPoint(); +01470 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->computeSplitPoint(); +01471 +01472 +01473 <font class="comment">// 5. Propagate, or link sons of base.</font> +01474 <font class="comment">//------------------------------------</font> +01475 <font class="comment">// If current face and FBase has sons, just links.</font> +01476 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>==NULL) +01477 { +01478 <font class="comment">// Just update sons neighbors.</font> +01479 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FRight= NULL; +01480 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FLeft= NULL; +01481 } +01482 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()) +01483 { +01484 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *toLeft, *toRight; +01485 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *fl, *fr; +01486 fl= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>; +01487 fr= <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>; +01488 toLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft; +01489 toRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonRight; +01490 <font class="comment">// Cross connection of sons.</font> +01491 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isRectangular()) +01492 { +01493 <font class="comment">// Case neigbhor is square.</font> +01494 fl->FRight= toRight; +01495 fr->FLeft= toLeft; +01496 toLeft->FRight= fr; +01497 toRight->FLeft= fl; +01498 } +01499 <font class="keywordflow">else</font> +01500 { +01501 <font class="comment">// Case neigbhor is rectangular.</font> +01502 fl->FRight= toLeft; +01503 fr->FLeft= toRight; +01504 toLeft->FLeft= fl; +01505 toRight->FLeft= fr; +01506 } +01507 } +01508 <font class="keywordflow">else</font> <font class="keywordflow">if</font> (propagateSplit) +01509 { +01510 <font class="comment">// Warning: at each iteration, the pointer of FBase may change (because of split() which can change the neighbor </font> +01511 <font class="comment">// and so "this").</font> +01512 <font class="keywordflow">while</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()) +01513 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->split(); +01514 +01515 <font class="comment">// There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.</font> +01516 <font class="comment">// And problems may arise because this face hasn't yet good connectivity.</font> +01517 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->isLeaf() && <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->isLeaf()); +01518 } +01519 +01520 +01521 <font class="comment">// 6. Must remove father from rdr list, and insert sons.</font> +01522 <font class="comment">//------------------------------------------------------</font> +01523 <font class="comment">// UGLY REFCOUNT SIDE EFFECT: do the append first.</font> +01524 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>); +01525 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>); +01526 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFaceFromRenderList(<font class="keyword">this</font>); +01527 +01528 +01529 <font class="comment">// 7. Update priority list.</font> +01530 <font class="comment">//------------------------------------------------------</font> +01531 <font class="comment">// Since we are freshly splitted, unlink from any list, and link to the MergePriorityList, because must look </font> +01532 <font class="comment">// now when should merge.</font> +01533 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_MergePriorityList.insert(0, 0, <font class="keyword">this</font>); +01534 +01535 <font class="comment">// Since we are split, no need to test father for merge, because it cannot!</font> +01536 <font class="keywordflow">if</font>(Father) +01537 { +01538 <font class="comment">// remove father from any priority list.</font> +01539 <a class="code" href="classNL3D_1_1CTessFace.html#z819_7">Father</a>->unlinkInPList(); +01540 } +01541 } +01542 +01543 <font class="comment">// ***************************************************************************</font> +<a name="l01544"></a><a class="code" href="classNL3D_1_1CTessFace.html#c2">01544</a> <font class="keywordtype">bool</font> CTessFace::canMerge(<font class="keywordtype">bool</font> testEm) +01545 { +01546 <font class="keywordflow">if</font>(<font class="keyword">this</font>== &<a class="code" href="classNL3D_1_1CTessFace.html#r0">CantMergeFace</a>) +01547 <font class="keywordflow">return</font> <font class="keyword">false</font>; +01548 +01549 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +01550 +01551 <font class="comment">// Test diamond config (sons must be leaves).</font> +01552 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->isLeaf()) +01553 <font class="keywordflow">return</font> <font class="keyword">false</font>; +01554 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->isLeaf()) +01555 <font class="keywordflow">return</font> <font class="keyword">false</font>; +01556 <font class="comment">// If Errormetric must be considered for this test.</font> +01557 <font class="keywordflow">if</font>(testEm) +01558 { +01559 <a class="code" href="classNL3D_1_1CTessFace.html#a10">updateErrorMetric</a>(); +01560 <font class="keywordtype">float</font> ps2= <a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a>; +01561 ps2*= CLandscapeGlobals::OORefineThreshold; +01562 <font class="keywordflow">if</font>(ps2>=1.0f) +01563 <font class="keywordflow">return</font> <font class="keyword">false</font>; +01564 } +01565 +01566 <font class="comment">// Then test neighbors.</font> +01567 <a class="code" href="classNL3D_1_1CTessFace.html#z819_14">RecursMarkCanMerge</a>= <font class="keyword">true</font>; +01568 <font class="keywordtype">bool</font> ok= <font class="keyword">true</font>; +01569 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +01570 { +01571 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->RecursMarkCanMerge) +01572 { +01573 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->canMerge(testEm)) +01574 ok= <font class="keyword">false</font>; +01575 } +01576 } +01577 <font class="keywordflow">else</font> +01578 { +01579 <font class="comment">// Rectangular case. May have a longer propagation...</font> +01580 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->RecursMarkCanMerge) +01581 { +01582 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->canMerge(testEm)) +01583 ok= <font class="keyword">false</font>; +01584 } +01585 <font class="keywordflow">if</font>(ok && <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a> && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->RecursMarkCanMerge) +01586 { +01587 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->canMerge(testEm)) +01588 ok= <font class="keyword">false</font>; +01589 } +01590 } +01591 <font class="comment">// Must not return false in preceding tests, because must set RecursMarkCanMerge to false.</font> +01592 <a class="code" href="classNL3D_1_1CTessFace.html#z819_14">RecursMarkCanMerge</a>= <font class="keyword">false</font>; +01593 +01594 <font class="keywordflow">return</font> ok; +01595 } +01596 +01597 +01598 <font class="comment">// ***************************************************************************</font> +<a name="l01599"></a><a class="code" href="classNL3D_1_1CTessFace.html#c4">01599</a> <font class="keywordtype">void</font> CTessFace::doMerge() +01600 { +01601 <font class="comment">// Assume that canMerge() return true.</font> +01602 <font class="comment">// And Assume that !isLeaf().</font> +01603 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +01604 +01605 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +01606 { +01607 <font class="comment">// 1. Let's merge vertex.</font> +01608 <font class="comment">//-----------------------</font> +01609 <font class="comment">// Delete vertex, only if not already done by the neighbor (ie neighbor not already merged to a leaf).</font> +01610 <font class="comment">// NB: this work even if neigbor is rectnagular.</font> +01611 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> || !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()) +01612 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessVertex(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase); +01613 +01614 <font class="comment">// Delete Far Vertex. Idem, but test too if != patch...</font> +01615 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> || !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf() || <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>) +01616 { +01617 <font class="comment">// May delete this vertex from VB.</font> +01618 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkDeleteVertexVBFar(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVBase); +01619 +01620 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFarVertexFromRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVBase); +01621 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessFarVertex(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVBase); +01622 } +01623 +01624 +01625 <font class="comment">// 2. Must remove sons from rdr list, and insert father.</font> +01626 <font class="comment">//------------------------------------------------------</font> +01627 <font class="comment">// Must do it BEFORE the TileFaces are released.</font> +01628 <font class="comment">// UGLY REFCOUNT SIDE EFFECT: do the append first.</font> +01629 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToRenderList(<font class="keyword">this</font>); +01630 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFaceFromRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>); +01631 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFaceFromRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>); +01632 +01633 +01634 <font class="comment">// 3. Let's merge Uv.</font> +01635 <font class="comment">//-------------------</font> +01636 <font class="comment">// Delete Uv.</font> +01637 <font class="comment">// Must do it for this and FBase separately, since they may not have same tile level (if != patch).</font> +01638 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level== <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +01639 { +01640 <font class="comment">// Square patch assumption: the sons are not of the same TileId/Patch.</font> +01641 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#f0">sameTile</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>)); +01642 <font class="comment">// release tiles: NearVertices, TileFaces, and TileMaterial.</font> +01643 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->releaseTileMaterial(); +01644 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->releaseTileMaterial(); +01645 } +01646 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level > <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +01647 { +01648 <font class="comment">// Delete Uv, only if not already done by the neighbor (ie neighbor not already merged to a leaf).</font> +01649 <font class="comment">// But Always delete if neighbor exist and has not same tile as me.</font> +01650 <font class="comment">// NB: this work with rectangular neigbor patch, since sameTile() will return false if different patch.</font> +01651 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> || !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf() || !<a class="code" href="classNL3D_1_1CTessFace.html#f0">sameTile</a>(<font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>)) +01652 { +01653 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->deleteTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +01654 } +01655 <font class="comment">// In all case, must delete the tilefaces of those face.</font> +01656 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->deleteTileFaces(); +01657 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->deleteTileFaces(); +01658 } +01659 +01660 +01661 <font class="comment">// 4. Let's merge Face.</font> +01662 <font class="comment">//-------------------</font> +01663 <font class="comment">// Change father 's neighbor pointers.</font> +01664 <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FBase; +01665 <font class="keywordflow">if</font>(FLeft) <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->changeNeighbor(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>, <font class="keyword">this</font>); +01666 <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FBase; +01667 <font class="keywordflow">if</font>(FRight) <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>->changeNeighbor(<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>, <font class="keyword">this</font>); +01668 <font class="comment">// delete sons.</font> +01669 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessFace(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>); +01670 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessFace(<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>); +01671 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>=NULL; +01672 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>=NULL; +01673 +01674 <font class="comment">// If not already done, merge the neighbor.</font> +01675 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>!=NULL && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()) +01676 { +01677 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->doMerge(); +01678 } +01679 +01680 } +01681 <font class="keywordflow">else</font> +01682 { +01683 <font class="comment">// Rectangular case.</font> +01684 <font class="comment">// Since minimum Order is 2, Sons of rectangular face are NEVER at TileLimitLevel. => no Uv merge to do.</font> +01685 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level< <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel); +01686 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>); +01687 +01688 <font class="comment">// 1. Let's merge vertex.</font> +01689 <font class="comment">//-----------------------</font> +01690 <font class="comment">// Delete vertex, only if not already done by the neighbor (ie neighbor not already merged to a leaf).</font> +01691 <font class="comment">// NB: this work even if neigbor is rectangular (see tesselation rules in splitRectangular()).</font> +01692 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a> || !<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->isLeaf()) +01693 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessVertex(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase); +01694 +01695 <font class="comment">// Delete Far Vertex. Rect patch: neightb must be of a != pathc as me => must delete FarVertex.</font> +01696 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a> || <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>); +01697 <font class="comment">// May delete this vertex from VB.</font> +01698 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->checkDeleteVertexVBFar(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVBase); +01699 +01700 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFarVertexFromRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVBase); +01701 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessFarVertex(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FVBase); +01702 +01703 +01704 <font class="comment">// 2. Must remove sons from rdr list, and insert father.</font> +01705 <font class="comment">//------------------------------------------------------</font> +01706 <font class="comment">// UGLY REFCOUNT SIDE EFFECT: do the append first.</font> +01707 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToRenderList(<font class="keyword">this</font>); +01708 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFaceFromRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>); +01709 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFaceFromRenderList(<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>); +01710 +01711 +01712 <font class="comment">// 3. Let's merge Face.</font> +01713 <font class="comment">//-------------------</font> +01714 <font class="comment">// Change father 's neighbor pointers (see splitRectangular()).</font> +01715 <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>= <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FRight; +01716 <font class="keywordflow">if</font>(FRight) <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>->changeNeighbor(<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>, <font class="keyword">this</font>); +01717 <font class="comment">// delete sons.</font> +01718 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessFace(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>); +01719 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessFace(<a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>); +01720 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>=NULL; +01721 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>=NULL; +01722 +01723 <font class="comment">// First, do it for my rectangular co-worker FBase (if not already done).</font> +01724 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()) +01725 { +01726 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->doMerge(); +01727 } +01728 <font class="comment">// If not already done, merge the neighbor.</font> +01729 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>!=NULL && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->isLeaf()) +01730 { +01731 <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->doMerge(); +01732 } +01733 } +01734 +01735 +01736 <font class="comment">// Update priority list.</font> +01737 <font class="comment">//------------------------------------------------------</font> +01738 <font class="comment">// Since we are freshly merged, unlink from any list, and link to the SplitPriorityList, because must look </font> +01739 <font class="comment">// now when we should split again.</font> +01740 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_SplitPriorityList.insert(0, 0, <font class="keyword">this</font>); +01741 +01742 <font class="comment">// since we are now merged maybe re-insert father in priority list.</font> +01743 <font class="keywordflow">if</font>(Father) +01744 { +01745 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_7">Father</a>->isLeaf()); +01746 <font class="comment">// If sons of father are both leaves (ie this, and the other (complexe case if rectangle) )</font> +01747 <font class="keywordflow">if</font>( <a class="code" href="classNL3D_1_1CTessFace.html#z819_7">Father</a>->SonLeft->isLeaf() && <a class="code" href="classNL3D_1_1CTessFace.html#z819_7">Father</a>->SonRight->isLeaf() ) +01748 { +01749 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_MergePriorityList.insert(0, 0, <a class="code" href="classNL3D_1_1CTessFace.html#z819_7">Father</a>); +01750 } +01751 } +01752 +01753 } +01754 +01755 +01756 <font class="comment">// ***************************************************************************</font> +<a name="l01757"></a><a class="code" href="classNL3D_1_1CTessFace.html#a12">01757</a> <font class="keywordtype">bool</font> CTessFace::merge() +01758 { +01759 <font class="comment">// Must not be a leaf.</font> +01760 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +01761 +01762 <font class="comment">// 0. Verify if merge is posible.</font> +01763 <font class="comment">//----------------------------</font> +01764 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#c2">canMerge</a>(<font class="keyword">false</font>)) +01765 <font class="keywordflow">return</font> <font class="keyword">false</font>; +01766 +01767 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a81">ProfNMerges</a>, 1); +01768 +01769 <font class="comment">// 1. Let's merge the face.</font> +01770 <font class="comment">//-----------------------</font> +01771 <font class="comment">// Propagation is done in doMerge().</font> +01772 <a class="code" href="classNL3D_1_1CTessFace.html#c4">doMerge</a>(); +01773 +01774 <font class="keywordflow">return</font> <font class="keyword">true</font>; +01775 } +01776 +01777 <font class="comment">// ***************************************************************************</font> +<a name="l01778"></a><a class="code" href="classNL3D_1_1CTessFace.html#a13">01778</a> <font class="keywordtype">void</font> CTessFace::refineAll() +01779 { +01780 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a77">ProfNRefineFaces</a>, 1); +01781 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a79">ProfNRefineLeaves</a>, <a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()?1:0); +01782 +01783 <font class="comment">/*</font> +01784 <font class="comment"> if(ps<RefineThreshold), the face must be merged (ie have no leaves).</font> +01785 <font class="comment"> if(ps E [RefineThreshold, RefineTreshold*2]), the face must be splitted (ave leaves), and is geomorphed.</font> +01786 <font class="comment"> if(ps>RefineThreshold*2), the face is fully splitted/geomoprhed (tests reported on sons...).</font> +01787 <font class="comment"> */</font> +01788 +01789 <font class="comment">// Test for Split or merge.</font> +01790 <font class="comment">//-----------------------</font> +01791 { +01792 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a78">ProfNRefineComputeFaces</a>, 1); +01793 +01794 <a class="code" href="classNL3D_1_1CTessFace.html#a10">updateErrorMetric</a>(); +01795 <font class="keywordtype">float</font> ps=<a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a>; +01796 ps*= CLandscapeGlobals::OORefineThreshold; +01797 <font class="comment">// 1.0f is the point of split().</font> +01798 <font class="comment">// 2.0f is the end of geomorph.</font> +01799 +01800 +01801 <font class="comment">// Test split/merge.</font> +01802 <font class="comment">//---------------------</font> +01803 <font class="comment">// If wanted, not already done, and limit not reached, split().</font> +01804 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +01805 { +01806 <font class="keywordflow">if</font>(ps>1.0f && <a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>< (<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel + CLandscapeGlobals::TileMaxSubdivision) ) +01807 <a class="code" href="classNL3D_1_1CTessFace.html#a11">split</a>(); +01808 } +01809 <font class="keywordflow">else</font> +01810 { +01811 <font class="comment">// Else, if splitted, must merge (if not already the case).</font> +01812 <font class="keywordflow">if</font>(ps<1.0f) +01813 { +01814 <font class="comment">// Merge only if agree, and neighbors agree.</font> +01815 <font class="comment">// canMerge() test all the good thing: FBase==CantMergeFace, or this is rectangular etc...</font> +01816 <font class="comment">// The test is propagated to neighbors.</font> +01817 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#c2">canMerge</a>(<font class="keyword">true</font>)) +01818 { +01819 <a class="code" href="classNL3D_1_1CTessFace.html#a12">merge</a>(); +01820 } +01821 } +01822 } +01823 } +01824 +01825 <font class="comment">// Recurs.</font> +01826 <font class="comment">//-----------------------</font> +01827 <font class="keywordflow">if</font>(SonLeft) +01828 { +01829 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->refineAll(); +01830 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->refineAll(); +01831 } +01832 +01833 } +01834 +01835 +01836 <font class="comment">// ***************************************************************************</font> +01837 <font class="comment">// Some updateRefine***() Doc:</font> +01838 +01839 <font class="comment">// Split or merge, and meaning of errorMetric:</font> +01840 <font class="comment">/*</font> +01841 <font class="comment"> if(errorMetric<RefineThreshold), the face must be merged (ie have no leaves).</font> +01842 <font class="comment"> if(errorMetric E [RefineThreshold, RefineTreshold*2]), the face must be splitted (ave leaves), and is geomorphed.</font> +01843 <font class="comment"> if(errorMetric>RefineThreshold*2), the face is fully splitted/geomoprhed.</font> +01844 <font class="comment">*/</font> +01845 +01846 +01847 <font class="comment">// Compute distNormalSplitMerge: distance from refineCenter to normal split/merge (ie without tile transition):</font> +01848 <font class="comment">/* </font> +01849 <font class="comment"> normal ErrorMetric formula is:</font> +01850 <font class="comment"> em = Size*OORefineThreshold/ dist^2; with dist == (SplitPoint - CLandscapeGlobals::RefineCenter).norm()</font> +01851 <font class="comment"> So inverse this function and we have:</font> +01852 <font class="comment"> dist= sqrt(Size*OORefineThreshold/em).</font> +01853 <font class="comment"> Split or merge is when em==1, so </font> +01854 <font class="comment"> distSplitMerge= sqrt(Size*OORefineThreshold)</font> +01855 <font class="comment">*/</font> +01856 +01857 +01858 <font class="comment">// Compute distTileTransSplitMerge.</font> +01859 <font class="comment">/* When we are sure that CLandscapeGlobals::TileDistNear < distMinFace < CLandscapeGlobals::TileDistFar, </font> +01860 <font class="comment"> the clamp in the original formula is skipped</font> +01861 <font class="comment"> </font> +01862 <font class="comment"> So the TileErrorMetric formula is:</font> +01863 <font class="comment"></font> +01864 <font class="comment"> {</font> +01865 <font class="comment"> ema= Sife*OORefineThreshold / distSP^2.</font> +01866 <font class="comment"> f= (TileDistFar^2 - distMinFace^2) * OOTileDeltaDist^2</font> +01867 <font class="comment"> f= f ^ 4. // no clamp. see above.</font> +01868 <font class="comment"> emb= NL*f + ema*(1-f)</font> +01869 <font class="comment"> emFinal= max(ema, emb).</font> +01870 <font class="comment"> }</font> +01871 <font class="comment"></font> +01872 <font class="comment"> The problem is that the formula is too complex (degree 8 equation). </font> +01873 <font class="comment"> So search for the result recursively.</font> +01874 <font class="comment">*/</font> +01875 +01876 +01877 <font class="comment">// Quadrant Selection</font> +01878 <font class="comment">/*</font> +01879 <font class="comment"> Quadrant/Direction is interesting for updateRefineSplit() only.</font> +01880 <font class="comment"> In the 2 most simples cases, the action we want is "Know when we enters in a bounding volume"</font> +01881 <font class="comment"> This fit well for Quadrant notion.</font> +01882 <font class="comment"></font> +01883 <font class="comment"> In the case "TileDistNear to TileDistFar", the rule is too complicated and there is also</font> +01884 <font class="comment"> the notion of "Know when we LEAVE the TileDistFar sphere around the face" which is incompatible</font> +01885 <font class="comment"> with Quadrant behavior (since can go in any direction to leave the sphere).</font> +01886 <font class="comment"></font> +01887 <font class="comment"> updateRefineMerge() are at least all notion of "Know when we LEAVE the SplitSphere around the SplitPoint"</font> +01888 <font class="comment"> which is incompatible with Quadrant behavior.</font> +01889 <font class="comment"> This is why updateRefineMerge() don't bother at all quadrant, and so the _MergePriorityList is inited with 0</font> +01890 <font class="comment"> quadrants.</font> +01891 <font class="comment"></font> +01892 <font class="comment">*/</font> +01893 +01894 <font class="comment">// ***************************************************************************</font> +<a name="l01895"></a><a class="code" href="classNL3D_1_1CTessFace.html#a14">01895</a> <font class="keywordtype">void</font> CTessFace::updateRefineSplit() +01896 { +01897 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a77">ProfNRefineFaces</a>, 1); +01898 +01899 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>); +01900 <font class="comment">// The face must be not splitted, because tested for split.</font> +01901 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +01902 +01903 <font class="comment">/*</font> +01904 <font class="comment"> NB: see above for some updateRefine*** doc.</font> +01905 <font class="comment"> */</font> +01906 +01907 <font class="comment">// Test for Split.</font> +01908 <font class="comment">//-----------------------</font> +01909 <font class="keywordtype">bool</font> splitted= <font class="keyword">false</font>; +01910 { +01911 <a class="code" href="classNL3D_1_1CTessFace.html#a10">updateErrorMetric</a>(); +01912 <font class="keywordtype">float</font> ps=<a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a>; +01913 ps*= CLandscapeGlobals::OORefineThreshold; +01914 <font class="comment">// 1.0f is the point of split().</font> +01915 <font class="comment">// 2.0f is the end of geomorph.</font> +01916 +01917 +01918 <font class="comment">// Test split.</font> +01919 <font class="comment">//---------------------</font> +01920 <font class="comment">// If wanted and limit not reached, split().</font> +01921 <font class="keywordflow">if</font>(ps>1.0f && <a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>< (<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel + CLandscapeGlobals::TileMaxSubdivision) ) +01922 { +01923 <a class="code" href="classNL3D_1_1CTessFace.html#a11">split</a>(); +01924 +01925 <font class="comment">// if split ok</font> +01926 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +01927 { +01928 splitted= <font class="keyword">true</font>; +01929 } +01930 } +01931 } +01932 +01933 +01934 <font class="comment">// Insert the face in the priority list.</font> +01935 <font class="comment">//-----------------------</font> +01936 <font class="comment">// If splitted, then insertion in Landscape->MergePriorityList at 0 has been done. so nothing to update.</font> +01937 <font class="comment">// Else, must compute when whe should re-test.</font> +01938 <font class="keywordflow">if</font>(!splitted) +01939 { +01940 <font class="comment">// the face is not splitted here.</font> +01941 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +01942 +01943 <font class="keywordtype">float</font> minDeltaDistToUpdate; +01944 +01945 <font class="comment">// by default insert in the quadrant-less rolling table.</font> +01946 uint quadrantId= 0; +01947 +01948 +01949 CVector dirToSplitPoint= <a class="code" href="classNL3D_1_1CTessFace.html#z821_2">SplitPoint</a> - CLandscapeGlobals::RefineCenter; +01950 <font class="comment">// The distance of SplitPoint to center.</font> +01951 <font class="keywordtype">float</font> distSplitPoint= dirToSplitPoint.norm(); +01952 <font class="comment">// The distance where we should split/merge. see updateRefin() doc.</font> +01953 <font class="keywordtype">float</font> distNormalSplitMerge= (float)sqrt(<a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>*CLandscapeGlobals::OORefineThreshold); +01954 +01955 +01956 <font class="comment">// If the face is at its max subdivision</font> +01957 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel+CLandscapeGlobals::TileMaxSubdivision) +01958 { +01959 <font class="comment">// special case: the face do not need to be tested for splitting, because Max subdivision reached.</font> +01960 <font class="comment">// Hence just unlink from any list, and return.</font> +01961 <a class="code" href="classNL3D_1_1CTessFacePListNode.html#a5">unlinkInPList</a>(); +01962 <font class="keywordflow">return</font>; +01963 } +01964 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +01965 { +01966 <font class="comment">// Always normal ErrorMetric. Because Faces at Tile level decide to split or merge their sons independently </font> +01967 <font class="comment">// of "Tile ErrorMetric".</font> +01968 +01969 <font class="comment">// The test is "when do we enter in the Split area?", so we can use Quadrant PriorityList</font> +01970 quadrantId= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_SplitPriorityList.selectQuadrant(dirToSplitPoint); +01971 +01972 <font class="comment">// compute distance to split as default "No Quadrant"</font> +01973 minDeltaDistToUpdate= distSplitPoint - distNormalSplitMerge; +01974 +01975 <font class="comment">// If a quadrant is selected, try to use it</font> +01976 <font class="keywordflow">if</font>(quadrantId>0) +01977 { +01978 <font class="keyword">const</font> CVector &quadrantDir= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_SplitPriorityList.getQuadrantDirection(quadrantId); +01979 +01980 <font class="comment">// We must not approach the SplitPoint at distNormalSplitMerge</font> +01981 <font class="keywordtype">float</font> dMin= quadrantDir*dirToSplitPoint - distNormalSplitMerge; +01982 +01983 <font class="comment">// If the dist with quadrant is too small then use the std way (without quadrant).</font> +01984 <font class="keywordflow">if</font>( dMin<<a class="code" href="tessellation_8cpp.html#a0">NL3D_TESS_USE_QUADRANT_THRESHOLD</a> ) +01985 quadrantId= 0; +01986 <font class="comment">// else ok, use quadrant behavior</font> +01987 <font class="keywordflow">else</font> +01988 minDeltaDistToUpdate= dMin; +01989 } +01990 } +01991 <font class="keywordflow">else</font> +01992 { +01993 <font class="comment">// Compute Distance of the face from RefineCenter. It is the min of the 3 points, as in computeTileErrorMetric().</font> +01994 CVector dirToV0= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->EndPos - CLandscapeGlobals::RefineCenter; +01995 CVector dirToV1= <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->EndPos - CLandscapeGlobals::RefineCenter; +01996 CVector dirToV2= <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->EndPos - CLandscapeGlobals::RefineCenter; +01997 <font class="keywordtype">float</font> s0= dirToV0.sqrnorm(); +01998 <font class="keywordtype">float</font> s1= dirToV1.sqrnorm(); +01999 <font class="keywordtype">float</font> s2= dirToV2.sqrnorm(); +02000 <font class="keywordtype">float</font> distMinFace= (float)sqrt( minof(s0, s1, s2) ); +02001 +02002 <font class="comment">// compute the delta distance to the normal split point. See above for doc.</font> +02003 <font class="keywordtype">float</font> normalEMDeltaDist; +02004 normalEMDeltaDist= distSplitPoint - distNormalSplitMerge; +02005 +02006 +02007 <font class="comment">/* </font> +02008 <font class="comment"> There is 3 possibles cases, according to level, and the distances minFaceDist:</font> +02009 <font class="comment"> */</font> +02011 <font class="keywordflow">if</font>( distMinFace > CLandscapeGlobals::TileDistFar ) +02012 { +02013 <font class="comment">// The test is "when do we enter in the Split area OR in TileDistFar area?", so we can use Quadrant PriorityList</font> +02014 quadrantId= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_SplitPriorityList.selectQuadrant(dirToSplitPoint); +02015 +02016 <font class="comment">// compute deltaDist as default "Direction less quadrant"</font> +02017 minDeltaDistToUpdate= normalEMDeltaDist; +02018 <font class="comment">// We must know when we enter in TileErrorMetric zone, because the computing is different.</font> +02019 minDeltaDistToUpdate= <a class="code" href="bit__set_8cpp.html#a0">min</a>(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistFar); +02020 +02021 <font class="comment">// try with quadrant if > 0.</font> +02022 <font class="keywordflow">if</font>(quadrantId>0) +02023 { +02024 <font class="keyword">const</font> CVector &quadrantDir= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_SplitPriorityList.getQuadrantDirection(quadrantId); +02025 +02026 <font class="comment">// We must not approach the SplitPoint at distNormalSplitMerge</font> +02027 <font class="keywordtype">float</font> dMin= quadrantDir*dirToSplitPoint - distNormalSplitMerge; +02028 <font class="comment">// and we must not reach one of the 3 sphere (Vi, TileDistFar).</font> +02029 <font class="keywordtype">float</font> d0 = quadrantDir*dirToV0 - CLandscapeGlobals::TileDistFar; +02030 <font class="keywordtype">float</font> d1 = quadrantDir*dirToV1 - CLandscapeGlobals::TileDistFar; +02031 <font class="keywordtype">float</font> d2 = quadrantDir*dirToV2 - CLandscapeGlobals::TileDistFar; +02032 <font class="comment">// take min dist</font> +02033 dMin= minof(dMin, d0, d1, d2); +02034 +02035 <font class="comment">// If the dist with quadrant is too small then use the std way (without quadrant).</font> +02036 <font class="keywordflow">if</font>( dMin<<a class="code" href="tessellation_8cpp.html#a0">NL3D_TESS_USE_QUADRANT_THRESHOLD</a> ) +02037 quadrantId= 0; +02038 <font class="comment">// else ok, use quadrant behavior</font> +02039 <font class="keywordflow">else</font> +02040 minDeltaDistToUpdate= dMin; +02041 } +02042 } +02044 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( distMinFace > CLandscapeGlobals::TileDistNear ) +02045 { +02046 <font class="comment">// NB: can't use quadrant behavior here. Leave quadrantId at 0.</font> +02047 +02048 <font class="comment">// Profile</font> +02049 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a82">ProfNRefineInTileTransition</a>, 1); +02050 +02051 <font class="comment">// Compute distance to split/Merge in TileTransition</font> +02052 <font class="keywordtype">float</font> distTileTransSplitMerge; +02053 <font class="keywordtype">float</font> maxDeltaDist= 8; +02054 <font class="keywordtype">float</font> minDeltaDist= 0; +02055 uint nbRecurs= 6; +02056 <font class="keywordtype">float</font> nearLimit; +02057 nearLimit= CLandscapeGlobals::RefineThreshold * <a class="code" href="classNL3D_1_1CTessFace.html#a9">computeNearLimit</a>(); +02058 <font class="comment">// search the distance to split recursively.</font> +02059 <font class="keywordflow">for</font>(uint i=0; i< nbRecurs; i++) +02060 { +02061 <font class="keywordtype">float</font> pivotDeltaDist= (maxDeltaDist-minDeltaDist)/2; +02062 <font class="comment">// If the em computed with this distance is still <1 (ie merged), then we can move further.</font> +02063 <font class="keywordflow">if</font> ( <a class="code" href="classNL3D_1_1CTessFace.html#c1">computeTileEMForUpdateRefine</a>(distSplitPoint-pivotDeltaDist, distMinFace-pivotDeltaDist, nearLimit ) < 1) +02064 minDeltaDist= pivotDeltaDist; +02065 <font class="comment">// else we must move not as far</font> +02066 <font class="keywordflow">else</font> +02067 maxDeltaDist= pivotDeltaDist; +02068 } +02069 <font class="comment">// And so take the minimum resulting delta distance</font> +02070 distTileTransSplitMerge= minDeltaDist; +02071 +02072 <font class="comment">// take the min with distance of distMinFace to the TileDistNear and TileDistFar sphere, because formula change at</font> +02073 <font class="comment">// those limits.</font> +02074 minDeltaDistToUpdate= <a class="code" href="bit__set_8cpp.html#a0">min</a>(distTileTransSplitMerge, CLandscapeGlobals::TileDistFar - distMinFace ); +02075 minDeltaDistToUpdate= <a class="code" href="bit__set_8cpp.html#a0">min</a>(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistNear); +02076 } +02078 <font class="keywordflow">else</font> +02079 { +02080 <font class="comment">// because the face is not a Tile Level (ie Level<Patch->TileLimitLevel), it should be splitted, </font> +02081 <font class="comment">// and won't merge until reaching at least the TileDistNear sphere.</font> +02082 <font class="comment">// if not splited (should not arise), force the split next time.</font> +02083 minDeltaDistToUpdate= 0; +02084 } +02085 +02086 } +02087 +02088 <font class="comment">// Profile.</font> +02089 <font class="keywordflow">if</font>(minDeltaDistToUpdate<0.0625) +02090 { +02091 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a83">ProfNRefineWithLowDistance</a>, 1); +02092 } +02093 +02094 +02095 <font class="comment">// insert in the Split priority list.</font> +02096 <font class="comment">// Until the RefineCenter move under minDeltaDistToUpdate, we don't need to test face.</font> +02097 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_SplitPriorityList.insert(quadrantId, minDeltaDistToUpdate, <font class="keyword">this</font>); +02098 } +02099 } +02100 +02101 +02102 <font class="comment">// ***************************************************************************</font> +<a name="l02103"></a><a class="code" href="classNL3D_1_1CTessFace.html#a15">02103</a> <font class="keywordtype">void</font> CTessFace::updateRefineMerge() +02104 { +02105 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a77">ProfNRefineFaces</a>, 1); +02106 +02107 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>); +02108 <font class="comment">// The face must be splitted, because tested for merge.</font> +02109 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +02110 +02111 <font class="comment">/*</font> +02112 <font class="comment"> NB: see above for some updateRefine*** doc.</font> +02113 <font class="comment"> */</font> +02114 +02115 <font class="comment">// Test for merge.</font> +02116 <font class="comment">//-----------------------</font> +02117 <font class="keywordtype">bool</font> merged= <font class="keyword">false</font>; +02118 { +02119 <a class="code" href="classNL3D_1_1CTessFace.html#a10">updateErrorMetric</a>(); +02120 <font class="keywordtype">float</font> ps=<a class="code" href="classNL3D_1_1CTessFace.html#z821_3">ErrorMetric</a>; +02121 ps*= CLandscapeGlobals::OORefineThreshold; +02122 <font class="comment">// 1.0f is the point of split().</font> +02123 <font class="comment">// 2.0f is the end of geomorph.</font> +02124 +02125 +02126 <font class="comment">// Test merge.</font> +02127 <font class="comment">//---------------------</font> +02128 <font class="comment">// Else, must merge ??</font> +02129 <font class="keywordflow">if</font>(ps<1.0f) +02130 { +02131 <font class="comment">// Merge only if agree, and neighbors agree.</font> +02132 <font class="comment">// canMerge() test all the good thing: FBase==CantMergeFace, or this is rectangular etc...</font> +02133 <font class="comment">// The test is propagated to neighbors.</font> +02134 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#c2">canMerge</a>(<font class="keyword">true</font>)) +02135 { +02136 <a class="code" href="classNL3D_1_1CTessFace.html#a12">merge</a>(); +02137 +02138 <font class="comment">// NB: here, merge() is not propagated to fathers (supposed to be not very usefull).</font> +02139 +02140 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02141 { +02142 merged= <font class="keyword">true</font>; +02143 } +02144 } +02145 } +02146 } +02147 +02148 +02149 <font class="comment">// Insert the face in the priority list.</font> +02150 <font class="comment">//-----------------------</font> +02151 <font class="comment">// If merged, then insertion in Landscape->SplitPriorityList at 0 has been done. so nothing to update.</font> +02152 <font class="comment">// Else, must compute when whe should re-test.</font> +02153 <font class="keywordflow">if</font>(!merged) +02154 { +02155 <font class="comment">// the face is splitted here.</font> +02156 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +02157 +02158 <font class="keywordtype">float</font> minDeltaDistToUpdate; +02159 +02160 +02161 <font class="comment">// The distance of SplitPoint to center.</font> +02162 <font class="keywordtype">float</font> distSplitPoint= (<a class="code" href="classNL3D_1_1CTessFace.html#z821_2">SplitPoint</a> - CLandscapeGlobals::RefineCenter).norm(); +02163 <font class="comment">// Compute distance from refineCenter to normal split/merge (ie without tile transition).</font> +02164 <font class="keywordtype">float</font> distNormalSplitMerge= (float)sqrt(<a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>*CLandscapeGlobals::OORefineThreshold); +02165 +02166 +02167 <font class="comment">// If the face is at its max subdivision</font> +02168 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel+CLandscapeGlobals::TileMaxSubdivision) +02169 { +02170 <font class="comment">// since the face is splitted, then must test always this face, because we must merge it (as soon as it is possible).</font> +02171 minDeltaDistToUpdate= 0; +02172 } +02173 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>>=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +02174 { +02175 <font class="comment">// Always normal ErrorMetric. Because Faces at Tile level decide to split or merge their sons independently </font> +02176 <font class="comment">// of "Tile ErrorMetric".</font> +02177 <font class="comment">// since splitted, compute distance to merge.</font> +02178 minDeltaDistToUpdate= distNormalSplitMerge - distSplitPoint; +02179 <font class="comment">// NB: it is possible that minDeltaDistToUpdate<0. A good example is when we are enforced split.</font> +02180 <font class="comment">// Then, distSplitMerge may be < distSplitPoint, meaning we should have not split, but a neigbhor has enforced us.</font> +02181 <font class="comment">// So now, must test every frame if we can merge....</font> +02182 minDeltaDistToUpdate= max( 0.f, minDeltaDistToUpdate ); +02183 } +02184 <font class="keywordflow">else</font> +02185 { +02186 <font class="comment">// Compute Distance of the face from RefineCenter. It is the min of the 3 points, as in computeTileErrorMetric().</font> +02187 <font class="keywordtype">float</font> s0= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm(); +02188 <font class="keywordtype">float</font> s1= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm(); +02189 <font class="keywordtype">float</font> s2= (<a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->EndPos - CLandscapeGlobals::RefineCenter).sqrnorm(); +02190 <font class="keywordtype">float</font> distMinFace= (float)sqrt( minof(s0, s1, s2) ); +02191 +02192 <font class="comment">// compute the delta distance to the normal split point. See above for doc.</font> +02193 <font class="keywordtype">float</font> normalEMDeltaDist; +02194 normalEMDeltaDist= distNormalSplitMerge - distSplitPoint; +02195 normalEMDeltaDist= max( 0.f, normalEMDeltaDist ); +02196 +02197 +02198 <font class="comment">/* </font> +02199 <font class="comment"> There is 3 possibles cases, according to level, and the distances minFaceDist:</font> +02200 <font class="comment"> */</font> +02202 <font class="keywordflow">if</font>( distMinFace > CLandscapeGlobals::TileDistFar ) +02203 { +02204 <font class="comment">// normal geomorph. Any face compute the distance to the SplitPoint, and take min with distance to</font> +02205 <font class="comment">// the TileDistFar sphere. </font> +02206 minDeltaDistToUpdate= normalEMDeltaDist; +02207 +02208 <font class="comment">// We must know when we enter in TileErrorMetric zone, because the computing is different.</font> +02209 minDeltaDistToUpdate= <a class="code" href="bit__set_8cpp.html#a0">min</a>(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistFar); +02210 } +02212 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( distMinFace > CLandscapeGlobals::TileDistNear ) +02213 { +02214 <font class="comment">// Profile</font> +02215 <a class="code" href="landscape__profile_8h.html#a2">NL3D_PROFILE_LAND_ADD</a>(<a class="code" href="namespaceNL3D.html#a82">ProfNRefineInTileTransition</a>, 1); +02216 +02217 +02218 <font class="comment">// Compute distance to split/Merge in TileTransition</font> +02219 <font class="keywordtype">float</font> distTileTransSplitMerge; +02220 <font class="keywordtype">float</font> maxDeltaDist= 8; +02221 <font class="keywordtype">float</font> minDeltaDist= 0; +02222 uint nbRecurs= 6; +02223 <font class="keywordtype">float</font> nearLimit; +02224 nearLimit= CLandscapeGlobals::RefineThreshold * <a class="code" href="classNL3D_1_1CTessFace.html#a9">computeNearLimit</a>(); +02225 <font class="comment">// Since splitted, compute distance to merge.</font> +02226 <font class="comment">// search the distance recursively.</font> +02227 <font class="keywordflow">for</font>(uint i=0; i< nbRecurs; i++) +02228 { +02229 <font class="keywordtype">float</font> pivotDeltaDist= (maxDeltaDist-minDeltaDist)/2; +02230 <font class="comment">// If the em computed with this distance is still >1 (ie splitted), then we can move further.</font> +02231 <font class="keywordflow">if</font> ( <a class="code" href="classNL3D_1_1CTessFace.html#c1">computeTileEMForUpdateRefine</a>(distSplitPoint+pivotDeltaDist, distMinFace+pivotDeltaDist, nearLimit ) > 1) +02232 minDeltaDist= pivotDeltaDist; +02233 <font class="comment">// else we must move not as far</font> +02234 <font class="keywordflow">else</font> +02235 maxDeltaDist= pivotDeltaDist; +02236 } +02237 <font class="comment">// And so take the minimum resulting delta distance</font> +02238 distTileTransSplitMerge= minDeltaDist; +02239 +02240 <font class="comment">// take the min with distance of distMinFace to the TileDistNear and TileDistFar sphere, because formula change at</font> +02241 <font class="comment">// those limits.</font> +02242 minDeltaDistToUpdate= <a class="code" href="bit__set_8cpp.html#a0">min</a>(distTileTransSplitMerge, CLandscapeGlobals::TileDistFar - distMinFace ); +02243 minDeltaDistToUpdate= <a class="code" href="bit__set_8cpp.html#a0">min</a>(minDeltaDistToUpdate, distMinFace - CLandscapeGlobals::TileDistNear); +02244 } +02246 <font class="keywordflow">else</font> +02247 { +02248 <font class="comment">// because the face is not a Tile Level (ie Level<Patch->TileLimitLevel), it should be splitted, </font> +02249 <font class="comment">// and won't merge until reaching at least the TileDistNear sphere.</font> +02250 <font class="comment">// Since splitted, Must enter in TileErrorMetric area to know when to merge.</font> +02251 minDeltaDistToUpdate= CLandscapeGlobals::TileDistNear - distMinFace; +02252 } +02253 +02254 } +02255 +02256 <font class="comment">// Merge Refine Threshold: because of enforced splits, we have lot of faces whit minDeltaDistToUpdate<0, because</font> +02257 <font class="comment">// they alwayas want to merge. To avoid this, add a delta, which delay the test for merge.</font> +02258 <font class="comment">// The caveat is that faces which do not need this may merge later. But 2 meters won't add too many faces.</font> +02259 minDeltaDistToUpdate+= <a class="code" href="landscape__def_8h.html#a7">NL3D_REFINE_MERGE_THRESHOLD</a>; +02260 +02261 <font class="comment">// insert in the Merge priority list.</font> +02262 <font class="comment">// Until the RefineCenter move under minDeltaDistToUpdate, we don't need to test face.</font> +02263 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->_MergePriorityList.insert(0, minDeltaDistToUpdate, <font class="keyword">this</font>); +02264 } +02265 } +02266 +02267 +02268 <font class="comment">// ***************************************************************************</font> +<a name="l02269"></a><a class="code" href="classNL3D_1_1CTessFace.html#a17">02269</a> <font class="keywordtype">void</font> CTessFace::unbind() +02270 { +02271 <font class="comment">// NB: since CantMergeFace has a NULL patch ptr, it is unbound too.</font> +02272 +02273 <font class="comment">// Square case.</font> +02274 <font class="comment">//=============</font> +02275 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +02276 { +02277 <font class="comment">// Change Left/Right neighbors.</font> +02278 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02279 { +02280 <font class="comment">// FLeft and FRight pointers are only valid in Leaves nodes.</font> +02281 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>) +02282 { +02283 <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->changeNeighbor(<font class="keyword">this</font>, NULL); +02284 <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>= NULL; +02285 } +02286 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>) +02287 { +02288 <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>->changeNeighbor(<font class="keyword">this</font>, NULL); +02289 <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>= NULL; +02290 } +02291 } +02292 <font class="comment">// Change Base neighbors.</font> +02293 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>) +02294 { +02295 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *oldNeigbhorFace= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>; +02296 +02297 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->changeNeighbor(<font class="keyword">this</font>, NULL); +02298 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>= NULL; +02299 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02300 { +02301 <font class="comment">// Duplicate the VBase of sons, so the unbind is correct and no vertices are shared.</font> +02302 CTessVertex *old= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase; +02303 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessVertex(); +02304 *(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase)= *old; +02305 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase; +02306 +02307 <font class="comment">// For geomorph (VertexProgram or soft), compute good MaxFaceSize and MaxNearLimit (change since unbinded)</font> +02308 <font class="comment">// update us.</font> +02309 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->MaxFaceSize= <a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>; +02310 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->MaxNearLimit= <a class="code" href="classNL3D_1_1CTessFace.html#a9">computeNearLimit</a>(); +02311 <font class="comment">// update our neigbhor, only if not a multiple patch face.</font> +02312 <font class="keywordflow">if</font>(oldNeigbhorFace->Patch) +02313 { +02314 old->MaxFaceSize= oldNeigbhorFace->Size; +02315 old->MaxNearLimit= oldNeigbhorFace->computeNearLimit(); +02316 } +02317 } +02318 } +02319 } +02320 <font class="comment">// Rectangular case.</font> +02321 <font class="comment">//==================</font> +02322 <font class="keywordflow">else</font> +02323 { +02324 <font class="comment">// Doens't need to test FBase, since must be same patch.</font> +02325 <font class="comment">// In rectangular, FLeft has the behavior of FBase in square case.</font> +02326 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>) +02327 { +02328 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *oldNeigbhorFace= <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>; +02329 +02330 <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->changeNeighbor(<font class="keyword">this</font>, NULL); +02331 <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>= NULL; +02332 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02333 { +02334 <font class="comment">// Duplicate the VBase of sons, so the unbind is correct and no vertices are shared.</font> +02335 <font class="comment">// NB: this code is a bit different from square case.</font> +02336 CTessVertex *old= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase; +02337 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->newTessVertex(); +02338 *(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase)= *old; +02339 <font class="comment">// This is the difference: (see rectangle tesselation rules).</font> +02340 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase; +02341 <font class="comment">// Yoyo_patch_himself (12/02/2001): I forgot this one!!</font> +02342 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft); +02343 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->VRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase; +02344 +02345 +02346 <font class="comment">// For geomorph (VertexProgram or soft), compute good MaxFaceSize and MaxNearLimit (change since unbinded)</font> +02347 <font class="comment">// update us.</font> +02348 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->MaxFaceSize= <a class="code" href="classNL3D_1_1CTessFace.html#z821_1">Size</a>; +02349 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->MaxNearLimit= <a class="code" href="classNL3D_1_1CTessFace.html#a9">computeNearLimit</a>(); +02350 <font class="comment">// update our neigbhor, only if not a multiple patch face.</font> +02351 <font class="keywordflow">if</font>(oldNeigbhorFace->Patch) +02352 { +02353 old->MaxFaceSize= oldNeigbhorFace->Size; +02354 old->MaxNearLimit= oldNeigbhorFace->computeNearLimit(); +02355 } +02356 } +02357 } +02358 <font class="comment">// But FRight still valid in leaves nodes only.</font> +02359 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02360 { +02361 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>->Patch!=<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>) +02362 { +02363 <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>->changeNeighbor(<font class="keyword">this</font>, NULL); +02364 <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>= NULL; +02365 } +02366 } +02367 } +02368 +02369 <font class="comment">// Propagate unbind.</font> +02370 <font class="comment">//==================</font> +02371 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02372 { +02373 <font class="comment">// update sons vertex pointers (since they may have been updated by me or my grandfathers).</font> +02374 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +02375 { +02376 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>; +02377 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>; +02378 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>; +02379 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>; +02380 } +02381 <font class="keywordflow">else</font> +02382 { +02383 <font class="comment">// Rectangular case. Update only ptrs which may have changed.</font> +02384 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VLeft= <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>; +02385 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VBase= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>; +02386 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VRight= <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>; +02387 } +02388 +02389 <font class="comment">// Must re-create good Vertex links for Far and Near Vertices!!!</font> +02390 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->updateNearFarVertices(); +02391 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->updateNearFarVertices(); +02392 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +02393 { +02394 <font class="comment">//NB: must do this for Base neighbor (see unbind() rectangular case...).</font> +02395 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonRight); +02396 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->updateNearFarVertices(); +02397 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonRight->updateNearFarVertices(); +02398 } +02399 +02400 <font class="comment">// unbind the sons.</font> +02401 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->unbind(); +02402 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->unbind(); +02403 } +02404 +02405 } +02406 <font class="comment">// ***************************************************************************</font> +<a name="l02407"></a><a class="code" href="classNL3D_1_1CTessFace.html#a18">02407</a> <font class="keywordtype">void</font> CTessFace::forceMerge() +02408 { +02409 <font class="keywordflow">if</font>(<font class="keyword">this</font>== &<a class="code" href="classNL3D_1_1CTessFace.html#r0">CantMergeFace</a>) +02410 <font class="keywordflow">return</font>; +02411 +02412 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02413 { +02414 <font class="comment">// First, force merge of Sons and neighbor sons, to have a diamond configuration.</font> +02415 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->forceMerge(); +02416 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->forceMerge(); +02417 +02418 <font class="comment">// forceMerge of necessary neighbors.</font> +02419 <a class="code" href="classNL3D_1_1CTessFace.html#z819_15">RecursMarkForceMerge</a>=<font class="keyword">true</font>; +02420 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +02421 { +02422 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->RecursMarkForceMerge) +02423 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->forceMerge(); +02424 } +02425 <font class="keywordflow">else</font> +02426 { +02427 <font class="comment">// Rectangular case. May have a longer propagation...</font> +02428 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->RecursMarkForceMerge) +02429 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->forceMerge(); +02430 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a> && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->RecursMarkForceMerge) +02431 <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>->forceMerge(); +02432 } +02433 <a class="code" href="classNL3D_1_1CTessFace.html#z819_15">RecursMarkForceMerge</a>=<font class="keyword">false</font>; +02434 +02435 <font class="comment">// If still a parent, merge.</font> +02436 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02437 <a class="code" href="classNL3D_1_1CTessFace.html#a12">merge</a>(); +02438 } +02439 } +02440 +02441 +02442 <font class="comment">// ***************************************************************************</font> +<a name="l02443"></a><a class="code" href="classNL3D_1_1CTessFace.html#a23">02443</a> <font class="keywordtype">void</font> CTessFace::forceMergeAtTileLevel() +02444 { +02445 <font class="keywordflow">if</font>(<font class="keyword">this</font>== &<a class="code" href="classNL3D_1_1CTessFace.html#r0">CantMergeFace</a>) +02446 <font class="keywordflow">return</font>; +02447 +02448 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02449 { +02450 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->forceMergeAtTileLevel(); +02451 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->forceMergeAtTileLevel(); +02452 } +02453 <font class="keywordflow">else</font> +02454 { +02455 <font class="comment">// If we are at tile subdivision, we must force our sons to merge.</font> +02456 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a>==<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +02457 <a class="code" href="classNL3D_1_1CTessFace.html#a18">forceMerge</a>(); +02458 } +02459 } +02460 +02461 +02462 <font class="comment">// ***************************************************************************</font> +<a name="l02463"></a><a class="code" href="classNL3D_1_1CTessFace.html#a24">02463</a> <font class="keywordtype">void</font> CTessFace::averageTesselationVertices() +02464 { +02465 <font class="comment">// If we are not splitted, no-op.</font> +02466 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02467 <font class="keywordflow">return</font>; +02468 +02469 +02470 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *neighbor; +02471 <font class="comment">// Normal square case.</font> +02472 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +02473 { +02474 neighbor= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>; +02475 } +02476 <font class="comment">// Special Rectangular case.</font> +02477 <font class="keywordflow">else</font> +02478 { +02479 <font class="comment">// NB: here, just need to compute average of myself with FLeft, because my neighbor FBase </font> +02480 <font class="comment">// is on same patch (see splitRectangular()), and is average with its FLeft neighbor is done </font> +02481 <font class="comment">// on an other branch of the recurs call.</font> +02482 neighbor= <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>; +02483 } +02484 +02485 +02486 <font class="comment">/* Try to average with neighbor.</font> +02487 <font class="comment"> - if no neighbor, no-op :).</font> +02488 <font class="comment"> - if neighbor is bind 1/N (CantMergeFace), no-op too, because the vertex is a BaseVertex, so don't modify.</font> +02489 <font class="comment"> - if my patch is same than my neighbor, then we are on a same patch :), and so no need to average.</font> +02490 <font class="comment"> */</font> +02491 <font class="keywordflow">if</font>(neighbor!=NULL && neighbor!=&<a class="code" href="classNL3D_1_1CTessFace.html#r0">CantMergeFace</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>!= neighbor->Patch) +02492 { +02493 <a class="code" href="debug_8h.html#a6">nlassert</a>(neighbor->Patch); +02494 <a class="code" href="debug_8h.html#a6">nlassert</a>(!neighbor->isLeaf()); +02495 <font class="comment">// must compute average beetween me and my neighbor.</font> +02496 <font class="comment">// NB: this work with both rectangular and square triangles (see split*()).</font> +02497 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase == neighbor->SonLeft->VBase); +02498 +02499 CVector v0= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->computeVertex(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase.getT()); +02500 CVector v1= neighbor->Patch->computeVertex(neighbor->SonLeft->PVBase.getS(), neighbor->SonLeft->PVBase.getT()); +02501 +02502 <font class="comment">// And so set the average.</font> +02503 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->EndPos= (v0+v1)/2; +02504 } +02505 +02506 +02507 <font class="comment">// Do same thing for sons. NB: see above, we are not a leaf.</font> +02508 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->averageTesselationVertices(); +02509 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->averageTesselationVertices(); +02510 } +02511 +02512 +02513 <font class="comment">// ***************************************************************************</font> +<a name="l02514"></a><a class="code" href="classNL3D_1_1CTessFace.html#a25">02514</a> <font class="keywordtype">void</font> CTessFace::refreshTesselationGeometry() +02515 { +02516 <font class="comment">// must enlarge the little tessBlock (if any), for clipping.</font> +02517 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->extendTessBlockWithEndPos(<font class="keyword">this</font>); +02518 +02519 <font class="comment">// If we are not splitted, no-op.</font> +02520 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02521 <font class="keywordflow">return</font>; +02522 +02523 +02524 <font class="comment">/* NB: rectangular case: just need to take SonLeft->VBase, because my neighbor on FBase will compute his son</font> +02525 <font class="comment"> on an other branch of the recurs call.</font> +02526 <font class="comment"> */</font> +02527 <font class="comment">// re-compute this position (maybe with new noise geometry in Tile Edition).</font> +02528 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->EndPos= <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->computeVertex(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase.getT()); +02529 <font class="comment">// overwrite cur Pos (NB: specialy hardcoded for Tile edition).</font> +02530 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->Pos= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->EndPos; +02531 +02532 <font class="comment">// Do same thing for sons. NB: see above, we are not a leaf.</font> +02533 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->refreshTesselationGeometry(); +02534 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->refreshTesselationGeometry(); +02535 } +02536 +02537 +02538 <font class="comment">// ***************************************************************************</font> +<a name="l02539"></a><a class="code" href="classNL3D_1_1CTessFace.html#a20">02539</a> <font class="keywordtype">bool</font> CTessFace::updateBindEdge(CTessFace *&edgeFace, <font class="keywordtype">bool</font> &splitWanted) +02540 { +02541 <font class="comment">// Return true, when the bind should be Ok, or if a split has occured.</font> +02542 <font class="comment">// Return false only if pointers are updated, without splits.</font> +02543 +02544 <font class="keywordflow">if</font>(edgeFace==NULL) +02545 <font class="keywordflow">return</font> <font class="keyword">true</font>; +02546 +02547 <font class="keywordflow">if</font>(edgeFace->isLeaf()) +02548 <font class="keywordflow">return</font> <font class="keyword">true</font>; +02549 +02550 <font class="comment">/*</font> +02551 <font class="comment"> Look at the callers, and you'll see that "this" is always a leaf.</font> +02552 <font class="comment"> Therefore, edgeFace is a valid pointer (either if it is FLeft, FRight or FBase).</font> +02553 <font class="comment"> */</font> +02554 +02555 <font class="comment">// MultiPatch face case.</font> +02556 <font class="comment">//======================</font> +02557 <font class="comment">// If neighbor is a multiple face.</font> +02558 <font class="keywordflow">if</font>(edgeFace->Patch==NULL && edgeFace->FBase==<font class="keyword">this</font>) +02559 { +02560 splitWanted= <font class="keyword">true</font>; +02561 <font class="keywordflow">return</font> <font class="keyword">true</font>; +02562 } +02563 +02564 +02565 <font class="comment">// neighbor is a "Square face" case.</font> +02566 <font class="comment">//==================================</font> +02567 <font class="keywordflow">if</font>(!edgeFace->isRectangular()) +02568 { +02569 <font class="comment">// NB: this code works either if I AM a rectangular face or a square face.</font> +02570 +02571 <font class="comment">// If the neighbor is splitted on ourself, split...</font> +02572 <font class="keywordflow">if</font>(edgeFace->FBase==<font class="keyword">this</font>) +02573 { +02574 splitWanted= <font class="keyword">true</font>; +02575 <font class="keywordflow">return</font> <font class="keyword">true</font>; +02576 } +02577 <font class="keywordflow">else</font> +02578 { +02579 <font class="comment">// Just update pointers...</font> +02580 <font class="keywordflow">if</font>(edgeFace->FLeft==<font class="keyword">this</font>) +02581 { +02582 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *sonLeft= edgeFace->SonLeft; +02583 sonLeft->FBase= <font class="keyword">this</font>; +02584 edgeFace= sonLeft; +02585 } +02586 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(edgeFace->FRight==<font class="keyword">this</font>) +02587 { +02588 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *sonRight= edgeFace->SonRight; +02589 sonRight->FBase= <font class="keyword">this</font>; +02590 edgeFace= sonRight; +02591 } +02592 <font class="keywordflow">else</font> +02593 { +02594 <font class="comment">// Look at the callers, and you'll see that "this" is always a leaf.</font> +02595 <font class="comment">// Therefore, we should never be here.</font> +02596 <a class="code" href="debug_8h.html#a12">nlstop</a>; +02597 } +02598 } +02599 } +02600 <font class="comment">// neighbor is a "Rectangle face" case.</font> +02601 <font class="comment">//=====================================</font> +02602 <font class="keywordflow">else</font> +02603 { +02604 <font class="comment">// NB: this code works either if I AM a rectangular face or a square face.</font> +02605 +02606 <font class="comment">// If the neighbor is splitted on ourself, split...</font> +02607 <font class="comment">// Test FLeft because of rectangular case... :)</font> +02608 <font class="comment">// FBase should be tested too. If edgeFace->FBase==this, I should be myself a rectangular face.</font> +02609 <font class="keywordflow">if</font>(edgeFace->FLeft==<font class="keyword">this</font> || edgeFace->FBase==<font class="keyword">this</font>) +02610 { +02611 splitWanted= <font class="keyword">true</font>; +02612 <font class="keywordflow">return</font> <font class="keyword">true</font>; +02613 } +02614 <font class="keywordflow">else</font> +02615 { +02616 <font class="keywordflow">if</font>(edgeFace->FRight==<font class="keyword">this</font>) +02617 { +02618 <font class="comment">// See rectangular tesselation rules, too know why we do this.</font> +02619 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *sonRight= edgeFace->SonRight; +02620 sonRight->FRight= <font class="keyword">this</font>; +02621 edgeFace= sonRight; +02622 } +02623 <font class="keywordflow">else</font> +02624 { +02625 <font class="comment">// Look at the callers, and you'll see that "this" is always a leaf.</font> +02626 <font class="comment">// Therefore, we should never be here.</font> +02627 <a class="code" href="debug_8h.html#a12">nlstop</a>; +02628 } +02629 } +02630 } +02631 +02632 <font class="keywordflow">return</font> <font class="keyword">false</font>; +02633 } +02634 +02635 +02636 +02637 <font class="comment">// ***************************************************************************</font> +<a name="l02638"></a><a class="code" href="classNL3D_1_1CTessFace.html#a22">02638</a> <font class="keywordtype">void</font> CTessFace::updateBindAndSplit() +02639 { +02640 <font class="keywordtype">bool</font> splitWanted= <font class="keyword">false</font>; +02641 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *f0= NULL; +02642 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *f1= NULL; +02643 <font class="comment">/*</font> +02644 <font class="comment"> Look at the callers, and you'll see that "this" is always a leaf.</font> +02645 <font class="comment"> Therefore, FBase, FLeft and FRight are good pointers, and *FLeft and *FRight should be Ok too.</font> +02646 <font class="comment"> */</font> +02647 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +02648 <font class="keywordflow">while</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a20">updateBindEdge</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>, splitWanted)); +02649 <font class="comment">// FLeft and FRight pointers are only valid in Leaves nodes.</font> +02650 <font class="keywordflow">while</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a20">updateBindEdge</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>, splitWanted)); +02651 <font class="keywordflow">while</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a20">updateBindEdge</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>, splitWanted)); +02652 <font class="comment">// In rectangular case, we MUST also update edges of FBase.</font> +02653 <font class="comment">// Because splitRectangular() split those two faces at the same time.</font> +02654 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +02655 { +02656 f0= <font class="keyword">this</font>; +02657 f1= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>; +02658 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>); +02659 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()); +02660 <font class="comment">// Doesn't need to update FBase->FBase, since it's me!</font> +02661 <font class="comment">// FLeft and FRight pointers are only valid in Leaves nodes.</font> +02662 <font class="keywordflow">while</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->updateBindEdge(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->FLeft, splitWanted)); +02663 <font class="keywordflow">while</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->updateBindEdge(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->FRight, splitWanted)); +02664 } +02665 +02666 +02667 +02668 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *fmult= NULL; +02669 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *fmult0= NULL; +02670 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *fmult1= NULL; +02671 <font class="comment">// If multipatch face case.</font> +02672 <font class="comment">//=========================</font> +02673 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +02674 { +02675 <font class="comment">// multipatch face case are detected when face->Patch==NULL !!!</font> +02676 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->Patch==NULL) +02677 { +02678 fmult= <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>; +02679 <font class="comment">// First, trick: FBase is NULL, so during the split. => no ptr problem.</font> +02680 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>= NULL; +02681 } +02682 } +02683 <font class="keywordflow">else</font> +02684 { +02685 <font class="comment">// multipatch face case are detected when face->Patch==NULL !!!</font> +02686 <font class="keywordflow">if</font>(f0->FLeft && f0->FLeft->Patch==NULL) +02687 { +02688 fmult0= f0->FLeft; +02689 <font class="comment">// First, trick: neighbor is NULL, so during the split. => no ptr problem.</font> +02690 f0->FLeft= NULL; +02691 } +02692 <font class="comment">// multipatch face case are detected when face->Patch==NULL !!!</font> +02693 <font class="keywordflow">if</font>(f1->FLeft && f1->FLeft->Patch==NULL) +02694 { +02695 fmult1= f1->FLeft; +02696 <font class="comment">// First, trick: neighbor is NULL, so during the split. => no ptr problem.</font> +02697 f1->FLeft= NULL; +02698 } +02699 } +02700 +02701 <font class="comment">// Then split, and propagate.</font> +02702 <font class="comment">//===========================</font> +02703 <a class="code" href="classNL3D_1_1CTessFace.html#a11">split</a>(<font class="keyword">false</font>); +02704 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +02705 { +02706 <font class="keywordflow">if</font>(FBase) +02707 { +02708 <font class="keywordflow">while</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()) +02709 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->updateBindAndSplit(); +02710 } +02711 <font class="comment">// There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.</font> +02712 <font class="comment">// And problems may arise because this face hasn't yet good connectivity.</font> +02713 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->isLeaf() && <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->isLeaf()); +02714 } +02715 <font class="keywordflow">else</font> +02716 { +02717 <font class="keywordflow">if</font>(f0->FLeft) +02718 { +02719 <font class="keywordflow">while</font>(f0->FLeft->isLeaf()) +02720 f0->FLeft->updateBindAndSplit(); +02721 } +02722 <font class="keywordflow">if</font>(f1->FLeft) +02723 { +02724 <font class="keywordflow">while</font>(f1->FLeft->isLeaf()) +02725 f1->FLeft->updateBindAndSplit(); +02726 } +02727 <font class="comment">// There is a possible bug here (maybe easily patched). Sons may have be propagated splitted.</font> +02728 <font class="comment">// And problems may arise because this face hasn't yet good connectivity.</font> +02729 <a class="code" href="debug_8h.html#a6">nlassert</a>(f0->SonLeft->isLeaf() && f0->SonRight->isLeaf()); +02730 <a class="code" href="debug_8h.html#a6">nlassert</a>(f1->SonLeft->isLeaf() && f1->SonRight->isLeaf()); +02731 } +02732 +02733 +02734 <font class="comment">// If multipatch face case, update neighbors.</font> +02735 <font class="comment">//===========================================</font> +02736 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>() && fmult) +02737 { +02738 <font class="comment">// Update good Face neighbors.</font> +02739 <font class="comment">//============================</font> +02740 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->FRight= fmult->SonRight; +02741 fmult->SonRight->changeNeighbor(&CTessFace::MultipleBindFace, <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>); +02742 +02743 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->FLeft= fmult->SonLeft; +02744 fmult->SonLeft->changeNeighbor(&CTessFace::MultipleBindFace, <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>); +02745 +02746 <font class="comment">// NB: this work auto with 1/2 or 1/4. See CPatch::bind(), to understand.</font> +02747 <font class="comment">// In 1/4 case, fmult->SonLeft and fmult->SonRight are themselves MultiPatch face. So it will recurse.</font> +02748 +02749 <font class="comment">// Update good vertex pointer.</font> +02750 <font class="comment">//============================</font> +02751 CTessVertex *vert= fmult->VBase; +02752 +02753 <font class="comment">// Copy the good coordinate: those splitted (because of noise).</font> +02754 vert->Pos= vert->StartPos= vert->EndPos= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase->EndPos; +02755 <font class="comment">// But delete the pointer.</font> +02756 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessVertex(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase); +02757 <font class="comment">// And update sons pointers, to good vertex.</font> +02758 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->VBase= vert; +02759 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->VBase= vert; +02760 <font class="comment">// Compute correct centers.</font> +02761 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->computeSplitPoint(); +02762 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->computeSplitPoint(); +02763 +02764 +02765 <font class="comment">// Update good Far vertex pointer.</font> +02766 <font class="comment">//================================</font> +02767 <font class="comment">// Because *->VBase may have been merged to the multiple bind face, Near/FarVertices which pointed on it must</font> +02768 <font class="comment">// be setup.</font> +02769 <font class="comment">// We do not have to propagate this vertex ptr change since sons are leaves!!</font> +02770 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->isLeaf() && <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->isLeaf()); +02771 <font class="comment">// update pointers on vertex.</font> +02772 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->updateNearFarVertices(); +02773 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->updateNearFarVertices(); +02774 +02775 +02776 <font class="comment">// Bind FBase to a false face which indicate a bind 1/N.</font> +02777 <font class="comment">// This face prevent for "this" face to be merged...</font> +02778 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>= &<a class="code" href="classNL3D_1_1CTessFace.html#r0">CantMergeFace</a>; +02779 +02780 <font class="comment">// Therefore, the vertex will be never deleted (since face not merged).</font> +02781 <font class="comment">// The only way to do this, is to unbind the patch from all (then the vertex is cloned), then the merge will be Ok.</font> +02782 } +02783 <font class="comment">// Else if rectangular.</font> +02784 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(fmult0 || fmult1) +02785 { +02786 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *f; +02787 sint i; +02788 +02789 <font class="comment">// Same reasoning for rectangular patchs, as above.</font> +02790 <font class="keywordflow">for</font>(i=0;i<2;i++) +02791 { +02792 <font class="keywordflow">if</font>(i==0) +02793 f= f0, fmult= fmult0; +02794 <font class="keywordflow">else</font> +02795 f= f1, fmult= fmult1; +02796 <font class="keywordflow">if</font>(fmult) +02797 { +02798 <font class="comment">// Update good Face neighbors (when I am a rectangle).</font> +02799 <font class="comment">//============================</font> +02800 <font class="comment">// Consider the fmult face as a square face.</font> +02801 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *toLeft, *toRight; +02802 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *fl=f->SonLeft, *fr=f->SonRight; +02803 toLeft= fmult->SonLeft; +02804 toRight= fmult->SonRight; +02805 <font class="comment">// Cross connection of sons.</font> +02806 fl->FLeft= toLeft; +02807 fr->FLeft= toRight; +02808 toLeft->changeNeighbor(&CTessFace::MultipleBindFace, fl); +02809 toRight->changeNeighbor(&CTessFace::MultipleBindFace, fr); +02810 +02811 <font class="comment">// Update good vertex pointer.</font> +02812 <font class="comment">//============================</font> +02813 CTessVertex *vert= fmult->VBase; +02814 +02815 <font class="comment">// Copy the good coordinate: those splitted (because of noise).</font> +02816 <font class="comment">// NB: this work too with rectangular patch (see tesselation rules).</font> +02817 vert->Pos= vert->StartPos= vert->EndPos= fl->VBase->EndPos; +02818 <font class="comment">// But delete the pointer.</font> +02819 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->getLandscape()->deleteTessVertex(fl->VBase); +02820 <font class="comment">// And update sons pointers, to good vertex (rectangular case, see tesselation rules).</font> +02821 fl->VBase= vert; +02822 fr->VLeft= vert; +02823 f->FBase->SonLeft->VRight= vert; +02824 +02825 <font class="comment">// Point to a bind 1/N indicator.</font> +02826 f->FLeft= &<a class="code" href="classNL3D_1_1CTessFace.html#r0">CantMergeFace</a>; +02827 } +02828 } +02829 <font class="comment">// After all updates done. recompute centers of both sons 's faces, and update far vertices pointers.</font> +02830 <font class="keywordflow">for</font>(i=0;i<2;i++) +02831 { +02832 <font class="keywordflow">if</font>(i==0) +02833 f= f0; +02834 <font class="keywordflow">else</font> +02835 f= f1; +02836 <font class="comment">// Compute correct centers.</font> +02837 f->SonRight->computeSplitPoint(); +02838 f->SonLeft->computeSplitPoint(); +02839 +02840 <font class="comment">// Update good Far vertex pointer.</font> +02841 <font class="comment">//================================</font> +02842 <font class="comment">// Because *->VBase may have been merged to the multiple bind face, Near/FarVertices which pointed on it must</font> +02843 <font class="comment">// be setup.</font> +02844 <font class="comment">// We do not have to propagate this vertex ptr change, since sons are leaves!!</font> +02845 <a class="code" href="debug_8h.html#a6">nlassert</a>(f->SonLeft->isLeaf() && f->SonRight->isLeaf()); +02846 <font class="comment">// update pointers on vertex.</font> +02847 f->SonLeft->updateNearFarVertices(); +02848 f->SonRight->updateNearFarVertices(); +02849 } +02850 } +02851 } +02852 +02853 +02854 <font class="comment">// ***************************************************************************</font> +<a name="l02855"></a><a class="code" href="classNL3D_1_1CTessFace.html#a21">02855</a> <font class="keywordtype">void</font> CTessFace::updateBind() +02856 { +02857 <font class="comment">/*</font> +02858 <font class="comment"> Remind that updateBind() is called ONLY on the patch which is binded (not the neighbors).</font> +02859 <font class="comment"> Since updateBind() is called on the bintree, and that precedent propagated split may have occur, we may not</font> +02860 <font class="comment"> 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</font> +02861 <font class="comment"> sons).</font> +02862 <font class="comment"> Also, since we are splitted, and correctly linked (this may not be the case in updateBindAndSplit()), FBase IS</font> +02863 <font class="comment"> correct. His FBase neighbor and him form a diamond. So we don't need to update him.</font> +02864 <font class="comment"></font> +02865 <font class="comment"> Same remarks for rectangular patchs.</font> +02866 <font class="comment"> */</font> +02867 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02868 { +02869 <font class="keywordtype">bool</font> splitWanted= <font class="keyword">false</font>; +02870 <font class="keywordflow">while</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a20">updateBindEdge</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>, splitWanted)); +02871 <font class="comment">// FLeft and FRight pointers are only valid in Leaves nodes.</font> +02872 <font class="keywordflow">while</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a20">updateBindEdge</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>, splitWanted)); +02873 <font class="keywordflow">while</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a20">updateBindEdge</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>, splitWanted)); +02874 <font class="keywordflow">if</font>(splitWanted) +02875 <a class="code" href="classNL3D_1_1CTessFace.html#a22">updateBindAndSplit</a>(); +02876 } +02877 +02878 +02879 <font class="comment">// Recurse to sons.</font> +02880 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02881 { +02882 <font class="comment">// Update bind of sons.</font> +02883 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->updateBind(); +02884 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->updateBind(); +02885 } +02886 } +02887 +02888 <font class="comment">// ***************************************************************************</font> +02889 <font class="keyword">static</font> <font class="keyword">inline</font> <font class="keywordtype">bool</font> <a class="code" href="namespaceNL3D.html#a462">matchEdge</a>(<font class="keyword">const</font> CVector2f &uv0, <font class="keyword">const</font> CVector2f &uv1, <font class="keyword">const</font> CVector2f &uva, <font class="keyword">const</font> CVector2f &uvb) +02890 { +02891 <font class="keywordflow">if</font>(uv0==uva && uv1==uvb) +02892 <font class="keywordflow">return</font> <font class="keyword">true</font>; +02893 <font class="keywordflow">if</font>(uv0==uvb && uv1==uva) +02894 <font class="keywordflow">return</font> <font class="keyword">true</font>; +02895 <font class="keywordflow">return</font> <font class="keyword">false</font>; +02896 } +02897 +02898 <font class="comment">// ***************************************************************************</font> +<a name="l02899"></a><a class="code" href="classNL3D_1_1CTessFace.html#a19">02899</a> CTessFace *CTessFace::linkTessFaceWithEdge(<font class="keyword">const</font> CVector2f &uv0, <font class="keyword">const</font> CVector2f &uv1, CTessFace *linkTo) +02900 { +02901 <font class="comment">// Compute 0,1 coords of 3 patch coords.</font> +02902 CVector2f vb( <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>.getT() ); +02903 CVector2f vl( <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>.getT() ); +02904 CVector2f vr( <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>.getT() ); +02905 +02906 <font class="comment">// Search if one of the 3 edges of this triangle match the wanted edge.</font> +02907 <font class="comment">// Base Edge</font> +02908 <font class="keywordflow">if</font>(<a class="code" href="namespaceNL3D.html#a462">matchEdge</a>(uv0, uv1, vl, vr)) +02909 { +02910 <font class="comment">// If leaf, check if unbound (else ptr is invalid)</font> +02911 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>==NULL || !<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +02912 <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>= linkTo; +02913 <font class="keywordflow">return</font> <font class="keyword">this</font>; +02914 } +02915 <font class="comment">// Left Edge</font> +02916 <font class="keywordflow">if</font>(<a class="code" href="namespaceNL3D.html#a462">matchEdge</a>(uv0, uv1, vb, vl)) +02917 { +02918 <font class="comment">// If leaf, check if unbound (else ptr is invalid)</font> +02919 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>==NULL || !<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()); +02920 <a class="code" href="classNL3D_1_1CTessFace.html#z819_5">FLeft</a>= linkTo; +02921 <font class="keywordflow">return</font> <font class="keyword">this</font>; +02922 } +02923 <font class="comment">// Right Edge</font> +02924 <font class="keywordflow">if</font>(<a class="code" href="namespaceNL3D.html#a462">matchEdge</a>(uv0, uv1, vb, vr)) +02925 { +02926 <font class="comment">// If leaf, check if unbound (else ptr is invalid)</font> +02927 <a class="code" href="debug_8h.html#a6">nlassert</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>==NULL || !<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02928 <a class="code" href="classNL3D_1_1CTessFace.html#z819_6">FRight</a>= linkTo; +02929 <font class="keywordflow">return</font> <font class="keyword">this</font>; +02930 } +02931 +02932 +02933 <font class="comment">// If not found here, recurs to children</font> +02934 <a class="code" href="classNL3D_1_1CTessFace.html#a0">CTessFace</a> *ret= NULL; +02935 <font class="keywordflow">if</font>( !<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>() ) +02936 { +02937 ret= <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->linkTessFaceWithEdge(uv0, uv1, linkTo); +02938 <font class="comment">// if no found in this branch, recusr right branch.</font> +02939 <font class="keywordflow">if</font>(!ret) +02940 ret= <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->linkTessFaceWithEdge(uv0, uv1, linkTo); +02941 } +02942 +02943 <font class="comment">// return the result from subBranchs</font> +02944 <font class="keywordflow">return</font> ret; +02945 } +02946 +02947 +02948 <font class="comment">// ***************************************************************************</font> +<a name="l02949"></a><a class="code" href="classNL3D_1_1CTessFace.html#a3">02949</a> <font class="keywordtype">bool</font> CTessFace::isRectangular()<font class="keyword"> const</font> +02950 <font class="keyword"></font>{ +02951 <font class="keywordflow">return</font> <a class="code" href="classNL3D_1_1CTessFace.html#z819_13">Level</a><<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->SquareLimitLevel; +02952 } +02953 +02954 +02955 +02956 <font class="comment">// ***************************************************************************</font> +02957 <font class="comment">// ***************************************************************************</font> +02958 <font class="comment">// For changePatchTexture.</font> +02959 <font class="comment">// ***************************************************************************</font> +02960 <font class="comment">// ***************************************************************************</font> +02961 +02962 +02963 <font class="comment">// ***************************************************************************</font> +<a name="l02964"></a><a class="code" href="classNL3D_1_1CTessFace.html#a26">02964</a> <font class="keywordtype">void</font> CTessFace::deleteTileUvs() +02965 { +02966 <font class="comment">// NB: NearVertices are removed from renderlist with deleteTileUv (called in releaseTileMaterial()).</font> +02967 +02968 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +02969 { +02970 <font class="comment">// Must delete the materials of leaves first.</font> +02971 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->deleteTileUvs(); +02972 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->deleteTileUvs(); +02973 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level== <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +02974 { +02975 <font class="comment">// Square patch assumption: the sons are not of the same TileId/Patch.</font> +02976 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#f0">sameTile</a>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>)); +02977 <font class="comment">// release tiles.</font> +02978 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->releaseTileMaterial(); +02979 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->releaseTileMaterial(); +02980 } +02981 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level > <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +02982 { +02983 <a class="code" href="debug_8h.html#a6">nlassert</a>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> || !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf()); +02984 +02985 <font class="comment">// Delete Uv, only if not already done by the neighbor (ie neighbor has yet TileFaces!!).</font> +02986 <font class="comment">// But Always delete if neighbor exist and has not same tile as me.</font> +02987 <font class="comment">// NB: this work with rectangular neigbor patch, since sameTile() will return false if different patch.</font> +02988 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a> || !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->emptyTileFaces() || !<a class="code" href="classNL3D_1_1CTessFace.html#f0">sameTile</a>(<font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>)) +02989 { +02990 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->deleteTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +02991 } +02992 <font class="comment">// In all case, must delete the tilefaces of those face.</font> +02993 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->deleteTileFaces(); +02994 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->deleteTileFaces(); +02995 <font class="comment">// For createTileUvs, it is important to mark those faces as NO TileMaterial.</font> +02996 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->TileMaterial= NULL; +02997 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->TileMaterial= NULL; +02998 } +02999 } +03000 <font class="keywordflow">else</font> +03001 { +03002 <font class="comment">// NB: this is done always BELOW tile creation (see above).</font> +03003 <font class="comment">// Do this only for tiles.</font> +03004 <font class="keywordflow">if</font>(TileMaterial) +03005 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->removeFaceFromTileRenderList(<font class="keyword">this</font>); +03006 } +03007 +03008 } +03009 +03010 +03011 <font class="comment">// ***************************************************************************</font> +<a name="l03012"></a><a class="code" href="classNL3D_1_1CTessFace.html#a27">03012</a> <font class="keywordtype">void</font> CTessFace::recreateTileUvs() +03013 { +03014 <font class="comment">// NB: NearVertices are append to renderlist with allocTileUv (called in computeTileMaterial()/heritTileMaterial()).</font> +03015 +03016 <font class="keywordflow">if</font>(!<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +03017 { +03018 <font class="comment">// Must recreate the materials of parent first.</font> +03019 +03020 <font class="comment">// There is no problem with rectangular patch, since tiles are always squares.</font> +03021 <font class="comment">// If new tile ....</font> +03022 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level==<a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +03023 { +03024 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->computeTileMaterial(); +03025 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->computeTileMaterial(); +03026 } +03027 <font class="comment">// else Tile herit.</font> +03028 <font class="keywordflow">else</font> <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->Level > <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->TileLimitLevel) +03029 { +03030 <a class="code" href="classNL3D_1_1CTessFace.html#c5">heritTileMaterial</a>(); +03031 } +03032 +03033 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->recreateTileUvs(); +03034 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->recreateTileUvs(); +03035 } +03036 <font class="keywordflow">else</font> +03037 { +03038 <font class="comment">// NB: this is done always AFTER tile creation (see above).</font> +03039 <font class="comment">// Do this only for tiles.</font> +03040 <font class="keywordflow">if</font>(TileMaterial) +03041 <a class="code" href="classNL3D_1_1CTessFace.html#z819_0">Patch</a>->appendFaceToTileRenderList(<font class="keyword">this</font>); +03042 } +03043 } +03044 +03045 +03046 +03047 <font class="comment">// ***************************************************************************</font> +<a name="l03048"></a><a class="code" href="classNL3D_1_1CTessFace.html#c5">03048</a> <font class="keywordtype">void</font> CTessFace::heritTileMaterial() +03049 { +03050 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->TileMaterial= <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>; +03051 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->TileId= <a class="code" href="classNL3D_1_1CTessFace.html#z820_1">TileId</a>; +03052 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->buildTileFaces(); +03053 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->copyTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>, <font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +03054 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->copyTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>, <font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>); +03055 +03056 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->TileMaterial= <a class="code" href="classNL3D_1_1CTessFace.html#z820_2">TileMaterial</a>; +03057 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->TileId= <a class="code" href="classNL3D_1_1CTessFace.html#z820_1">TileId</a>; +03058 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->buildTileFaces(); +03059 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->copyTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s1">IdUvLeft</a>, <font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>); +03060 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->copyTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s2">IdUvRight</a>, <font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +03061 +03062 <font class="comment">// Create, or link to the tileUv.</font> +03063 <font class="comment">// Try to link to a neighbor TileUv.</font> +03064 <font class="comment">// Can only work iff exist, and iff FBase is same patch, and same TileId.</font> +03065 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>!=NULL && !<a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->isLeaf() && <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft->TileMaterial!=NULL && <a class="code" href="classNL3D_1_1CTessFace.html#f0">sameTile</a>(<font class="keyword">this</font>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>) ) +03066 { +03067 <font class="comment">// Ok!! link to the (existing) TileUv.</font> +03068 <font class="comment">// FBase->SonLeft!=NULL since FBase->isLeaf()==false.</font> +03069 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->copyTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +03070 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->copyTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_4">FBase</a>->SonLeft, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +03071 } +03072 <font class="keywordflow">else</font> +03073 { +03074 <font class="comment">// Allocate a new vertex, and copy it to SonLeft and SonRight.</font> +03075 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->allocTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +03076 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->copyTileUv(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>, <a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +03077 +03078 <font class="comment">// Fill the new near vertex, with middle of Left/Right father.</font> +03079 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->heritTileUv(<font class="keyword">this</font>); +03080 +03081 <font class="comment">// UVs are computed, may create and fill VB.</font> +03082 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->checkCreateFillTileVB(<a class="code" href="classNL3D_1_1CTessFace.html#z820_0s0">IdUvBase</a>); +03083 } +03084 +03085 } +03086 +03087 +03088 <font class="comment">// ***************************************************************************</font> +03089 <font class="comment">// ***************************************************************************</font> +03090 <font class="comment">// For getTesselatedPos</font> +03091 <font class="comment">// ***************************************************************************</font> +03092 <font class="comment">// ***************************************************************************</font> +03093 +03094 +03095 <font class="comment">// ***************************************************************************</font> +<a name="l03096"></a><a class="code" href="classNL3D_1_1CTessFace.html#a28">03096</a> <font class="keywordtype">void</font> CTessFace::getTesselatedPos(<font class="keyword">const</font> CUV &uv, <font class="keywordtype">bool</font> verifInclusion, CVector &ret) +03097 { +03098 CVector uvPos(uv.U, uv.V, 0); +03099 +03100 <font class="comment">// may verif if uv is In this triangle. supposed true if rectangular branch.</font> +03101 <font class="keywordflow">if</font>(verifInclusion && !(<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>() && !<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) ) +03102 { +03103 CVector uvs[3]; +03104 uvs[0].set( <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>.getT(), 0); +03105 uvs[1].set( <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>.getT(), 0); +03106 uvs[2].set( <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>.getT(), 0); +03107 <font class="keywordflow">for</font>(sint i=0; i<3; i++) +03108 { +03109 CVector dUv= uvs[(i+1)%3] - uvs[i]; +03110 CVector normalUv(dUv.y, -dUv.x, 0); +03111 <font class="comment">// if out this 2D plane, uv is out this triangle</font> +03112 <font class="keywordflow">if</font>(normalUv * (uvPos-uvs[i]) <0) +03113 <font class="keywordflow">return</font>; +03114 } +03115 } +03116 +03117 <font class="comment">// compute tesselated pos in this face.</font> +03118 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +03119 <font class="comment">// ok, no more sons, let's do it.</font> +03120 <a class="code" href="classNL3D_1_1CTessFace.html#c10">computeTesselatedPos</a>(uv, ret); +03121 <font class="keywordflow">else</font> +03122 { +03123 <font class="comment">// must subdivide.</font> +03124 <font class="comment">// if we are rectangular (strange tesselation), must test in both leaves, else, choose only one.</font> +03125 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a3">isRectangular</a>()) +03126 { +03127 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->getTesselatedPos(uv, <font class="keyword">true</font>, ret); +03128 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->getTesselatedPos(uv, <font class="keyword">true</font>, ret); +03129 } +03130 <font class="keywordflow">else</font> +03131 { +03132 <font class="comment">// Compute the uv plane which separate the 2 leaves.</font> +03133 CVector uvBase, uvMiddle; +03134 uvBase.set ( <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>.getT(), 0); +03135 uvMiddle.set( <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->PVBase.getT(), 0); +03136 CVector dUv= uvMiddle - uvBase; +03137 CVector normalUv(dUv.y, -dUv.x, 0); +03138 <font class="comment">// choose what leaf to recurs.</font> +03139 <font class="keywordflow">if</font>(normalUv * (uvPos - uvBase) <0) +03140 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->getTesselatedPos(uv, <font class="keyword">false</font>, ret); +03141 <font class="keywordflow">else</font> +03142 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->getTesselatedPos(uv, <font class="keyword">false</font>, ret); +03143 +03144 } +03145 } +03146 +03147 } +03148 +03149 +03150 <font class="comment">// ***************************************************************************</font> +<a name="l03151"></a><a class="code" href="classNL3D_1_1CTessFace.html#c10">03151</a> <font class="keywordtype">void</font> CTessFace::computeTesselatedPos(<font class="keyword">const</font> CUV &uv, CVector &ret) +03152 { +03153 CVector uvPos(uv.U, uv.V, 0); +03154 +03155 <font class="comment">// compute the UV triangle of this face.</font> +03156 CTriangle uvTri; +03157 uvTri.V0.set( <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_10">PVBase</a>.getT(), 0); +03158 uvTri.V1.set( <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_11">PVLeft</a>.getT(), 0); +03159 uvTri.V2.set( <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>.getS(), <a class="code" href="classNL3D_1_1CTessFace.html#z819_12">PVRight</a>.getT(), 0); +03160 +03161 <font class="comment">// must interpolate the position with given UV, so compute XYZ gradients.</font> +03162 CVector Gx; +03163 CVector Gy; +03164 CVector Gz; +03165 <font class="comment">// If VertexProgram activated</font> +03166 <font class="keywordflow">if</font>( CLandscapeGlobals::VertexProgramEnabled ) +03167 { +03168 <font class="comment">// then Must update geomorphed position because not done !!</font> +03169 <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->computeGeomPos(); +03170 <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->computeGeomPos(); +03171 <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->computeGeomPos(); +03172 } +03173 <font class="comment">// NB: take geomorphed position.</font> +03174 uvTri.computeGradient(<a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->Pos.x, <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->Pos.x, <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->Pos.x, Gx); +03175 uvTri.computeGradient(<a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->Pos.y, <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->Pos.y, <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->Pos.y, Gy); +03176 uvTri.computeGradient(<a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->Pos.z, <a class="code" href="classNL3D_1_1CTessFace.html#z819_2">VLeft</a>->Pos.z, <a class="code" href="classNL3D_1_1CTessFace.html#z819_3">VRight</a>->Pos.z, Gz); +03177 +03178 <font class="comment">// Compute interpolated position.</font> +03179 ret= <a class="code" href="classNL3D_1_1CTessFace.html#z819_1">VBase</a>->Pos; +03180 uvPos-= uvTri.V0; +03181 ret.x+= Gx*uvPos; +03182 ret.y+= Gy*uvPos; +03183 ret.z+= Gz*uvPos; +03184 +03185 } +03186 +03187 +03188 <font class="comment">// ***************************************************************************</font> +<a name="l03189"></a><a class="code" href="classNL3D_1_1CTessFace.html#a29">03189</a> <font class="keywordtype">void</font> CTessFace::appendTessellationLeaves(std::vector<const CTessFace*> &leaves)<font class="keyword"> const</font> +03190 <font class="keyword"></font>{ +03191 <font class="keywordflow">if</font>(<a class="code" href="classNL3D_1_1CTessFace.html#a2">isLeaf</a>()) +03192 leaves.push_back(<font class="keyword">this</font>); +03193 <font class="keywordflow">else</font> +03194 { +03195 <a class="code" href="classNL3D_1_1CTessFace.html#z819_8">SonLeft</a>->appendTessellationLeaves(leaves); +03196 <a class="code" href="classNL3D_1_1CTessFace.html#z819_9">SonRight</a>->appendTessellationLeaves(leaves); +03197 } +03198 } +03199 +03200 +03201 } <font class="comment">// NL3D</font> +</pre></div> + +<!-- footer --> +<BR><FONT Size=+5> </FONT> +</TD> +<TD WIDTH=15><IMG SRC=http://www.nevrax.org/inc/img/pixel.gif WIDTH=15 HEIGHT=15 BORDER=0 ALT=""></TD> +</TR> +</TABLE> +</BODY> +</HTML> |