00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
00052
00053
00054
00055
00056
00057
00058
00059 inline sint noiseFloor(float f)
00060 {
00061
00062 sint a;
00063 f*=256;
00064
00065
00066 _asm
00067 {
00068 fld f
00069 fistp a
00070 }
00071
00072
00073 a>>=8;
00074
00075 return a;
00076 }
00077
00078
00079 inline sint noiseCeil(float f)
00080 {
00081
00082 sint a;
00083 f*=256;
00084
00085
00086 _asm
00087 {
00088 fld f
00089 fistp a
00090 }
00091
00092
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
00139
00140 clamp(ts, 0, OrderS-1);
00141 clamp(tt, 0, OrderT-1);
00142
00143 uint tileId= tt*OrderS + ts;
00144
00145 sint tileNumber= Tiles[tileId].Tile[0];
00146
00147 uint tileSubNoise= Tiles[tileId].getTileSubNoise();
00148
00149
00150 CTileNoiseMap *noiseMap;
00151 noiseMap = getZone()->getLandscape()->TileBank.getTileNoiseMap (tileNumber, tileSubNoise);
00152
00153
00154
00155
00156
00157
00158 sint8 pix= noiseMap->Pixels[mt*NL3D_TILE_NOISE_MAP_SIZE + ms];
00159
00160
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
00170
00171
00172 ts= noiseFloor(sTile);
00173 tt= noiseFloor(tTile);
00174
00175
00176
00177
00178
00179
00180 float u= s * NL3D_TILE_NOISE_MAP_TILE_FACTOR;
00181 float v= t * NL3D_TILE_NOISE_MAP_TILE_FACTOR;
00182
00183
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
00206 ms= noiseFloor(uv.U);
00207 mt= noiseFloor(uv.V);
00208
00209
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
00234
00235
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
00246 sDist= (float)fabs(0.5 - sDecimal);
00247 tDist= (float)fabs(0.5 - tDecimal);
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
00263 float sInc, tInc, sa, ta, sa1, ta1;
00264 computeDisplaceBilinear(sTile, tTile, sInc, tInc, sa, ta, sa1, ta1);
00265
00266
00267
00268
00269
00270
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
00294 nlassert( (smoothBorderX==0) != (smoothBorderY==0) );
00295
00296
00297
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
00305 getBindNeighbor(edge, bindInfo);
00306
00307
00308 if(!bindInfo.Zone)
00309 return computeDisplaceInteriorSmooth(s, t);
00310
00311 else
00312 {
00313 float ret;
00314
00315
00316
00317 float sInc, tInc, sa, ta, sa1, ta1;
00318 computeDisplaceBilinear(sTile, tTile, sInc, tInc, sa, ta, sa1, ta1);
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 CPatchUVLocator uvLocator;
00329 uvLocator.build(this, edge, bindInfo);
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 sTile= noiseFloor(sTile) + 0.5f;
00343 tTile= noiseFloor(tTile) + 0.5f;
00344
00345 if(sTile>OrderS) sTile--;
00346 if(tTile>OrderT) tTile--;
00347
00348
00349
00350 CVector2f stTileIn, stIn;
00351 CVector2f stTileOut, stOut;
00352 CPatch *patchOut;
00353 uint patchId;
00354
00355
00356
00357 if(smoothBorderX!=0)
00358 {
00359
00360 ret = computeDisplaceRaw(sTile,tTile, s,t) * sa * ta;
00361 ret+= computeDisplaceRaw(sTile,tTile+tInc, s,t) * sa * ta1;
00362
00363
00364
00365
00366
00367 stIn.set(s, t);
00368
00369 stTileIn.set(sTile+smoothBorderX, tTile);
00370
00371 patchId= uvLocator.selectPatch(stTileIn);
00372 uvLocator.locateUV(stTileIn, patchId, patchOut, stTileOut);
00373 uvLocator.locateUV(stIn, patchId, patchOut, stOut);
00374
00375 ret+= patchOut->computeDisplaceRaw(stTileOut.x, stTileOut.y, stOut.x, stOut.y) * sa1 * ta;
00376
00377
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
00387 else
00388 {
00389
00390
00391
00392 ret = computeDisplaceRaw(sTile, tTile, s,t) * sa * ta;
00393 ret+= computeDisplaceRaw(sTile+sInc,tTile, s,t) * sa1 * ta;
00394
00395
00396
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
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
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
00431 if(edge==-1)
00432 return computeDisplaceRaw(sTile, tTile, s, t);
00433
00434 else
00435 {
00436 CBindInfo bindInfo;
00437 getBindNeighbor(edge, bindInfo);
00438
00439
00440 if(!bindInfo.Zone)
00441 {
00442 return computeDisplaceRaw(sTile, tTile, s, t);
00443 }
00444
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
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
00472
00473
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
00483 nlassert( (smoothBorderX!=0) && (smoothBorderY!=0) );
00484
00485
00486
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
00495 getBindNeighbor(edgeX, bindInfoX);
00496 getBindNeighbor(edgeY, bindInfoY);
00497
00498
00499 if(!bindInfoX.Zone || !bindInfoY.Zone)
00500 return computeDisplaceInteriorSmooth(s, t);
00501 else
00502 {
00503 float ret;
00504
00505
00506
00507 float sInc, tInc, sa, ta, sa1, ta1;
00508 computeDisplaceBilinear(sTile, tTile, sInc, tInc, sa, ta, sa1, ta1);
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 CPatchUVLocator uvLocatorX;
00519 CPatchUVLocator uvLocatorY;
00520 uvLocatorX.build(this, edgeX, bindInfoX);
00521 uvLocatorY.build(this, edgeY, bindInfoY);
00522
00523
00524
00525
00526 sTile= noiseFloor(sTile) + 0.5f;
00527 tTile= noiseFloor(tTile) + 0.5f;
00528
00529 if(sTile>OrderS) sTile--;
00530 if(tTile>OrderT) tTile--;
00531
00532
00533
00534 CVector2f stTileIn, stIn;
00535 CVector2f stTileOut, stOut;
00536 CPatch *patchOut;
00537 uint patchId;
00538
00539
00540
00541 ret = computeDisplaceRaw(sTile,tTile, s,t) * sa * ta;
00542
00543
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
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
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 stIn.set(s, t);
00572 stTileIn.set(sTile+smoothBorderX, tTile+smoothBorderY);
00573
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
00594 nlassert( (smoothBorderX==0) != (smoothBorderY==0) );
00595
00596
00597
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
00605 if(getSmoothFlag(edge))
00606 {
00607
00608 getBindNeighbor(edge, bindInfo);
00609
00610
00611 if(!bindInfo.Zone)
00612 return bpatch->evalNormal(s/getOrderS(), t/getOrderT());
00613 else
00614 {
00615 CVector r0, r1;
00616
00617
00618 r0= bpatch->evalNormal(s/getOrderS(), t/getOrderT());
00619
00620
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
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
00645
00646
00647 return r0*coef + r1*(1-coef);
00648 }
00649 }
00650
00651 else
00652 {
00653
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
00663 CVector r0;
00664 r0= bpatch->evalNormal(s/getOrderS(), t/getOrderT());
00665
00666
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
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
00685 if(edge==-1)
00686 {
00687 CBezierPatch *bpatch= unpackIntoCache();
00688 return bpatch->evalNormal(s/getOrderS(), t/getOrderT());
00689 }
00690
00691 else
00692 {
00693 CBindInfo bindInfo;
00694 getBindNeighbor(edge, bindInfo);
00695
00696
00697 if(!bindInfo.Zone)
00698 {
00699 CBezierPatch *bpatch= unpackIntoCache();
00700 return bpatch->evalNormal(s/getOrderS(), t/getOrderT());
00701 }
00702
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
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
00737 nlassert( (smoothBorderX!=0) && (smoothBorderY!=0) );
00738
00739
00740
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
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
00761 if(getCornerSmoothFlag(corner))
00762 {
00763
00764 getBindNeighbor(edgeX, bindInfoX);
00765 getBindNeighbor(edgeY, bindInfoY);
00766
00767
00768 if(!bindInfoX.Zone || !bindInfoY.Zone)
00769 return bpatch->evalNormal(s/getOrderS(), t/getOrderT());
00770 else
00771 {
00772 CVector ret;
00773
00774
00775
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
00789 ret= bpatch->evalNormal(s/getOrderS(), t/getOrderT()) *coefX*coefY;
00790
00791
00792
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
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
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
00817
00818
00819 stIn.set(se, te);
00820 patchId= uvLocatorY.selectPatch(stIn);
00821 uvLocatorY.locateUV(stIn, patchId, patchOut, stOut);
00822
00823
00824 ret+= patchOut->computeNormalOnNeighbor(stOut.x, stOut.y, bindInfoY.Edge[patchId]) *(1-coefX)*(1-coefY);
00825
00826 return ret;
00827 }
00828 }
00829
00830 else
00831 {
00832
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
00844 CVector rx, ry;
00845
00846 rx= computeNormalEdgeSmooth(s, t, smoothBorderX, 0);
00847
00848 ry= computeNormalEdgeSmooth(s, t, 0, smoothBorderY);
00849
00850
00851 if(coefY + coefX>0)
00852 {
00853
00854 float maxCoef= max(coefY, coefX);
00855
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
00879
00880
00881 sint8 smoothNormalBorderX= 0;
00882 sint8 smoothNormalBorderY= 0;
00883
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
00894 sint8 smoothDisplaceBorderX= 0;
00895 sint8 smoothDisplaceBorderY= 0;
00896
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
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
00920
00921
00922
00923 CVector displaceNormal;
00924
00925
00926
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
00934 CBezierPatch *bpatch= unpackIntoCache();
00935
00936 displaceNormal= bpatch->evalNormal(s, t);
00937 }
00938
00939
00940
00941
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 }