From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/patch__noise_8cpp-source.html | 1037 ++++++++++++++++++++++++ 1 file changed, 1037 insertions(+) create mode 100644 docs/doxygen/nel/patch__noise_8cpp-source.html (limited to 'docs/doxygen/nel/patch__noise_8cpp-source.html') diff --git a/docs/doxygen/nel/patch__noise_8cpp-source.html b/docs/doxygen/nel/patch__noise_8cpp-source.html new file mode 100644 index 00000000..80a4d798 --- /dev/null +++ b/docs/doxygen/nel/patch__noise_8cpp-source.html @@ -0,0 +1,1037 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

patch_noise.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 #include "std3d.h"
+00027 
+00028 
+00029 #include "3d/patch.h"
+00030 #include "3d/tessellation.h"
+00031 #include "3d/bezier_patch.h"
+00032 #include "3d/zone.h"
+00033 #include "3d/landscape.h"
+00034 #include "nel/misc/vector.h"
+00035 #include "nel/misc/common.h"
+00036 #include "3d/tile_noise_map.h"
+00037 #include "3d/patchuv_locator.h"
+00038 using   namespace       std;
+00039 using   namespace       NLMISC;
+00040 
+00041 
+00042 namespace NL3D 
+00043 {
+00044 
+00045 
+00046 // ***************************************************************************
+00047 
+00048 
+00049 #ifdef NL_OS_WINDOWS
+00050 
+00051 /* This floor works only for floor with noise, because floor/ceil are only made on decimal coordinates:
+00052         sTile =1.25 ....  NB: because of difference of mapping (rare case), we may have sometimes values with
+00053         precision < 1/4 (eg 1.125). Just use f*256 to compute the floor.
+00054 
+00055   NB: using a fastFloor() (fistp changing the controlfp() is not very a good idea here, because 
+00056   computeNoise() are not "packed", so change on controlFp() would bee to frequent... 
+00057   And also because we need either floor() or ceil() here.
+00058 */
+00059 inline  sint noiseFloor(float f)
+00060 {
+00061         // build a fixed 24:8.
+00062         sint    a;
+00063         f*=256;
+00064 
+00065         // fast ftol. work if no decimal.
+00066         _asm
+00067         {
+00068                 fld f
+00069                 fistp a
+00070         }
+00071 
+00072         // floor.
+00073         a>>=8;
+00074 
+00075         return a;
+00076 }
+00077 
+00078 
+00079 inline  sint noiseCeil(float f)
+00080 {
+00081         // build a fixed 24:8.
+00082         sint    a;
+00083         f*=256;
+00084 
+00085         // fast ftol. work if no decimal.
+00086         _asm
+00087         {
+00088                 fld f
+00089                 fistp a
+00090         }
+00091 
+00092         // ceil.
+00093         a+=255;
+00094         a>>=8;
+00095 
+00096         return a;
+00097 }
+00098 
+00099 
+00100 inline  float noiseFloorF(float f)
+00101 {
+00102         return (float)noiseFloor(f);
+00103 }
+00104 inline  float noiseCeilF(float f)
+00105 {
+00106         return (float)noiseCeil(f);
+00107 }
+00108 
+00109 
+00110 #else
+00111 
+00112 
+00113 inline  float noiseFloorF(float f)
+00114 {
+00115         return (float)floor(f);
+00116 }
+00117 inline  float noiseCeilF(float f)
+00118 {
+00119         return (float)ceil(f);
+00120 }
+00121 
+00122 inline  sint noiseFloor(float f)
+00123 {
+00124         return (sint)floor(f);
+00125 }
+00126 inline  sint noiseCeil(float f)
+00127 {
+00128         return (sint)ceil(f);
+00129 }
+00130 
+00131 #endif
+00132 
+00133 
+00134 
+00135 // ***************************************************************************
+00136 float           CPatch::computeDisplaceRawInteger(sint ts, sint tt, sint ms, sint mt) const
+00137 {
+00138         // Choose the noiseMap.
+00139         // ===============================
+00140         clamp(ts, 0, OrderS-1);
+00141         clamp(tt, 0, OrderT-1);
+00142 
+00143         uint    tileId= tt*OrderS + ts;
+00144         // Get the tile for pass0. This is the principal tile, and this one tells what noise to take.
+00145         sint    tileNumber= Tiles[tileId].Tile[0];
+00146         // Get the subNoise from tileElement.
+00147         uint    tileSubNoise= Tiles[tileId].getTileSubNoise();
+00148 
+00149         // retrieve the wanted noiseMap.
+00150         CTileNoiseMap   *noiseMap;
+00151         noiseMap = getZone()->getLandscape()->TileBank.getTileNoiseMap (tileNumber, tileSubNoise);
+00152 
+00153 
+00154         // Sample the noiseMap with (s,t).
+00155         // ===============================
+00156 
+00157         // sample from map.
+00158         sint8   pix= noiseMap->Pixels[mt*NL3D_TILE_NOISE_MAP_SIZE + ms];
+00159 
+00160         // normalize.
+00161         return  (float)pix * (NL3D_NOISE_MAX / 127.f);
+00162 }
+00163 
+00164 
+00165 // ***************************************************************************
+00166 void            CPatch::computeDisplaceRawCoordinates(float sTile, float tTile, float s, float t,
+00167         sint &ts, sint &tt, sint &ms, sint &mt) const
+00168 {
+00169         // Choose the noiseMap.
+00170         // ===============================
+00171         // Compute coordinate in the patch.
+00172         ts= noiseFloor(sTile);
+00173         tt= noiseFloor(tTile);
+00174 
+00175 
+00176         // Sample the noiseMap with (s,t).
+00177         // ===============================
+00178 
+00179         // scale the map.
+00180         float   u= s * NL3D_TILE_NOISE_MAP_TILE_FACTOR;
+00181         float   v= t * NL3D_TILE_NOISE_MAP_TILE_FACTOR;
+00182 
+00183         // Speed rotation.
+00184         CUV             uv;
+00185         switch(NoiseRotation & 3)
+00186         {
+00187                 case 0: 
+00188                         uv.U= u;
+00189                         uv.V= v;
+00190                         break;
+00191                 case 1: 
+00192                         uv.U= NL3D_TILE_NOISE_MAP_SIZE-v;
+00193                         uv.V= u;
+00194                         break;
+00195                 case 2: 
+00196                         uv.U= NL3D_TILE_NOISE_MAP_SIZE-u;
+00197                         uv.V= NL3D_TILE_NOISE_MAP_SIZE-v;
+00198                         break;
+00199                 case 3: 
+00200                         uv.U= v;
+00201                         uv.V= NL3D_TILE_NOISE_MAP_SIZE-u;
+00202                         break;
+00203         }
+00204 
+00205         // direct map (no bilinear, no round, the case where s,t < 1/4 of a tile is very rare).
+00206         ms= noiseFloor(uv.U);
+00207         mt= noiseFloor(uv.V);
+00208 
+00209         // Manage Tiling (add NL3D_TILE_NOISE_MAP_SIZE*1 should be sufficient, but take margin).
+00210         ms= (ms + (NL3D_TILE_NOISE_MAP_SIZE*256)) & (NL3D_TILE_NOISE_MAP_SIZE-1);
+00211         mt= (mt + (NL3D_TILE_NOISE_MAP_SIZE*256)) & (NL3D_TILE_NOISE_MAP_SIZE-1);
+00212 }
+00213 
+00214 
+00215 
+00216 // ***************************************************************************
+00217 float           CPatch::computeDisplaceRaw(float sTile, float tTile, float s, float t) const
+00218 {
+00219         sint    ts,tt,ms,mt;
+00220         computeDisplaceRawCoordinates(sTile, tTile, s, t, ts, tt, ms, mt);
+00221         return computeDisplaceRawInteger(ts, tt, ms, mt);
+00222 
+00223 }
+00224 
+00225 // ***************************************************************************
+00226 static inline   void    computeDisplaceBilinear(float sTile, float tTile, 
+00227         float &sInc, float &tInc, float &sa, float &ta, float &sa1, float &ta1)
+00228 {
+00229         float   sDecimal= sTile-noiseFloor(sTile);
+00230         float   tDecimal= tTile-noiseFloor(tTile);
+00231         float   sDist, tDist;
+00232 
+00233         // Do a bilinear centered on 0.5, 0.5.
+00234 
+00235         // Compute increment, according to position against center.
+00236         if(sDecimal>=0.5)
+00237                 sInc= 1;
+00238         else
+00239                 sInc= -1;
+00240         if(tDecimal>=0.5)
+00241                 tInc= 1;
+00242         else
+00243                 tInc= -1;
+00244 
+00245         // Compute weight factor.
+00246         sDist= (float)fabs(0.5 - sDecimal);     // s distance from center.
+00247         tDist= (float)fabs(0.5 - tDecimal);     // t distance from center.
+00248         sa= 1-sDist;
+00249         ta= 1-tDist;
+00250         sa1= 1-sa;
+00251         ta1= 1-ta;
+00252 }
+00253 
+00254 
+00255 // ***************************************************************************
+00256 float           CPatch::computeDisplaceInteriorSmooth(float s, float t) const
+00257 {
+00258         float sTile= s;
+00259         float tTile= t;
+00260         float   ret;
+00261 
+00262         // compute bi-linear weight factors.
+00263         float   sInc, tInc, sa, ta, sa1, ta1;
+00264         computeDisplaceBilinear(sTile, tTile, sInc, tInc, sa, ta, sa1, ta1);
+00265 
+00266 
+00267         // NB: to have smooth transition, must keep the same (s,t), so we do a transition with the noise tile of 
+00268         // our neigbhor, but under us.
+00269 
+00270         // speed up, using just one computeDisplaceRawCoordinates(), and multiple computeDisplaceRawInteger().
+00271         sint    ts,tt,ms,mt;
+00272         computeDisplaceRawCoordinates(sTile, tTile, s, t, ts, tt, ms, mt);
+00273 
+00274         sint    sIncInt= (sint) sInc;
+00275         sint    tIncInt= (sint) tInc;
+00276         ret = computeDisplaceRawInteger(ts, tt, ms,mt) * sa * ta;
+00277         ret+= computeDisplaceRawInteger(ts+sIncInt, tt, ms,mt) * sa1 * ta;
+00278         ret+= computeDisplaceRawInteger(ts, tt+tIncInt, ms,mt) * sa * ta1;
+00279         ret+= computeDisplaceRawInteger(ts+sIncInt, tt+tIncInt, ms,mt) * sa1 * ta1;
+00280 
+00281         return ret;
+00282 }
+00283 
+00284 
+00285 // ***************************************************************************
+00286 float           CPatch::computeDisplaceEdgeSmooth(float s, float t, sint8 smoothBorderX, sint8 smoothBorderY) const
+00287 {
+00288         float sTile= s;
+00289         float tTile= t;
+00290         CBindInfo       bindInfo;
+00291         uint            edge=0;
+00292 
+00293         // only one must be not null
+00294         nlassert( (smoothBorderX==0) != (smoothBorderY==0) );
+00295 
+00296 
+00297         // Get the edge against we must share displace.
+00298         if(smoothBorderX==-1)   edge=0;
+00299         else if(smoothBorderY==1)       edge=1;
+00300         else if(smoothBorderX==1)       edge=2;
+00301         else if(smoothBorderY==-1)      edge=3;
+00302         else nlstop;
+00303 
+00304         // Build the bindInfo against this edge.
+00305         getBindNeighbor(edge, bindInfo);
+00306 
+00307         // Fast reject: if no neighbor, just do a simple computeDisplaceInteriorSmooth.
+00308         if(!bindInfo.Zone)
+00309                 return computeDisplaceInteriorSmooth(s, t);
+00310         // else, look for result in neighborhood.
+00311         else
+00312         {
+00313                 float   ret;
+00314 
+00315 
+00316                 // compute bi-linear weight factors.
+00317                 float   sInc, tInc, sa, ta, sa1, ta1;
+00318                 computeDisplaceBilinear(sTile, tTile, sInc, tInc, sa, ta, sa1, ta1);
+00319                 // Manage limit case: if bilinear has not chosen the good direction (because of floor and orientation).
+00320                 // eg on Right edge: This case arise if sDecimal==0, so if sa==sa1==0.5f. result is that
+00321                 // smoothBorderX is != than sInc on right border. same reasoning with downBorder (smoothBorderY=1).
+00322 
+00323                 // NO NEED TO DO HERE, because sInc or tInc is not used if it is bad (smoothBorder? used instead).
+00324                 // and no need to correct sa, sa1, because in this case they are both equal to 0.5.
+00325 
+00326 
+00327                 // compute Neighboring info.
+00328                 CPatchUVLocator         uvLocator;
+00329                 uvLocator.build(this, edge, bindInfo);
+00330 
+00331                 /* NB: there is floor problems with neighbors:
+00332                         - difference of orientation => uv.v=1. This point to the 1th tile. But this is not the same, if
+00333                                 v goes to up, or goes to down.
+00334                         - if multiple bind, problem at limit (eg a bind 1/2 on edge 0 with OrdertT=8, when uv.v= 4).
+00335                                 because, selection of the patch is dependent of orientation too.
+00336                         To avoid them, just take center of (sTile, tTile) to remove ambiguity.
+00337                         This works because computeDisplaceRaw() use sTile, tTile to get the noiseMap, so the decimal part is not 
+00338                         used.
+00339 
+00340                         Notice that we do this AFTER computeDisplaceBilinear() of course.
+00341                 */
+00342                 sTile= noiseFloor(sTile) + 0.5f;
+00343                 tTile= noiseFloor(tTile) + 0.5f;
+00344                 // If we were exactly on the superior edge, prec compute is false... so correct this here.
+00345                 if(sTile>OrderS) sTile--;
+00346                 if(tTile>OrderT) tTile--;
+00347 
+00348 
+00349                 // Bilinear across an edge (enjoy!!).
+00350                 CVector2f       stTileIn, stIn;
+00351                 CVector2f       stTileOut, stOut;
+00352                 CPatch          *patchOut;
+00353                 uint            patchId;
+00354 
+00355 
+00356                 // if vertical edge.
+00357                 if(smoothBorderX!=0)
+00358                 {
+00359                         // compute contribution of our patch.
+00360                         ret = computeDisplaceRaw(sTile,tTile, s,t) * sa * ta;
+00361                         ret+= computeDisplaceRaw(sTile,tTile+tInc, s,t) * sa * ta1;
+00362 
+00363                         // compute contribution of next(s) patchs.
+00364 
+00365                         // contribution of next at tTile.
+00366                         // Keep the same coordinate.
+00367                         stIn.set(s, t);
+00368                         // But look for the neighbor noise tile.
+00369                         stTileIn.set(sTile+smoothBorderX, tTile);
+00370                         // change basis: find the s,t on the neighbor patch.
+00371                         patchId= uvLocator.selectPatch(stTileIn);
+00372                         uvLocator.locateUV(stTileIn, patchId, patchOut, stTileOut);
+00373                         uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00374                         // Compute displace, and bi-linear on the neighbor patch.
+00375                         ret+= patchOut->computeDisplaceRaw(stTileOut.x, stTileOut.y, stOut.x, stOut.y) * sa1 * ta;
+00376 
+00377                         // contribution of next at tTile+tInc (same reasoning).
+00378                         stIn.set(s, t);
+00379                         stTileIn.set(sTile+smoothBorderX, tTile+tInc);
+00380                         patchId= uvLocator.selectPatch(stTileIn);
+00381                         uvLocator.locateUV(stTileIn, patchId, patchOut, stTileOut);
+00382                         uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00383                         ret+= patchOut->computeDisplaceRaw(stTileOut.x, stTileOut.y, stOut.x, stOut.y) * sa1 * ta1;
+00384 
+00385                 }
+00386                 // else if horizontal edge.
+00387                 else
+00388                 {
+00389                         // same reasoning as above.
+00390 
+00391                         // compute contribution of our patch.
+00392                         ret = computeDisplaceRaw(sTile, tTile, s,t) * sa * ta;
+00393                         ret+= computeDisplaceRaw(sTile+sInc,tTile, s,t) * sa1 * ta;
+00394 
+00395                         // compute contribution of next(s) patchs.
+00396                         // contribution of next at tTile.
+00397                         stIn.set(s, t);
+00398                         stTileIn.set(sTile, tTile+smoothBorderY);
+00399                         patchId= uvLocator.selectPatch(stTileIn);
+00400                         uvLocator.locateUV(stTileIn, patchId, patchOut, stTileOut);
+00401                         uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00402                         ret+= patchOut->computeDisplaceRaw(stTileOut.x, stTileOut.y, stOut.x, stOut.y) * sa * ta1;
+00403 
+00404                         // contribution of next at tTile+tInc (same reasoning).
+00405                         stIn.set(s, t);
+00406                         stTileIn.set(sTile+sInc, tTile+smoothBorderY);
+00407                         patchId= uvLocator.selectPatch(stTileIn);
+00408                         uvLocator.locateUV(stTileIn, patchId, patchOut, stTileOut);
+00409                         uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00410                         ret+= patchOut->computeDisplaceRaw(stTileOut.x, stTileOut.y, stOut.x, stOut.y) * sa1 * ta1;
+00411                 }
+00412 
+00413                 return ret;
+00414         }
+00415 
+00416 }
+00417 
+00418 
+00419 // ***************************************************************************
+00420 float           CPatch::computeDisplaceRawOnNeighbor(float sTile, float tTile, float s, float t) const
+00421 {
+00422         sint    edge= -1;
+00423 
+00424         // look on what neighbor patch we must find the value (if any).
+00425         if(sTile<0)     edge=0;
+00426         else if(tTile>OrderT)   edge=1;
+00427         else if(sTile>OrderS)   edge=2;
+00428         else if(tTile<0)                edge=3;
+00429 
+00430         // If the location is In the patch, just return normal value.
+00431         if(edge==-1)
+00432                 return computeDisplaceRaw(sTile, tTile, s, t);
+00433         // else must find on neighbor.
+00434         else
+00435         {
+00436                 CBindInfo       bindInfo;
+00437                 getBindNeighbor(edge, bindInfo);
+00438 
+00439                 // Fast reject: if no neighbor on the edge, just do a simple computeDisplaceRaw()
+00440                 if(!bindInfo.Zone)
+00441                 {
+00442                         return computeDisplaceRaw(sTile, tTile, s, t);
+00443                 }
+00444                 // else must find on neighbor.
+00445                 else
+00446                 {
+00447                         CPatchUVLocator         uvLocator;
+00448                         uvLocator.build(this, edge, bindInfo);
+00449 
+00450                         CVector2f       stTileIn, stIn;
+00451                         CVector2f       stTileOut, stOut;
+00452                         CPatch          *patchOut;
+00453                         uint            patchId;
+00454 
+00455                         // look on neighbor. same reasoning as in computeDisplaceEdgeSmooth();
+00456                         stIn.set(s, t);
+00457                         stTileIn.set(sTile, tTile);
+00458                         patchId= uvLocator.selectPatch(stTileIn);
+00459                         uvLocator.locateUV(stTileIn, patchId, patchOut, stTileOut);
+00460                         uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00461                         return patchOut->computeDisplaceRaw(stTileOut.x, stTileOut.y, stOut.x, stOut.y);
+00462                 }
+00463 
+00464         }
+00465 }
+00466 
+00467 
+00468 // ***************************************************************************
+00469 float           CPatch::computeDisplaceCornerSmooth(float s, float t, sint8 smoothBorderX, sint8 smoothBorderY) const
+00470 {
+00471         // compute the value across the corner (enjoy!!)
+00472         // NB: Only corners with Edges==4 and corners on a bind are correclty supported.
+00473         // ignore problems with corner which nbEdges!=4, because Blend of normals blend to 0 on corner (see computenoise()).
+00474 
+00475         float sTile= s;
+00476         float tTile= t;
+00477         CBindInfo       bindInfoX;
+00478         CBindInfo       bindInfoY;
+00479         uint            edgeX=0;
+00480         uint            edgeY=0;
+00481 
+00482         // both must be not null
+00483         nlassert( (smoothBorderX!=0) && (smoothBorderY!=0) );
+00484 
+00485 
+00486         // Get the edge against we must share displace.
+00487         if(smoothBorderX==-1)   edgeX=0;
+00488         else if(smoothBorderX==1)       edgeX=2;
+00489         else nlstop;
+00490         if(smoothBorderY==1)    edgeY=1;
+00491         else if(smoothBorderY==-1)      edgeY=3;
+00492         else nlstop;
+00493 
+00494         // Build the bindInfo against those 2 edge.
+00495         getBindNeighbor(edgeX, bindInfoX);
+00496         getBindNeighbor(edgeY, bindInfoY);
+00497 
+00498         // Fast reject: if no neighbor on one of the edge, just do a simple computeDisplaceInteriorSmooth.
+00499         if(!bindInfoX.Zone || !bindInfoY.Zone)
+00500                 return computeDisplaceInteriorSmooth(s, t);
+00501         else
+00502         {
+00503                 float   ret;
+00504 
+00505 
+00506                 // compute bi-linear weight factors.
+00507                 float   sInc, tInc, sa, ta, sa1, ta1;
+00508                 computeDisplaceBilinear(sTile, tTile, sInc, tInc, sa, ta, sa1, ta1);
+00509                 // Manage limit case: if bilinear has not chosen the good direction (because of floor and orientation).
+00510                 // eg on Right edge: This case arise if sDecimal==0, so if sa==sa1==0.5f. result is that
+00511                 // smoothBorderX is != than sInc on right border. same reasoning with downBorder (smoothBorderY=1).
+00512 
+00513                 // NO NEED TO DO HERE, because sInc or tInc are not used at all.
+00514 
+00515 
+00516 
+00517                 // compute Neighboring info.
+00518                 CPatchUVLocator         uvLocatorX;
+00519                 CPatchUVLocator         uvLocatorY;
+00520                 uvLocatorX.build(this, edgeX, bindInfoX);
+00521                 uvLocatorY.build(this, edgeY, bindInfoY);
+00522 
+00523 
+00524                 /* NB: see floor problems note in computeDisplaceEdgeSmooth();
+00525                 */
+00526                 sTile= noiseFloor(sTile) + 0.5f;
+00527                 tTile= noiseFloor(tTile) + 0.5f;
+00528                 // If we were exactly on the superior edge, prec compute is false... so correct this here.
+00529                 if(sTile>OrderS) sTile--;
+00530                 if(tTile>OrderT) tTile--;
+00531 
+00532 
+00533                 // Bilinear across a corner.
+00534                 CVector2f       stTileIn, stIn;
+00535                 CVector2f       stTileOut, stOut;
+00536                 CPatch          *patchOut;
+00537                 uint            patchId;
+00538 
+00539 
+00540                 // compute contribution of our patch.
+00541                 ret = computeDisplaceRaw(sTile,tTile, s,t) * sa * ta;
+00542 
+00543                 // compute contribution of the patch on the left/right side. same reasoning as in computeDisplaceEdgeSmooth();
+00544                 stIn.set(s, t);
+00545                 stTileIn.set(sTile+smoothBorderX, tTile);
+00546                 patchId= uvLocatorX.selectPatch(stTileIn);
+00547                 uvLocatorX.locateUV(stTileIn, patchId, patchOut, stTileOut);
+00548                 uvLocatorX.locateUV(stIn, patchId, patchOut, stOut);
+00549                 ret+= patchOut->computeDisplaceRaw(stTileOut.x, stTileOut.y, stOut.x, stOut.y) * sa1 * ta;
+00550 
+00551 
+00552                 // compute contribution of the patch on the up/down side. same reasoning as in computeDisplaceEdgeSmooth();
+00553                 stIn.set(s, t);
+00554                 stTileIn.set(sTile, tTile+smoothBorderY);
+00555                 patchId= uvLocatorY.selectPatch(stTileIn);
+00556                 uvLocatorY.locateUV(stTileIn, patchId, patchOut, stTileOut);
+00557                 uvLocatorY.locateUV(stIn, patchId, patchOut, stOut);
+00558                 ret+= patchOut->computeDisplaceRaw(stTileOut.x, stTileOut.y, stOut.x, stOut.y) * sa * ta1;
+00559 
+00560 
+00561                 /* compute contribution of the patch adjacent to me.
+00562                         There is multiple case to consider here. Take example with corner=0 (ie smBdX=smBdY=-1):
+00563                                 - if we are a normal corner with 4 edges, take the result from the left patch of our top patch.
+00564                                 - if the corner is on a bind Edge, the top patch may be the bigger patch, so don't take the result
+00565                                         from his neighbor (of course).
+00566                                 - if we are a normal corner with N!=4 edges, just do same thing than if N==4. this is false but don't bother.
+00567 
+00568                         To solve smoothly cases 1 and 2, use computeDisplaceRawOnNeighbor().
+00569                         This method, if nessecary, look on his neighbor to compute the value.
+00570                 */
+00571                 stIn.set(s, t);
+00572                 stTileIn.set(sTile+smoothBorderX, tTile+smoothBorderY);
+00573                 // look on our "top" patch (this is arbitrary).
+00574                 patchId= uvLocatorY.selectPatch(stTileIn);
+00575                 uvLocatorY.locateUV(stTileIn, patchId, patchOut, stTileOut);
+00576                 uvLocatorY.locateUV(stIn, patchId, patchOut, stOut);
+00577                 ret+= patchOut->computeDisplaceRawOnNeighbor(stTileOut.x, stTileOut.y, stOut.x, stOut.y) * sa1 * ta1;
+00578 
+00579 
+00580                 return ret;
+00581         }
+00582 
+00583 }
+00584 
+00585 // ***************************************************************************
+00586 CVector         CPatch::computeNormalEdgeSmooth(float s, float t, sint8 smoothBorderX, sint8 smoothBorderY) const
+00587 {
+00588         CBindInfo       bindInfo;
+00589         uint            edge=0;
+00590         CBezierPatch    *bpatch;
+00591         bpatch= unpackIntoCache();
+00592 
+00593         // only one must be not null
+00594         nlassert( (smoothBorderX==0) != (smoothBorderY==0) );
+00595 
+00596 
+00597         // Get the edge against we must share displace.
+00598         if(smoothBorderX==-1)   edge=0;
+00599         else if(smoothBorderY==1)       edge=1;
+00600         else if(smoothBorderX==1)       edge=2;
+00601         else if(smoothBorderY==-1)      edge=3;
+00602         else nlstop;
+00603 
+00604         // If the edge is smoothed, blend with neighbor.
+00605         if(getSmoothFlag(edge))
+00606         {
+00607                 // Build the bindInfo against this edge.
+00608                 getBindNeighbor(edge, bindInfo);
+00609 
+00610                 // Fast reject: if no neighbor, just do a simple computeDisplaceInteriorSmooth.
+00611                 if(!bindInfo.Zone)
+00612                         return bpatch->evalNormal(s/getOrderS(), t/getOrderT());
+00613                 else
+00614                 {
+00615                         CVector         r0, r1;
+00616 
+00617                         // Compute our contribution.
+00618                         r0= bpatch->evalNormal(s/getOrderS(), t/getOrderT());
+00619 
+00620                         // Compute the coordinate on the border of the edge, and the coef of the blend.
+00621                         float           se=s;
+00622                         float           te=t;
+00623                         float           coef=0.0;
+00624                         if(smoothBorderX==-1)           se= noiseFloorF(se), coef=s-se;
+00625                         else if(smoothBorderX==1)       se= noiseCeilF(se), coef=se-s;
+00626                         else if(smoothBorderY==-1)      te= noiseFloorF(te), coef=t-te;
+00627                         else if(smoothBorderY==1)       te= noiseCeilF(te), coef=te-t;
+00628                         coef= 0.5f + coef*0.5f;
+00629 
+00630                         // Compute contribution of the normal on the neighbor, on the border of the edge.
+00631                         CPatchUVLocator         uvLocator;
+00632                         CVector2f       stIn, stOut;
+00633                         CPatch          *patchOut;
+00634                         uint            patchId;
+00635 
+00636                         uvLocator.build(this, edge, bindInfo);
+00637                         stIn.set(se, te);
+00638                         patchId= uvLocator.selectPatch(stIn);
+00639                         uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00640 
+00641                         bpatch= patchOut->unpackIntoCache();
+00642                         r1= bpatch->evalNormal(stOut.x/patchOut->getOrderS(), stOut.y/patchOut->getOrderT());
+00643 
+00644                         // NB: don't bother problems with bind 1/X and the choice of the patch, because bind are C1, so normal is C0.
+00645 
+00646                         // Blend 2 result. For speed optim, don't normalize.
+00647                         return r0*coef + r1*(1-coef);
+00648                 }
+00649         }
+00650         // else blend with vector Null.
+00651         else
+00652         {
+00653                 // compute coef.
+00654                 float           se=s;
+00655                 float           te=t;
+00656                 float           coef=0.0;
+00657                 if(smoothBorderX==-1)           se= noiseFloorF(se), coef=s-se;
+00658                 else if(smoothBorderX==1)       se= noiseCeilF(se), coef=se-s;
+00659                 else if(smoothBorderY==-1)      te= noiseFloorF(te), coef=t-te;
+00660                 else if(smoothBorderY==1)       te= noiseCeilF(te), coef=te-t;
+00661 
+00662                 // Compute our contribution.
+00663                 CVector         r0;
+00664                 r0= bpatch->evalNormal(s/getOrderS(), t/getOrderT());
+00665 
+00666                 // Blend with 0.
+00667                 return r0*coef;
+00668         }
+00669 }
+00670 
+00671 
+00672 // ***************************************************************************
+00673 CVector         CPatch::computeNormalOnNeighbor(float s, float t, uint edgeExclude) const
+00674 {
+00675         sint    edge= -1;
+00676 
+00677         // look on what neighbor patch we must find the value (if any).
+00678         if(s<1 && edgeExclude!=0)                               edge=0;
+00679         else if(t>OrderT-1 && edgeExclude!=1)   edge=1;
+00680         else if(s>OrderS-1 && edgeExclude!=2)   edge=2;
+00681         else if(t<1 && edgeExclude!=3)                  edge=3;
+00682 
+00683 
+00684         // If the location is In the patch, just return normal value. (case of a bind 1/X).
+00685         if(edge==-1)
+00686         {
+00687                 CBezierPatch    *bpatch= unpackIntoCache();
+00688                 return bpatch->evalNormal(s/getOrderS(), t/getOrderT());
+00689         }
+00690         // else must find on neighbor.
+00691         else
+00692         {
+00693                 CBindInfo       bindInfo;
+00694                 getBindNeighbor(edge, bindInfo);
+00695 
+00696                 // Fast reject: if no neighbor on the edge, just do a simple computeDisplaceRaw()
+00697                 if(!bindInfo.Zone)
+00698                 {
+00699                         CBezierPatch    *bpatch= unpackIntoCache();
+00700                         return bpatch->evalNormal(s/getOrderS(), t/getOrderT());
+00701                 }
+00702                 // else must find on neighbor.
+00703                 else
+00704                 {
+00705                         CPatchUVLocator         uvLocator;
+00706                         uvLocator.build(this, edge, bindInfo);
+00707 
+00708                         CVector2f       stIn;
+00709                         CVector2f       stOut;
+00710                         CPatch          *patchOut;
+00711                         uint            patchId;
+00712 
+00713                         // look on neighbor. same reasoning as in computeDisplaceEdgeSmooth();
+00714                         stIn.set(s, t);
+00715                         patchId= uvLocator.selectPatch(stIn);
+00716                         uvLocator.locateUV(stIn, patchId, patchOut, stOut);
+00717                         CBezierPatch    *bpatch= patchOut->unpackIntoCache();
+00718                         return bpatch->evalNormal(stOut.x/patchOut->getOrderS(), stOut.y/patchOut->getOrderT());
+00719                 }
+00720 
+00721         }
+00722 }
+00723 
+00724 
+00725 // ***************************************************************************
+00726 CVector         CPatch::computeNormalCornerSmooth(float s, float t, sint8 smoothBorderX, sint8 smoothBorderY) const
+00727 {
+00728         CBindInfo       bindInfoX;
+00729         CBindInfo       bindInfoY;
+00730         uint            edgeX=0;
+00731         uint            edgeY=0;
+00732         uint            corner;
+00733         CBezierPatch    *bpatch;
+00734         bpatch= unpackIntoCache();
+00735 
+00736         // both must be not null
+00737         nlassert( (smoothBorderX!=0) && (smoothBorderY!=0) );
+00738 
+00739 
+00740         // Get the edge against we must share displace.
+00741         if(smoothBorderX==-1)   edgeX=0;
+00742         else if(smoothBorderX==1)       edgeX=2;
+00743         else nlstop;
+00744         if(smoothBorderY==1)    edgeY=1;
+00745         else if(smoothBorderY==-1)      edgeY=3;
+00746         else nlstop;
+00747 
+00748         // Get the corner against we must share displace.
+00749         if(smoothBorderX==-1)
+00750         {
+00751                 if(smoothBorderY==-1)   corner=0;
+00752                 else                                    corner=1;
+00753         }
+00754         else
+00755         {
+00756                 if(smoothBorderY==-1)   corner=3;
+00757                 else                                    corner=2;
+00758         }
+00759 
+00760         // If this corner is smoothed, blend with 4 neighbors patchs.
+00761         if(getCornerSmoothFlag(corner))
+00762         {
+00763                 // Build the bindInfo against the 2 edge.
+00764                 getBindNeighbor(edgeX, bindInfoX);
+00765                 getBindNeighbor(edgeY, bindInfoY);
+00766 
+00767                 // Fast reject: if no neighbor, just do a simple computeDisplaceInteriorSmooth.
+00768                 if(!bindInfoX.Zone || !bindInfoY.Zone)
+00769                         return bpatch->evalNormal(s/getOrderS(), t/getOrderT());
+00770                 else
+00771                 {
+00772                         CVector         ret;
+00773 
+00774 
+00775                         // Compute the coordinate on the border of the edge, and the coef of the blend.
+00776                         float           se=s;
+00777                         float           te=t;
+00778                         float           coefX;
+00779                         float           coefY;
+00780                         if(smoothBorderX==-1)   se= noiseFloorF(se), coefX=s-se;
+00781                         else                                    se= noiseCeilF(se), coefX=se-s;
+00782                         if(smoothBorderY==-1)   te= noiseFloorF(te), coefY=t-te;
+00783                         else                                    te= noiseCeilF(te), coefY=te-t;
+00784                         coefX= 0.5f + coefX*0.5f;
+00785                         coefY= 0.5f + coefY*0.5f;
+00786 
+00787 
+00788                         // Compute our contribution.
+00789                         ret= bpatch->evalNormal(s/getOrderS(), t/getOrderT()) *coefX*coefY;
+00790 
+00791 
+00792                         // compute Neighboring info.
+00793                         CPatchUVLocator         uvLocatorX;
+00794                         CPatchUVLocator         uvLocatorY;
+00795                         CVector2f       stIn, stOut;
+00796                         CPatch          *patchOut;
+00797                         uint            patchId;
+00798 
+00799                         uvLocatorX.build(this, edgeX, bindInfoX);
+00800                         uvLocatorY.build(this, edgeY, bindInfoY);
+00801 
+00802                         // Patch on our X side.
+00803                         stIn.set(se, te);
+00804                         patchId= uvLocatorX.selectPatch(stIn);
+00805                         uvLocatorX.locateUV(stIn, patchId, patchOut, stOut);
+00806                         bpatch= patchOut->unpackIntoCache();
+00807                         ret+= bpatch->evalNormal(stOut.x/patchOut->getOrderS(), stOut.y/patchOut->getOrderT()) *(1-coefX)*coefY;
+00808 
+00809                         // Patch on our Y side.
+00810                         stIn.set(se, te);
+00811                         patchId= uvLocatorY.selectPatch(stIn);
+00812                         uvLocatorY.locateUV(stIn, patchId, patchOut, stOut);
+00813                         bpatch= patchOut->unpackIntoCache();
+00814                         ret+= bpatch->evalNormal(stOut.x/patchOut->getOrderS(), stOut.y/patchOut->getOrderT()) *coefX*(1-coefY);
+00815 
+00816                         /* compute contribution of the patch adjacent to me.
+00817                                 Same reasoning as in computeDisplaceCornerSmooth().
+00818                         */
+00819                         stIn.set(se, te);
+00820                         patchId= uvLocatorY.selectPatch(stIn);
+00821                         uvLocatorY.locateUV(stIn, patchId, patchOut, stOut);
+00822                         // Because we compute the normal exactly on the edge, we must inform this method not to take us as neighbor.
+00823                         // ugly but simpler.
+00824                         ret+= patchOut->computeNormalOnNeighbor(stOut.x, stOut.y, bindInfoY.Edge[patchId]) *(1-coefX)*(1-coefY);
+00825 
+00826                         return ret;
+00827                 }
+00828         }
+00829         // else must blend with 0.
+00830         else
+00831         {
+00832                 // compute coef.
+00833                 float           se=s;
+00834                 float           te=t;
+00835                 float           coefX;
+00836                 float           coefY;
+00837                 if(smoothBorderX==-1)   se= noiseFloorF(se), coefX=s-se;
+00838                 else                                    se= noiseCeilF(se), coefX=se-s;
+00839                 if(smoothBorderY==-1)   te= noiseFloorF(te), coefY=t-te;
+00840                 else                                    te= noiseCeilF(te), coefY=te-t;
+00841 
+00842 
+00843                 // To have smooth continuities with smooth on edge (if any), we must do this.
+00844                 CVector         rx, ry;
+00845                 // Compute a smooth with my X neighbor.
+00846                 rx= computeNormalEdgeSmooth(s, t, smoothBorderX, 0);
+00847                 // Compute a smooth with my Y neighbor.
+00848                 ry= computeNormalEdgeSmooth(s, t, 0, smoothBorderY);
+00849 
+00850                 // Blend the 2 result.
+00851                 if(coefY + coefX>0)
+00852                 {
+00853                         // This the weight used to blend to 0.
+00854                         float   maxCoef= max(coefY, coefX);
+00855                         // This the weight used to blend beetween rx and ry.
+00856                         float   ooSum= 1.0f / (coefY + coefX);
+00857                         float   blendCoefX= coefX * ooSum;
+00858                         float   blendCoefY= coefY * ooSum;
+00859 
+00860                         return maxCoef* (rx*blendCoefY + ry*blendCoefX);
+00861                 }
+00862                 else
+00863                 {
+00864                         return CVector::Null;
+00865                 }
+00866         }
+00867 }
+00868 
+00869 
+00870 
+00871 // ***************************************************************************
+00872 void            CPatch::computeNoise(float s, float t, CVector &displace) const
+00873 {
+00874         float   so= s*OrderS;
+00875         float   to= t*OrderT;
+00876 
+00877 
+00878         // Pre-Compute Border Smothing.
+00879         //=========================
+00880         // If we are on a border, flag it.
+00881         sint8   smoothNormalBorderX= 0;
+00882         sint8   smoothNormalBorderY= 0;
+00883         // NB: because OrderS and OrderT >=2, smoothNormalBorderX=-1 and smoothNormalBorderX=1 are exclusive (as smoothNormalBorderY).
+00884         if(so < 1) smoothNormalBorderX= -1;
+00885         else if(so > OrderS-1) smoothNormalBorderX= 1;
+00886         if(to < 1) smoothNormalBorderY= -1;
+00887         else if(to > OrderT-1) smoothNormalBorderY= 1;
+00888 
+00889         bool    smoothNormalEdge= (smoothNormalBorderX!=0) != (smoothNormalBorderY!=0);
+00890         bool    smoothNormalCorner= (smoothNormalBorderX!=0) && (smoothNormalBorderY!=0);
+00891 
+00892 
+00893         // Do same thing, but to know if we must compute a displace on an interior, on an edge or on a corner.
+00894         sint8   smoothDisplaceBorderX= 0;
+00895         sint8   smoothDisplaceBorderY= 0;
+00896         // NB: because OrderS and OrderT >=2, smoothBorderX=-1 and smoothBorderX=1 are exclusive (as smoothBorderY).
+00897         if(so < 0.5) smoothDisplaceBorderX= -1;
+00898         else if(so > OrderS-0.5) smoothDisplaceBorderX= 1;
+00899         if(to < 0.5) smoothDisplaceBorderY= -1;
+00900         else if(to > OrderT-0.5) smoothDisplaceBorderY= 1;
+00901 
+00902         bool    smoothDisplaceEdge= (smoothDisplaceBorderX!=0) != (smoothDisplaceBorderY!=0);
+00903         bool    smoothDisplaceCorner= (smoothDisplaceBorderX!=0) && (smoothDisplaceBorderY!=0);
+00904 
+00905 
+00906         // Compute Displace value.
+00907         //=========================
+00908         float   displaceValue;
+00909 
+00910         if(smoothDisplaceCorner)
+00911                 displaceValue= computeDisplaceCornerSmooth(so, to, smoothDisplaceBorderX, smoothDisplaceBorderY);
+00912         else if(smoothDisplaceEdge)
+00913                 displaceValue= computeDisplaceEdgeSmooth(so, to, smoothDisplaceBorderX, smoothDisplaceBorderY);
+00914         else
+00915                 displaceValue= computeDisplaceInteriorSmooth(so, to);
+00916 
+00917 
+00918 
+00919         // Compute Displace normal.
+00920         //=========================
+00921 
+00922         // Evaluate the normal.
+00923         CVector         displaceNormal;
+00924 
+00925 
+00926         // smooth on edges and on corners.
+00927         if(smoothNormalCorner)
+00928                 displaceNormal= computeNormalCornerSmooth(so, to, smoothNormalBorderX, smoothNormalBorderY);
+00929         else if(smoothNormalEdge)
+00930                 displaceNormal= computeNormalEdgeSmooth(so, to, smoothNormalBorderX, smoothNormalBorderY);
+00931         else
+00932         {
+00933                 // unpack...
+00934                 CBezierPatch    *bpatch= unpackIntoCache();
+00935                 // eval.
+00936                 displaceNormal= bpatch->evalNormal(s, t);
+00937         }
+00938 
+00939 
+00940 
+00941         // Final result.
+00942         //=========================
+00943         displace= displaceNormal * displaceValue;
+00944 }
+00945 
+00946 
+00947 
+00948 // ***************************************************************************
+00949 void                    CPatch::setCornerSmoothFlag(uint corner, bool smooth)
+00950 {
+00951         nlassert(corner<=3);
+00952         uint    mask= 1<<corner;
+00953         if(smooth)
+00954                 _CornerSmoothFlag|= mask;
+00955         else
+00956                 _CornerSmoothFlag&= ~mask;
+00957 }
+00958 
+00959 // ***************************************************************************
+00960 bool                    CPatch::getCornerSmoothFlag(uint corner) const
+00961 {
+00962         nlassert(corner<=3);
+00963         uint    mask= 1<<corner;
+00964         return  (_CornerSmoothFlag& mask)!=0;
+00965 }
+00966 
+00967 
+00968 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1