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/patchuv_locator.h"
00037 #include "3d/vegetable_manager.h"
00038 #include "3d/fast_floor.h"
00039 #include "3d/light_influence_interpolator.h"
00040 #include "3d/patchdlm_context.h"
00041
00042 using namespace std;
00043 using namespace NLMISC;
00044
00045
00046 namespace NL3D
00047 {
00048
00049
00050
00051 CBezierPatch CPatch::CachePatch;
00052 const CPatch *CPatch::LastPatch= NULL;
00053 uint32 CPatch::_Version=7;
00054
00055
00056
00057 CPatch::CPatch()
00058 {
00059 Zone= NULL;
00060 OrderS=0;
00061 OrderT=0;
00062 Son0=NULL;
00063 Son1=NULL;
00064 TessBlockRefCount=0;
00065 Clipped=false;
00066 RenderClipped= true;
00067 OldRenderClipped= true;
00068 NumRenderableFaces= 0;
00069
00070
00071 ExcludeFromRefineAll= false;
00072
00073
00074
00075
00076
00077
00078 Far0= -1;
00079 Far1= -1;
00080
00081
00082 _BindZoneNeighbor[0]= NULL;
00083 _BindZoneNeighbor[1]= NULL;
00084 _BindZoneNeighbor[2]= NULL;
00085 _BindZoneNeighbor[3]= NULL;
00086 NoiseRotation= 0;
00087
00088 _CornerSmoothFlag= 0;
00089
00090
00091 MasterBlock.resetClip();
00092
00093
00094 _ULNearPrec= NULL;
00095 _ULNearNext= NULL;
00096
00097
00098 _DLMContext= NULL;
00099 _DLMContextRefCount= 0;
00100 }
00101
00102 CPatch::~CPatch()
00103 {
00104 release();
00105 }
00106
00107
00108 void CPatch::release()
00109 {
00110 if(Zone)
00111 {
00112
00113 if(!RenderClipped)
00114 {
00115
00116 deleteVBAndFaceVector();
00117
00118
00119 RenderClipped= true;
00120 }
00121
00122
00123 nlassert(Son0 && Son1);
00124 nlassert(Son0->isLeaf() && Son1->isLeaf());
00125 nlassert(Son0->FLeft == NULL);
00126 nlassert(Son0->FRight == NULL);
00127 nlassert(Son1->FLeft == NULL);
00128 nlassert(Son1->FRight == NULL);
00129
00130
00131
00132 resetRenderFar();
00133
00134 getLandscape()->deleteTessFace(Son0);
00135 getLandscape()->deleteTessFace(Son1);
00136
00137 }
00138
00139
00140 Pass0.Patch= NULL;
00141 Pass1.Patch= NULL;
00142 OrderS=0;
00143 OrderT=0;
00144 Son0=NULL;
00145 Son1=NULL;
00146 clearTessBlocks();
00147 resetMasterBlock();
00148 Clipped=false;
00149 RenderClipped= true;
00150 OldRenderClipped= true;
00151
00152
00153
00154 Zone= NULL;
00155
00156
00157 if(_ULNearPrec!= NULL)
00158 {
00159
00160 nlassert(_ULNearPrec==this && _ULNearNext==this);
00161 }
00162 _ULNearPrec= NULL;
00163 _ULNearNext= NULL;
00164
00165
00166 if(_DLMContext)
00167 delete _DLMContext;
00168
00169 _DLMContext= NULL;
00170 _DLMContextRefCount= 0;
00171 }
00172
00173
00174
00175 CBezierPatch *CPatch::unpackIntoCache() const
00176 {
00177 if(LastPatch!=this)
00178 {
00179 unpack(CachePatch);
00180 LastPatch=this;
00181 }
00182 return &CachePatch;
00183 }
00184
00185 void CPatch::unpack(CBezierPatch &p) const
00186 {
00187 sint i;
00188 const CVector &bias= Zone->getPatchBias();
00189 float scale= Zone->getPatchScale();
00190
00191 for(i=0;i<4;i++)
00192 Vertices[i].unpack(p.Vertices[i], bias, scale);
00193 for(i=0;i<8;i++)
00194 Tangents[i].unpack(p.Tangents[i], bias, scale);
00195 for(i=0;i<4;i++)
00196 Interiors[i].unpack(p.Interiors[i], bias, scale);
00197 }
00198
00199 void CPatch::computeDefaultErrorSize()
00200 {
00201 CBezierPatch &p= *unpackIntoCache();
00202 CVector &v0= p.Vertices[0];
00203 CVector &v1= p.Vertices[1];
00204 CVector &v2= p.Vertices[2];
00205
00206
00207 ErrorSize= ((v1 - v0)^(v2 - v0)).norm();
00208
00209 }
00210
00211
00212
00213
00214 void CPatch::buildBBoxFromBezierPatch(const CBezierPatch &p, CAABBox &ret) const
00215 {
00216
00217
00218 CVector bmin= p.Vertices[0];
00219 CVector bmax= bmin;
00220
00221 sint i;
00222 for(i=0;i<4;i++)
00223 {
00224 bmin.minof(bmin, p.Vertices[i]);
00225 bmax.maxof(bmax, p.Vertices[i]);
00226 }
00227 for(i=0;i<8;i++)
00228 {
00229 bmin.minof(bmin, p.Tangents[i]);
00230 bmax.maxof(bmax, p.Tangents[i]);
00231 }
00232 for(i=0;i<4;i++)
00233 {
00234 bmin.minof(bmin, p.Interiors[i]);
00235 bmax.maxof(bmax, p.Interiors[i]);
00236 }
00237
00238
00239 static CVector vectorNoiseMax(NL3D_NOISE_MAX, NL3D_NOISE_MAX, NL3D_NOISE_MAX);
00240 bmin-= vectorNoiseMax;
00241 bmax+= vectorNoiseMax;
00242
00243
00244
00245 ret.setMinMax(bmin, bmax);
00246 }
00247
00248
00249
00250 CAABBox CPatch::buildBBox() const
00251 {
00252 CBezierPatch &p= *unpackIntoCache();
00253
00254
00255 CAABBox ret;
00256 buildBBoxFromBezierPatch(p, ret);
00257
00258 return ret;
00259 }
00260
00261
00262
00263 void CPatch::addTrianglesInBBox(CPatchIdent paId, const CAABBox &bbox, std::vector<CTrianglePatch> &triangles, uint8 tileTessLevel) const
00264 {
00265 CBezierPatch &bpatch= *unpackIntoCache();
00266
00267
00268 addTrianglesInBBoxRecurs(paId, bbox, triangles, tileTessLevel, bpatch, 0, OrderS, 0, OrderT);
00269 }
00270
00271
00272
00273 void CPatch::addTrianglesInBBoxRecurs(CPatchIdent paId, const CAABBox &bbox, std::vector<CTrianglePatch> &triangles, uint8 tessLevel,
00274 const CBezierPatch &pa, uint8 s0, uint8 s1, uint8 t0, uint8 t1) const
00275 {
00276 uint8 lenS=s1-s0, lenT=t1-t0;
00277 nlassert(lenS>0);
00278 nlassert(lenT>0);
00279
00280
00281
00282
00283 CAABBox paBBox;
00284 buildBBoxFromBezierPatch(pa, paBBox);
00285
00286 if( !paBBox.intersect(bbox) )
00287 return;
00288
00289
00290 else if( lenS==1 && lenT==1 )
00291 {
00292 addTileTrianglesInBBox(paId, bbox, triangles, tessLevel, s0, t0);
00293 }
00294
00295
00296 else
00297 {
00298
00299 if(lenS>lenT)
00300 {
00301
00302 CBezierPatch left, right;
00303 pa.subdivideS(left, right);
00304 uint8 sMiddle= (uint8)( ((uint)s0+(uint)s1) /2 );
00305
00306 addTrianglesInBBoxRecurs(paId, bbox, triangles, tessLevel, left, s0, sMiddle, t0, t1);
00307
00308 addTrianglesInBBoxRecurs(paId, bbox, triangles, tessLevel, right, sMiddle, s1, t0, t1);
00309 }
00310 else
00311 {
00312
00313 CBezierPatch top, bottom;
00314 pa.subdivideT(top, bottom);
00315 uint8 tMiddle= (uint8)( ((uint)t0+(uint)t1) /2 );
00316
00317 addTrianglesInBBoxRecurs(paId, bbox, triangles, tessLevel, top, s0, s1, t0, tMiddle);
00318
00319 addTrianglesInBBoxRecurs(paId, bbox, triangles, tessLevel, bottom, s0, s1, tMiddle, t1);
00320 }
00321 }
00322
00323
00324 }
00325
00326
00327
00328 void CPatch::addTileTrianglesInBBox(CPatchIdent paId, const CAABBox &bbox, std::vector<CTrianglePatch> &triangles, uint8 tessLevel, uint8 s0, uint8 t0) const
00329 {
00330 nlassert(s0<OrderS);
00331 nlassert(t0<OrderT);
00332 nlassert(tessLevel<=2);
00333 uint tessLen= 1<<tessLevel;
00334
00335
00336 float startS0= (float)s0 / (float)(OrderS);
00337 float startT0= (float)t0 / (float)(OrderT);
00338 float ds= 1.0f/(float)(OrderS*tessLen);
00339 float dt= 1.0f/(float)(OrderT*tessLen);
00340
00341
00342 uint sl,tl;
00343 for(tl=0; tl<tessLen; tl++)
00344 {
00345 float fs0, fs1, ft0, ft1;
00346
00347 ft0= startT0 + (float)tl * dt ;
00348 ft1= ft0 + dt;
00349 for(sl=0; sl<tessLen; sl++)
00350 {
00351
00352 fs0= startS0 + (float)sl * ds ;
00353 fs1= fs0 + ds;
00354
00355
00356 CVector p0, p1, p2, p3;
00357 CUV uv0, uv1, uv2, uv3;
00358 uv0.U= fs0; uv0.V= ft0;
00359 uv1.U= fs0; uv1.V= ft1;
00360 uv2.U= fs1; uv2.V= ft1;
00361 uv3.U= fs1; uv3.V= ft0;
00362
00363 p0= computeVertex(uv0.U, uv0.V);
00364 p1= computeVertex(uv1.U, uv1.V);
00365 p2= computeVertex(uv2.U, uv2.V);
00366 p3= computeVertex(uv3.U, uv3.V);
00367
00368
00369 CAABBox quadBBox;
00370 quadBBox.setCenter(p0);
00371 quadBBox.extend(p1);
00372 quadBBox.extend(p2);
00373 quadBBox.extend(p3);
00374
00375
00376 if(quadBBox.intersect(bbox))
00377 {
00378
00379 CTrianglePatch tri;
00380 tri.PatchId= paId;
00381
00382
00383 tri.V0= p0; tri.V1= p1; tri.V2= p2;
00384 tri.Uv0= uv0; tri.Uv1= uv1; tri.Uv2= uv2;
00385 triangles.push_back(tri);
00386
00387
00388 tri.V0= p2; tri.V1= p3; tri.V2= p0;
00389 tri.Uv0= uv2; tri.Uv1= uv3; tri.Uv2= uv0;
00390 triangles.push_back(tri);
00391
00392
00393
00394 }
00395 }
00396 }
00397
00398 }
00399
00400
00401
00402
00403 void CPatchQuadBlock::buildTileTriangles(uint8 quadId, CTrianglePatch triangles[2]) const
00404 {
00405
00406 uint sd0= quadId&(NL_PATCH_BLOCK_MAX_QUAD-1);
00407 uint td0= quadId/(NL_PATCH_BLOCK_MAX_QUAD);
00408 uint sd1= sd0+1;
00409 uint td1= td0+1;
00410 uint s= PatchBlockId.S0+sd0;
00411 uint t= PatchBlockId.T0+td0;
00412 nlassert(s<PatchBlockId.S1);
00413 nlassert(t<PatchBlockId.T1);
00414
00415
00416 float fs0= (float)s / (float)(PatchBlockId.OrderS);
00417 float ft0= (float)t / (float)(PatchBlockId.OrderT);
00418 float fs1= (float)(s+1) / (float)(PatchBlockId.OrderS);
00419 float ft1= (float)(t+1) / (float)(PatchBlockId.OrderT);
00420 CUV uv0, uv1, uv2, uv3;
00421 uv0.U= fs0; uv0.V= ft0;
00422 uv1.U= fs0; uv1.V= ft1;
00423 uv2.U= fs1; uv2.V= ft1;
00424 uv3.U= fs1; uv3.V= ft0;
00425
00426
00427 const CVector &p0= Vertices[sd0 + td0*NL_PATCH_BLOCK_MAX_VERTEX];
00428 const CVector &p1= Vertices[sd0 + td1*NL_PATCH_BLOCK_MAX_VERTEX];
00429 const CVector &p2= Vertices[sd1 + td1*NL_PATCH_BLOCK_MAX_VERTEX];
00430 const CVector &p3= Vertices[sd1 + td0*NL_PATCH_BLOCK_MAX_VERTEX];
00431
00432
00433
00434 {
00435 CTrianglePatch &tri= triangles[0];
00436 tri.PatchId= PatchBlockId.PatchId;
00437 tri.V0= p0; tri.V1= p1; tri.V2= p2;
00438 tri.Uv0= uv0; tri.Uv1= uv1; tri.Uv2= uv2;
00439 }
00440
00441
00442 {
00443 CTrianglePatch &tri= triangles[1];
00444 tri.PatchId= PatchBlockId.PatchId;
00445 tri.V0= p2; tri.V1= p3; tri.V2= p0;
00446 tri.Uv0= uv2; tri.Uv1= uv3; tri.Uv2= uv0;
00447 }
00448
00449 }
00450
00451
00452
00453 void CPatch::fillPatchQuadBlock(CPatchQuadBlock &quadBlock) const
00454 {
00455 CPatchBlockIdent &pbId= quadBlock.PatchBlockId;
00456 uint lenS= pbId.S1-pbId.S0;
00457 uint lenT= pbId.T1-pbId.T0;
00458 nlassert( pbId.OrderS==OrderS );
00459 nlassert( pbId.OrderT==OrderT );
00460 nlassert( pbId.S1<=OrderS );
00461 nlassert( pbId.T1<=OrderT );
00462 nlassert( pbId.S0<pbId.S1 );
00463 nlassert( pbId.T0<pbId.T1 );
00464 nlassert( lenS<=NL_PATCH_BLOCK_MAX_QUAD );
00465 nlassert( lenT<=NL_PATCH_BLOCK_MAX_QUAD );
00466
00467
00468 uint s0= pbId.S0;
00469 uint t0= pbId.T0;
00470
00471 float startS0= (float)s0 / (float)(OrderS);
00472 float startT0= (float)t0 / (float)(OrderT);
00473 float ds= 1.0f/(float)(OrderS);
00474 float dt= 1.0f/(float)(OrderT);
00475
00476
00477 uint sl,tl;
00478 for(tl=0; tl<lenT+1; tl++)
00479 {
00480 float fs, ft;
00481
00482 ft= startT0 + (float)tl * dt ;
00483 for(sl=0; sl<lenS+1; sl++)
00484 {
00485
00486 fs= startS0 + (float)sl * ds ;
00487
00488
00489 quadBlock.Vertices[sl + tl*NL_PATCH_BLOCK_MAX_VERTEX]= computeContinousVertex(fs, ft);
00490 }
00491 }
00492
00493 }
00494
00495
00496
00497 void CPatch::addPatchBlocksInBBox(CPatchIdent paId, const CAABBox &bbox, std::vector<CPatchBlockIdent> &paBlockIds) const
00498 {
00499 CBezierPatch &bpatch= *unpackIntoCache();
00500
00501
00502 addPatchBlocksInBBoxRecurs(paId, bbox, paBlockIds, bpatch, 0, OrderS, 0, OrderT);
00503 }
00504
00505
00506
00507 void CPatch::addPatchBlocksInBBoxRecurs(CPatchIdent paId, const CAABBox &bbox, std::vector<CPatchBlockIdent> &paBlockIds,
00508 const CBezierPatch &pa, uint8 s0, uint8 s1, uint8 t0, uint8 t1) const
00509 {
00510 uint8 lenS=s1-s0, lenT=t1-t0;
00511 nlassert(lenS>0);
00512 nlassert(lenT>0);
00513
00514
00515
00516
00517 CAABBox paBBox;
00518 buildBBoxFromBezierPatch(pa, paBBox);
00519
00520 if( !paBBox.intersect(bbox) )
00521 return;
00522
00523
00524 else if( lenS<=NL_PATCH_BLOCK_MAX_QUAD && lenT<=NL_PATCH_BLOCK_MAX_QUAD )
00525 {
00526
00527 CPatchBlockIdent pbId;
00528
00529 pbId.PatchId= paId;
00530 pbId.OrderS= OrderS;
00531 pbId.OrderT= OrderT;
00532 pbId.S0= s0;
00533 pbId.S1= s1;
00534 pbId.T0= t0;
00535 pbId.T1= t1;
00536
00537 paBlockIds.push_back(pbId);
00538 }
00539
00540
00541 else
00542 {
00543
00544 if(lenS>lenT)
00545 {
00546
00547 CBezierPatch left, right;
00548 pa.subdivideS(left, right);
00549 uint8 sMiddle= (uint8)( ((uint)s0+(uint)s1) /2 );
00550
00551 addPatchBlocksInBBoxRecurs(paId, bbox, paBlockIds, left, s0, sMiddle, t0, t1);
00552
00553 addPatchBlocksInBBoxRecurs(paId, bbox, paBlockIds, right, sMiddle, s1, t0, t1);
00554 }
00555 else
00556 {
00557
00558 CBezierPatch top, bottom;
00559 pa.subdivideT(top, bottom);
00560 uint8 tMiddle= (uint8)( ((uint)t0+(uint)t1) /2 );
00561
00562 addPatchBlocksInBBoxRecurs(paId, bbox, paBlockIds, top, s0, s1, t0, tMiddle);
00563
00564 addPatchBlocksInBBoxRecurs(paId, bbox, paBlockIds, bottom, s0, s1, tMiddle, t1);
00565 }
00566 }
00567
00568 }
00569
00570
00571
00572 CVector CPatch::getTesselatedPos(CUV uv) const
00573 {
00574
00575 clamp(uv.U, 0, 1);
00576 clamp(uv.V, 0, 1);
00577
00578 CVector ret= CVector::Null;
00579 Son0->getTesselatedPos(uv, true, ret);
00580 Son1->getTesselatedPos(uv, true, ret);
00581
00582 return ret;
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 void CPatch::addRefTessBlocks()
00595 {
00596 uint i;
00597
00598 TessBlockRefCount++;
00599 if(TessBlocks.size()==0)
00600 {
00601
00602
00603
00604 nlassert(NL3D_TESSBLOCK_TILESIZE==4);
00605
00606 sint os= OrderS>>1;
00607 sint ot= OrderT>>1;
00608 nlassert(os>0);
00609 nlassert(ot>0);
00610 TessBlocks.resize(os*ot);
00611
00612 for(i=0; i<TessBlocks.size(); i++)
00613 TessBlocks[i].init(this);
00614
00615
00616
00617
00618
00619 CVegetableManager *vegetableManager= getLandscape()->_VegetableManager;
00620
00621
00622 uint nTbPerCb= NL3D_PATCH_VEGETABLE_NUM_TESSBLOCK_PER_CLIPBLOCK;
00623 uint wCB= (os + nTbPerCb-1) >> NL3D_PATCH_VEGETABLE_NUM_TESSBLOCK_PER_CLIPBLOCK_SHIFT;
00624 uint hCB= (ot + nTbPerCb-1) >> NL3D_PATCH_VEGETABLE_NUM_TESSBLOCK_PER_CLIPBLOCK_SHIFT;
00625 VegetableClipBlocks.resize(wCB * hCB);
00626
00627 for(i=0; i<VegetableClipBlocks.size(); i++)
00628 {
00629 VegetableClipBlocks[i]= vegetableManager->createClipBlock();
00630 }
00631
00632
00633
00634
00635
00636 getLandscape()->linkPatchToNearUL(this);
00637 }
00638 }
00639
00640
00641 void CPatch::decRefTessBlocks()
00642 {
00643 TessBlockRefCount--;
00644
00645 if(TessBlockRefCount==0)
00646 clearTessBlocks();
00647 nlassert(TessBlockRefCount>=0);
00648 }
00649
00650
00651
00652 void CPatch::clearTessBlocks()
00653 {
00654 uint i;
00655
00656
00657
00658
00659 if(Zone)
00660 {
00661 CVegetableManager *vegetableManager= getLandscape()->_VegetableManager;
00662
00663
00664 deleteAllVegetableIgs();
00665
00666
00667 for(i=0; i<VegetableClipBlocks.size(); i++)
00668 {
00669 vegetableManager->deleteClipBlock(VegetableClipBlocks[i]);
00670 }
00671 contReset(VegetableClipBlocks);
00672 }
00673
00674
00675
00676
00677 if(Zone)
00678 {
00679
00680 getLandscape()->unlinkPatchFromNearUL(this);
00681 }
00682
00683
00684
00685
00686 TessBlockRefCount=0;
00687 contReset(TessBlocks);
00688 }
00689
00690
00691
00692 void CPatch::resetMasterBlock()
00693 {
00694
00695 nlassert(RenderClipped);
00696
00697 MasterBlock.FarVertexList.clear();
00698 MasterBlock.FarFaceList.clear();
00699 NumRenderableFaces= 0;
00700
00701 nlassert(MasterBlock.NearVertexList.size()==0);
00702 }
00703
00704
00705 uint CPatch::getNumTessBlock(CTessFace *face)
00706 {
00707
00708
00709 CParamCoord edgeMid(face->PVLeft, face->PVRight);
00710 CParamCoord middle(edgeMid, face->PVBase);
00711
00712 uint ts= ((uint)middle.S * (uint)(OrderS>>1)) / 0x8000;
00713 uint tt= ((uint)middle.T * (uint)(OrderT>>1)) / 0x8000;
00714 uint numtb= tt*(uint)(OrderS>>1) + ts;
00715
00716 return numtb;
00717 }
00718
00719
00720
00721 void CPatch::getNumTessBlock(CParamCoord pc, TFarVertType &type, uint &numtb)
00722 {
00723 uint tboS= (uint)(OrderS>>1);
00724 uint tboT= (uint)(OrderT>>1);
00725
00726
00727 uint ts= ((uint)pc.S * tboS) / 0x8000;
00728 uint tt= ((uint)pc.T * tboT) / 0x8000;
00729 numtb= tt*tboS + ts;
00730
00731 bool edgeS= (ts*0x8000) == ((uint)pc.S * tboS);
00732 bool edgeT= (tt*0x8000) == ((uint)pc.T * tboT);
00733
00734
00735 if(edgeS && edgeT)
00736 type= FVMasterBlock;
00737
00738 else if(edgeS || edgeT)
00739 type= FVTessBlockEdge;
00740
00741 else
00742 type= FVTessBlock;
00743
00744 }
00745
00746
00747
00748
00749 void CPatch::extendTessBlockWithEndPos(CTessFace *face)
00750 {
00751 if(face->Level>=TessBlockLimitLevel)
00752 {
00753
00754 uint numtb= getNumTessBlock(face);
00755
00756
00757 TessBlocks[numtb].extendSphereFirst(face->VBase->EndPos);
00758 TessBlocks[numtb].extendSphereAdd(face->VLeft->EndPos);
00759 TessBlocks[numtb].extendSphereAdd(face->VRight->EndPos);
00760 TessBlocks[numtb].extendSphereCompile();
00761 }
00762 }
00763
00764
00765
00766 void CPatch::dirtTessBlockFaceVector(CTessBlock &tb)
00767 {
00768
00769 if(!RenderClipped)
00770 {
00771
00772 if(!tb.isInModifyList())
00773 {
00774
00775
00776 tb.appendToModifyListAndDeleteFaceVector(getLandscape()->_TessBlockModificationRoot, getLandscape()->_FaceVectorManager);
00777 }
00778 }
00779 }
00780
00781
00782
00783 void CPatch::appendFaceToRenderList(CTessFace *face)
00784 {
00785
00786 NumRenderableFaces++;
00787
00788
00789
00790 if(face->Level<TessBlockLimitLevel)
00791 {
00792 MasterBlock.FarFaceList.append(face);
00793 MasterBlock.FaceTileMaterialRefCount++;
00794
00795
00796 dirtTessBlockFaceVector(MasterBlock);
00797 }
00798 else
00799 {
00800
00801 addRefTessBlocks();
00802
00803
00804 uint numtb= getNumTessBlock(face);
00805 TessBlocks[numtb].FarFaceList.append(face);
00806 TessBlocks[numtb].FaceTileMaterialRefCount++;
00807
00808
00809 dirtTessBlockFaceVector(TessBlocks[numtb]);
00810
00811
00812
00813 TessBlocks[numtb].extendSphereFirst(face->VBase->EndPos);
00814 TessBlocks[numtb].extendSphereAdd(face->VLeft->EndPos);
00815 TessBlocks[numtb].extendSphereAdd(face->VRight->EndPos);
00816
00817
00818 TessBlocks[numtb].extendSphereAdd(face->VBase->StartPos);
00819 TessBlocks[numtb].extendSphereAdd(face->VLeft->StartPos);
00820 TessBlocks[numtb].extendSphereAdd(face->VRight->StartPos);
00821 TessBlocks[numtb].extendSphereCompile();
00822
00823
00824
00825 appendFaceToTileRenderList(face);
00826 }
00827 }
00828
00829
00830
00831 void CPatch::removeFaceFromRenderList(CTessFace *face)
00832 {
00833
00834 NumRenderableFaces--;
00835 nlassert(NumRenderableFaces>=0);
00836
00837
00838
00839 if(face->Level<TessBlockLimitLevel)
00840 {
00841 MasterBlock.FarFaceList.remove(face);
00842 MasterBlock.FaceTileMaterialRefCount--;
00843
00844
00845 dirtTessBlockFaceVector(MasterBlock);
00846 }
00847 else
00848 {
00849
00850 uint numtb= getNumTessBlock(face);
00851 TessBlocks[numtb].FarFaceList.remove(face);
00852 TessBlocks[numtb].FaceTileMaterialRefCount--;
00853
00854
00855 dirtTessBlockFaceVector(TessBlocks[numtb]);
00856
00857
00858 removeFaceFromTileRenderList(face);
00859
00860
00861 decRefTessBlocks();
00862 }
00863 }
00864
00865
00866
00867 void CPatch::appendFaceToTileRenderList(CTessFace *face)
00868 {
00869 if(face->TileMaterial)
00870 {
00871
00872
00873 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00874 {
00875 CPatchRdrPass *tilePass= face->TileMaterial->Pass[i].PatchRdrPass;
00876
00877 if(tilePass)
00878 {
00879
00880 nlassert(face->TileFaces[i]);
00881 face->TileMaterial->TileFaceList[i].append(face->TileFaces[i]);
00882 }
00883 }
00884
00885
00886 uint numtb= getNumTessBlock(face);
00887 dirtTessBlockFaceVector(TessBlocks[numtb]);
00888 }
00889 }
00890
00891
00892
00893 void CPatch::removeFaceFromTileRenderList(CTessFace *face)
00894 {
00895 if(face->TileMaterial)
00896 {
00897
00898
00899 for(sint i=0;i<NL3D_MAX_TILE_FACE;i++)
00900 {
00901 CPatchRdrPass *tilePass= face->TileMaterial->Pass[i].PatchRdrPass;
00902
00903 if(tilePass)
00904 {
00905
00906 nlassert(face->TileFaces[i]);
00907 face->TileMaterial->TileFaceList[i].remove(face->TileFaces[i]);
00908 }
00909 }
00910
00911
00912 uint numtb= getNumTessBlock(face);
00913 dirtTessBlockFaceVector(TessBlocks[numtb]);
00914 }
00915 }
00916
00917
00918
00919 void CPatch::computeTbTm(uint &numtb, uint &numtm, uint ts, uint tt)
00920 {
00921 sint is= ts&1;
00922 sint it= tt&1;
00923 ts>>=1;
00924 tt>>=1;
00925
00926 numtb= tt*(uint)(OrderS>>1) + ts;
00927 numtm= it*2+is;
00928 }
00929
00930
00931
00932 void CPatch::appendTileMaterialToRenderList(CTileMaterial *tm)
00933 {
00934 nlassert(tm);
00935
00936
00937 addRefTessBlocks();
00938
00939 uint numtb, numtm;
00940 computeTbTm(numtb, numtm, tm->TileS, tm->TileT);
00941 TessBlocks[numtb].RdrTileRoot[numtm]= tm;
00942 TessBlocks[numtb].FaceTileMaterialRefCount++;
00943 TessBlocks[numtb].TileMaterialRefCount++;
00944
00945 MasterBlock.TileMaterialRefCount++;
00946
00947
00948
00949
00950 addRefDLMContext();
00951
00952
00953
00954
00955
00956 if( TessBlocks[numtb].TileMaterialRefCount == 1 && getLandscape()->isVegetableActive() )
00957 {
00958 createVegetableBlock(numtb, tm->TileS, tm->TileT);
00959 }
00960
00961 }
00962
00963 void CPatch::removeTileMaterialFromRenderList(CTileMaterial *tm)
00964 {
00965 nlassert(tm);
00966
00967 uint numtb, numtm;
00968 computeTbTm(numtb, numtm, tm->TileS, tm->TileT);
00969 TessBlocks[numtb].RdrTileRoot[numtm]= NULL;
00970 TessBlocks[numtb].FaceTileMaterialRefCount--;
00971 TessBlocks[numtb].TileMaterialRefCount--;
00972
00973 MasterBlock.TileMaterialRefCount--;
00974
00975
00976
00977
00978 if( TessBlocks[numtb].TileMaterialRefCount==0 )
00979 {
00980
00981 releaseVegetableBlock(numtb);
00982 }
00983
00984
00985 decRefTessBlocks();
00986
00987
00988
00989
00990 decRefDLMContext();
00991 }
00992
00993
00994
00995 void CPatch::appendFarVertexToRenderList(CTessFarVertex *fv)
00996 {
00997 TFarVertType type;
00998 uint numtb;
00999 getNumTessBlock(fv->PCoord, type, numtb);
01000
01001
01002 if(type==FVMasterBlock || type==FVTessBlockEdge)
01003 {
01004 fv->OwnerBlock= &MasterBlock;
01005 MasterBlock.FarVertexList.append(fv);
01006 }
01007 else
01008 {
01009
01010 addRefTessBlocks();
01011
01012 fv->OwnerBlock= &TessBlocks[numtb];
01013 TessBlocks[numtb].FarVertexList.append(fv);
01014 }
01015 }
01016
01017 void CPatch::removeFarVertexFromRenderList(CTessFarVertex *fv)
01018 {
01019 TFarVertType type;
01020 uint numtb;
01021 getNumTessBlock(fv->PCoord, type, numtb);
01022
01023
01024 if(type==FVMasterBlock || type==FVTessBlockEdge)
01025 {
01026 MasterBlock.FarVertexList.remove(fv);
01027 fv->OwnerBlock= NULL;
01028 }
01029 else
01030 {
01031 TessBlocks[numtb].FarVertexList.remove(fv);
01032 fv->OwnerBlock= NULL;
01033
01034
01035 decRefTessBlocks();
01036 }
01037 }
01038
01039
01040
01041 void CPatch::appendNearVertexToRenderList(CTileMaterial *tileMat, CTessNearVertex *nv)
01042 {
01043 nlassert(tileMat);
01044
01045
01046 addRefTessBlocks();
01047
01048 uint numtb, numtm;
01049 computeTbTm(numtb, numtm, tileMat->TileS, tileMat->TileT);
01050 nv->OwnerBlock= &TessBlocks[numtb];
01051 TessBlocks[numtb].NearVertexList.append(nv);
01052 }
01053
01054 void CPatch::removeNearVertexFromRenderList(CTileMaterial *tileMat, CTessNearVertex *nv)
01055 {
01056 nlassert(tileMat);
01057
01058 uint numtb, numtm;
01059 computeTbTm(numtb, numtm, tileMat->TileS, tileMat->TileT);
01060 TessBlocks[numtb].NearVertexList.remove(nv);
01061 nv->OwnerBlock= NULL;
01062
01063
01064 decRefTessBlocks();
01065 }
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079 void CPatch::makeRoots()
01080 {
01081 CTessVertex *a= BaseVertices[0];
01082 CTessVertex *b= BaseVertices[1];
01083 CTessVertex *c= BaseVertices[2];
01084 CTessVertex *d= BaseVertices[3];
01085
01086
01087 a->Pos= a->StartPos= a->EndPos= computeVertex(0,0);
01088 b->Pos= b->StartPos= b->EndPos= computeVertex(0,1);
01089 c->Pos= c->StartPos= c->EndPos= computeVertex(1,1);
01090 d->Pos= d->StartPos= d->EndPos= computeVertex(1,0);
01091
01092
01093 CTessFarVertex *fa= &BaseFarVertices[0];
01094 CTessFarVertex *fb= &BaseFarVertices[1];
01095 CTessFarVertex *fc= &BaseFarVertices[2];
01096 CTessFarVertex *fd= &BaseFarVertices[3];
01097 fa->Src= a;
01098 fa->PCoord.setST(0,0);
01099 fb->Src= b;
01100 fb->PCoord.setST(0,1);
01101 fc->Src= c;
01102 fc->PCoord.setST(1,1);
01103 fd->Src= d;
01104 fd->PCoord.setST(1,0);
01105
01106
01107
01108 nlassert(RenderClipped==true);
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 nlassert(Son0==NULL);
01133 nlassert(Son1==NULL);
01134 Son0= getLandscape()->newTessFace();
01135 Son1= getLandscape()->newTessFace();
01136
01137
01138 Son0->Patch= this;
01139 Son0->Level= 0;
01140 if(OrderS>=OrderT)
01141 {
01142 Son0->VBase= b;
01143 Son0->VLeft= c;
01144 Son0->VRight= a;
01145 Son0->FVBase= fb;
01146 Son0->FVLeft= fc;
01147 Son0->FVRight= fa;
01148 Son0->PVBase.setST(0, 1);
01149 Son0->PVLeft.setST(1, 1);
01150 Son0->PVRight.setST(0, 0);
01151 }
01152 else
01153 {
01154 Son0->VBase= a;
01155 Son0->VLeft= b;
01156 Son0->VRight= d;
01157 Son0->FVBase= fa;
01158 Son0->FVLeft= fb;
01159 Son0->FVRight= fd;
01160 Son0->PVBase.setST(0, 0);
01161 Son0->PVLeft.setST(0, 1);
01162 Son0->PVRight.setST(1, 0);
01163 }
01164 Son0->FBase= Son1;
01165 Son0->FLeft= NULL;
01166 Son0->FRight= NULL;
01167
01168 Son0->Size= ErrorSize/2;
01169 Son0->computeSplitPoint();
01170
01171
01172 Son1->Patch= this;
01173 Son1->Level= 0;
01174 if(OrderS>=OrderT)
01175 {
01176 Son1->VBase= d;
01177 Son1->VLeft= a;
01178 Son1->VRight= c;
01179 Son1->FVBase= fd;
01180 Son1->FVLeft= fa;
01181 Son1->FVRight= fc;
01182 Son1->PVBase.setST(1, 0);
01183 Son1->PVLeft.setST(0, 0);
01184 Son1->PVRight.setST(1, 1);
01185 }
01186 else
01187 {
01188 Son1->VBase= c;
01189 Son1->VLeft= d;
01190 Son1->VRight= b;
01191 Son1->FVBase= fc;
01192 Son1->FVLeft= fd;
01193 Son1->FVRight= fb;
01194 Son1->PVBase.setST(1, 1);
01195 Son1->PVLeft.setST(1, 0);
01196 Son1->PVRight.setST(0, 1);
01197 }
01198 Son1->FBase= Son0;
01199 Son1->FLeft= NULL;
01200 Son1->FRight= NULL;
01201
01202 Son1->Size= ErrorSize/2;
01203 Son1->computeSplitPoint();
01204
01205
01206
01207 clearTessBlocks();
01208 resetMasterBlock();
01209 appendFarVertexToRenderList(fa);
01210 appendFarVertexToRenderList(fb);
01211 appendFarVertexToRenderList(fc);
01212 appendFarVertexToRenderList(fd);
01213 appendFaceToRenderList(Son0);
01214 appendFaceToRenderList(Son1);
01215
01216
01217
01218
01219
01220 Son0->VBase->MaxFaceSize= 1;
01221 Son0->VLeft->MaxFaceSize= 1;
01222 Son0->VRight->MaxFaceSize= 1;
01223 Son1->VBase->MaxFaceSize= 1;
01224 Son1->VLeft->MaxFaceSize= 1;
01225 Son1->VRight->MaxFaceSize= 1;
01226
01227 Son0->VBase->MaxNearLimit= 1;
01228 Son0->VLeft->MaxNearLimit= 1;
01229 Son0->VRight->MaxNearLimit= 1;
01230 Son1->VBase->MaxNearLimit= 1;
01231 Son1->VLeft->MaxNearLimit= 1;
01232 Son1->VRight->MaxNearLimit= 1;
01233
01234 }
01235
01236
01237
01238 void CPatch::compile(CZone *z, uint patchId, uint8 orderS, uint8 orderT, CTessVertex *baseVertices[4], float errorSize)
01239 {
01240 nlassert(z);
01241 Zone= z;
01242
01243
01244
01245 _ULNearPrec= this;
01246 _ULNearNext= this;
01247
01248
01249
01250
01251 Pass0.Patch= this;
01252 Pass1.Patch= this;
01253
01254
01255 MasterBlock.init(this);
01256
01257
01258 nlassert(patchId<0x10000);
01259 PatchId= (uint16)patchId;
01260
01261 if(errorSize==0)
01262 computeDefaultErrorSize();
01263 else
01264 ErrorSize= errorSize;
01265
01266 nlassert(orderS==2 || orderS==4 || orderS==8 || orderS==16);
01267 nlassert(orderT==2 || orderT==4 || orderT==8 || orderT==16);
01268 nlassert (OrderS==orderS);
01269 nlassert (OrderT==orderT);
01270
01271
01272 sint ps= getPowerOf2(orderS) , pt= getPowerOf2(orderT);
01273 sint pmin= min(ps,pt);
01274 sint pmax= max(ps,pt);
01275
01276
01277
01278
01279 TileLimitLevel= pmin*2 + pmax-pmin;
01280
01281 TessBlockLimitLevel= TileLimitLevel-2;
01282
01283
01284
01285 SquareLimitLevel= pmax-pmin;
01286
01287
01288 CAABBox bb= buildBBox();
01289 BSphere.Center= bb.getCenter();
01290 BSphere.Radius= bb.getRadius();
01291
01292
01293 BaseVertices[0]= baseVertices[0];
01294 BaseVertices[1]= baseVertices[1];
01295 BaseVertices[2]= baseVertices[2];
01296 BaseVertices[3]= baseVertices[3];
01297
01298
01299 makeRoots();
01300 }
01301
01302 CVector CPatch::computeVertex(float s, float t) const
01303 {
01304
01305
01306 if(getLandscape()->getNoiseMode())
01307 {
01308
01309 CVector displace;
01310 computeNoise(s,t, displace);
01311
01312
01313
01314 CBezierPatch *patch= unpackIntoCache();
01315 return patch->eval(s,t) + displace;
01316 }
01317 else
01318 {
01319
01320 CBezierPatch *patch= unpackIntoCache();
01321 return patch->eval(s,t);
01322 }
01323 }
01324
01325
01326
01327 CVector CPatch::computeContinousVertex(float s, float t) const
01328 {
01329
01330 nlassert(Zone);
01331
01332
01333 sint edgeIdS= -1;
01334 sint edgeIdT= -1;
01335 if(s==0) edgeIdS= 0;
01336 else if(s==1) edgeIdS= 2;
01337 if(t==0) edgeIdT= 3;
01338 else if(t==1) edgeIdT= 1;
01339
01340
01341 if(edgeIdS>=0 && edgeIdT>=0)
01342 {
01343
01344 if(edgeIdS==0 && edgeIdT==3) return BaseVertices[0]->EndPos;
01345 if(edgeIdS==0 && edgeIdT==1) return BaseVertices[1]->EndPos;
01346 if(edgeIdS==2 && edgeIdT==1) return BaseVertices[2]->EndPos;
01347 if(edgeIdS==2 && edgeIdT==3) return BaseVertices[3]->EndPos;
01348 nlstop;
01349
01350 return CVector::Null;
01351 }
01352
01353 else if(edgeIdS>=0 || edgeIdT>=0)
01354 {
01355
01356 CVector vertexOnMe= computeVertex(s,t);
01357
01358
01359 sint edgeId;
01360 if(edgeIdS>=0)
01361 edgeId= edgeIdS;
01362 else
01363 edgeId= edgeIdT;
01364
01365
01366 CBindInfo bindInfo;
01367 getBindNeighbor(edgeId, bindInfo);
01368
01369 if(!bindInfo.Zone)
01370 {
01371 return vertexOnMe;
01372 }
01373
01374 else
01375 {
01376
01377 CPatchUVLocator uvLocator;
01378 uvLocator.build(this, edgeId, bindInfo);
01379
01380
01381 CVector2f stTileIn, stTileOut;
01382 stTileIn.x= s * getOrderS();
01383 stTileIn.y= t * getOrderT();
01384
01385
01386 uint pid= uvLocator.selectPatch(stTileIn);
01387 CPatch *nebPatch;
01388 uvLocator.locateUV(stTileIn, pid, nebPatch, stTileOut);
01389
01390
01391 stTileOut.x/= nebPatch->getOrderS();
01392 stTileOut.y/= nebPatch->getOrderT();
01393
01394
01395
01396
01397 bool onCorner;
01398 CVector vertexOnNeb= nebPatch->computeVertexButCorner(stTileOut.x, stTileOut.y, onCorner);
01399
01400
01401 if(onCorner)
01402 return vertexOnNeb;
01403 else
01404 {
01405
01406 vertexOnMe+= vertexOnNeb;
01407 vertexOnMe/= 2;
01408 return vertexOnMe;
01409 }
01410 }
01411
01412 }
01413
01414 else
01415 return computeVertex(s, t);
01416 }
01417
01418
01419
01420 CVector CPatch::computeVertexButCorner(float s, float t, bool &onCorner) const
01421 {
01422
01423 nlassert(Zone);
01424
01425
01426 sint edgeIdS= -1;
01427 sint edgeIdT= -1;
01428 if(s==0) edgeIdS= 0;
01429 else if(s==1) edgeIdS= 2;
01430 if(t==0) edgeIdT= 3;
01431 else if(t==1) edgeIdT= 1;
01432
01433
01434 if(edgeIdS>=0 && edgeIdT>=0)
01435 {
01436
01437 onCorner= true;
01438
01439 if(edgeIdS==0 && edgeIdT==3) return BaseVertices[0]->EndPos;
01440 if(edgeIdS==0 && edgeIdT==1) return BaseVertices[1]->EndPos;
01441 if(edgeIdS==2 && edgeIdT==1) return BaseVertices[2]->EndPos;
01442 if(edgeIdS==2 && edgeIdT==3) return BaseVertices[3]->EndPos;
01443 nlstop;
01444
01445 return CVector::Null;
01446 }
01447
01448 else
01449 {
01450 onCorner= false;
01451 return computeVertex(s, t);
01452 }
01453 }
01454
01455
01456
01457 void CPatch::refineAll()
01458 {
01459
01460 nlassert(Son0);
01461 nlassert(Son1);
01462 Son0->refineAll();
01463 Son1->refineAll();
01464 }
01465
01466
01467
01468
01469 void CPatch::averageTesselationVertices()
01470 {
01471 nlassert(Son0);
01472 nlassert(Son1);
01473
01474
01475
01476
01477 CTessVertex *a= BaseVertices[0];
01478 CTessVertex *b= BaseVertices[1];
01479 CTessVertex *c= BaseVertices[2];
01480 CTessVertex *d= BaseVertices[3];
01481
01482 a->Pos= a->StartPos= a->EndPos= computeVertex(0,0);
01483 b->Pos= b->StartPos= b->EndPos= computeVertex(0,1);
01484 c->Pos= c->StartPos= c->EndPos= computeVertex(1,1);
01485 d->Pos= d->StartPos= d->EndPos= computeVertex(1,0);
01486
01487
01488
01489 Son0->averageTesselationVertices();
01490 Son1->averageTesselationVertices();
01491 }
01492
01493
01494
01495 void CPatch::refreshTesselationGeometry()
01496 {
01497 nlassert(Son0);
01498 nlassert(Son1);
01499
01500
01501 CTessVertex *a= BaseVertices[0];
01502 CTessVertex *b= BaseVertices[1];
01503 CTessVertex *c= BaseVertices[2];
01504 CTessVertex *d= BaseVertices[3];
01505
01506 a->Pos= a->StartPos= a->EndPos= computeVertex(0,0);
01507 b->Pos= b->StartPos= b->EndPos= computeVertex(0,1);
01508 c->Pos= c->StartPos= c->EndPos= computeVertex(1,1);
01509 d->Pos= d->StartPos= d->EndPos= computeVertex(1,0);
01510
01511
01512
01513 Son0->refreshTesselationGeometry();
01514 Son1->refreshTesselationGeometry();
01515 }
01516
01517
01518
01519
01520 void CPatch::clip(const std::vector<CPlane> &pyramid)
01521 {
01522 Clipped= false;
01523 for(sint i=0;i<(sint)pyramid.size();i++)
01524 {
01525
01526 if(!BSphere.clipBack(pyramid[i]))
01527 {
01528 Clipped= true;
01529 break;
01530 }
01531 }
01532
01533
01534 RenderClipped= Clipped;
01535 }
01536
01537
01538
01539 void CPatch::resetRenderFar()
01540 {
01541 if (Pass0.PatchRdrPass)
01542 {
01543
01544 Zone->Landscape->freeFarRenderPass (this, Pass0.PatchRdrPass, Far0);
01545 Pass0.PatchRdrPass= NULL;
01546 }
01547 if (Pass1.PatchRdrPass)
01548 {
01549
01550 Zone->Landscape->freeFarRenderPass (this, Pass1.PatchRdrPass, Far1);
01551 Pass1.PatchRdrPass= NULL;
01552 }
01553
01554 Far0= -1;
01555 Far1= -1;
01556 }
01557
01558
01559
01560 void CPatch::serial(NLMISC::IStream &f)
01561 {
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581 uint ver= f.serialVersion(_Version);
01582
01583
01584
01585 if (ver<2)
01586 {
01587 throw EOlderStream(f);
01588 }
01589
01590 f.xmlSerial (Vertices[0], Vertices[1], Vertices[2], Vertices[3], "VERTICIES");
01591
01592 f.xmlPush ("TANGENTS");
01593 f.serial (Tangents[0], Tangents[1], Tangents[2], Tangents[3]);
01594 f.serial (Tangents[4], Tangents[5], Tangents[6], Tangents[7]);
01595 f.xmlPop ();
01596
01597 f.xmlSerial (Interiors[0], Interiors[1], Interiors[2], Interiors[3], "INTERIORS");
01598
01599 f.xmlPush ("TILES");
01600 f.serialCont(Tiles);
01601 f.xmlPop ();
01602
01603 if(ver>=1)
01604 {
01605
01606 if(ver<=6)
01607 {
01608 nlassert(f.isReading());
01609
01610
01611 vector<CTileColorOldPatchVersion6> tmpArray;
01612 f.xmlPush ("TILE_COLORS");
01613 f.serialCont(tmpArray);
01614 f.xmlPop ();
01615
01616
01617 TileColors.resize(tmpArray.size());
01618 if(TileColors.size()>0)
01619 {
01620 memcpy(&TileColors[0], &tmpArray[0], TileColors.size()*sizeof(CTileColor));
01621 }
01622 }
01623 else
01624 {
01625
01626 f.xmlPush ("TILE_COLORS");
01627 f.serialCont(TileColors);
01628 f.xmlPop ();
01629 }
01630 }
01631 if(ver>=2)
01632 {
01633 f.xmlSerial (OrderS, "ORDER_S");
01634 f.xmlSerial (OrderT, "ORDER_T");
01635
01636 f.xmlPush ("COMPRESSED_LUMELS");
01637 f.serialCont(CompressedLumels);
01638 f.xmlPop ();
01639 }
01640
01641 if(ver>=3)
01642 {
01643 f.xmlSerial (NoiseRotation, "NOISE_ROTATION");
01644 f.xmlSerial (_CornerSmoothFlag, "CORNER_SMOOTH_FLAG");
01645 }
01646 else
01647 {
01648
01649 NoiseRotation= 0;
01650 _CornerSmoothFlag= 0;
01651 }
01652 if(ver>=4)
01653 {
01654 f.xmlSerial(Flags, "FLAGS");
01655 }
01656 else
01657 {
01658 Flags=NL_PATCH_SMOOTH_FLAG_MASK;
01659 }
01660
01661
01662 if(ver>=5)
01663 {
01664 f.xmlPush ("TILE_LIGHT_INFLUENCES");
01665 f.serialCont(TileLightInfluences);
01666 f.xmlPop ();
01667 }
01668 else
01669 {
01670 if(f.isReading())
01671 {
01672
01673 resetTileLightInfluences();
01674 }
01675 }
01676
01677
01678 if(ver<6 && f.isReading())
01679 {
01680
01681 for(uint i=0; i<Tiles.size(); i++)
01682 {
01683 Tiles[i].setVegetableState(CTileElement::AboveWater);
01684 }
01685 }
01686
01687
01688 }
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701 void CPatch::unbind()
01702 {
01703 nlassert(Son0 && Son1);
01704
01705 Son0->unbind();
01706 Son1->unbind();
01707 Son0->forceMerge();
01708 Son1->forceMerge();
01709
01710 nlassert(Son0->isLeaf() && Son1->isLeaf());
01711
01712 nlassert(Son0->FLeft == NULL);
01713 nlassert(Son0->FRight == NULL);
01714 nlassert(Son1->FLeft == NULL);
01715 nlassert(Son1->FRight == NULL);
01716
01717
01718
01719 _BindZoneNeighbor[0]= NULL;
01720 _BindZoneNeighbor[1]= NULL;
01721 _BindZoneNeighbor[2]= NULL;
01722 _BindZoneNeighbor[3]= NULL;
01723
01724 }
01725
01726
01727
01728 CTessFace *CPatch::getRootFaceForEdge(sint edge) const
01729 {
01730 nlassert(edge>=0 && edge<=3);
01731
01732
01733 if(OrderS>=OrderT)
01734 {
01735 if(edge==0 || edge==1)
01736 return Son0;
01737 else
01738 return Son1;
01739 }
01740 else
01741 {
01742 if(edge==0 || edge==3)
01743 return Son0;
01744 else
01745 return Son1;
01746 }
01747 }
01748
01749
01750 CTessVertex *CPatch::getRootVertexForEdge(sint edge) const
01751 {
01752
01753 nlassert(edge>=0 && edge<=3);
01754
01755
01756 if(OrderS>=OrderT)
01757 {
01758 switch(edge)
01759 {
01760 case 0: return Son0->VRight;
01761 case 1: return Son0->VBase;
01762 case 2: return Son0->VLeft;
01763 case 3: return Son1->VBase;
01764 default: return NULL;
01765 }
01766 }
01767 else
01768 {
01769 switch(edge)
01770 {
01771 case 0: return Son0->VBase;
01772 case 1: return Son0->VLeft;
01773 case 2: return Son1->VBase;
01774 case 3: return Son0->VRight;
01775 default: return NULL;
01776 }
01777 }
01778 }
01779
01780
01781
01782 void CPatch::changeEdgeNeighbor(sint edge, CTessFace *to)
01783 {
01784 nlassert(edge>=0 && edge<=3);
01785
01786
01787 if(OrderS>=OrderT)
01788 {
01789 switch(edge)
01790 {
01791 case 0: Son0->FRight= to; break;
01792 case 1: Son0->FLeft= to; break;
01793 case 2: Son1->FRight= to; break;
01794 case 3: Son1->FLeft= to; break;
01795 }
01796 }
01797 else
01798 {
01799 switch(edge)
01800 {
01801 case 0: Son0->FLeft= to; break;
01802 case 1: Son1->FRight= to; break;
01803 case 2: Son1->FLeft= to; break;
01804 case 3: Son0->FRight= to; break;
01805 }
01806 }
01807 }
01808
01809
01810
01811 CTessFace *CPatch::linkTessFaceWithEdge(const CVector2f &uv0, const CVector2f &uv1, CTessFace *linkTo)
01812 {
01813 nlassert(Son0 && Son1);
01814
01815 CTessFace *face= Son0->linkTessFaceWithEdge(uv0, uv1, linkTo);
01816
01817 if(!face)
01818 face= Son1->linkTessFaceWithEdge(uv0, uv1, linkTo);
01819 return face;
01820 }
01821
01822
01823
01824 void CPatch::bind(CBindInfo Edges[4], bool rebind)
01825 {
01826
01827
01828 static CTessFace bind1_2[4];
01829 static CTessFace bind1_4[8];
01830
01831
01832
01833 nlassert(Son0 && Son1);
01834 nlassert(Son0->isLeaf() && Son1->isLeaf());
01835 nlassert(Son0->FLeft == NULL);
01836 nlassert(Son0->FRight == NULL);
01837 nlassert(Son1->FLeft == NULL);
01838 nlassert(Son1->FRight == NULL);
01839
01840
01841
01842 sint i;
01843 for(i=0;i<4;i++)
01844 {
01845
01846 _BindZoneNeighbor[i]= Edges[i].Zone;
01847 }
01848
01849
01850 if(!rebind)
01851 {
01852
01853 CTessVertex *a= BaseVertices[0];
01854 CTessVertex *b= BaseVertices[1];
01855 CTessVertex *c= BaseVertices[2];
01856 CTessVertex *d= BaseVertices[3];
01857
01858 a->Pos= a->StartPos= a->EndPos= computeVertex(0,0);
01859 b->Pos= b->StartPos= b->EndPos= computeVertex(0,1);
01860 c->Pos= c->StartPos= c->EndPos= computeVertex(1,1);
01861 d->Pos= d->StartPos= d->EndPos= computeVertex(1,0);
01862
01863
01864 Son0->computeSplitPoint();
01865 Son1->computeSplitPoint();
01866 }
01867 else
01868 {
01869
01870
01871 checkFillVertexVBFar(Son0->FVBase);
01872 checkFillVertexVBFar(Son0->FVLeft);
01873 checkFillVertexVBFar(Son0->FVRight);
01874 checkFillVertexVBFar(Son1->FVBase);
01875 }
01876
01877
01878
01879 for(i=0;i<4;i++)
01880 {
01881 CBindInfo &bind= Edges[i];
01882
01883 nlassert(bind.NPatchs==0 || bind.NPatchs==1 || bind.NPatchs==2 || bind.NPatchs==4 || bind.NPatchs==5);
01884 if(bind.NPatchs==1)
01885 {
01886
01887 this->changeEdgeNeighbor(i, bind.Next[0]->getRootFaceForEdge(bind.Edge[0]));
01888
01889 bind.Next[0]->changeEdgeNeighbor(bind.Edge[0], this->getRootFaceForEdge(i));
01890 }
01891 else if(bind.NPatchs==2)
01892 {
01893
01894 this->changeEdgeNeighbor(i, bind1_2+i);
01895 bind1_2[i].FBase= this->getRootFaceForEdge(i);
01896
01897
01898 bind1_2[i].SonRight= bind.Next[0]->getRootFaceForEdge(bind.Edge[0]);
01899 bind1_2[i].SonLeft= bind.Next[1]->getRootFaceForEdge(bind.Edge[1]);
01900 bind1_2[i].VBase= bind.Next[0]->getRootVertexForEdge(bind.Edge[0]);
01901
01902 bind.Next[0]->changeEdgeNeighbor(bind.Edge[0], &CTessFace::MultipleBindFace);
01903 bind.Next[1]->changeEdgeNeighbor(bind.Edge[1], &CTessFace::MultipleBindFace);
01904 }
01905 else if(bind.NPatchs==4)
01906 {
01907
01908 this->changeEdgeNeighbor(i, bind1_2+i);
01909 bind1_2[i].FBase= this->getRootFaceForEdge(i);
01910
01911
01912
01913 bind1_2[i].SonRight= bind1_4 + 2*i+0;
01914 bind1_2[i].SonLeft= bind1_4 + 2*i+1;
01915 bind1_2[i].VBase= bind.Next[1]->getRootVertexForEdge(bind.Edge[1]);
01916
01917 bind1_4[2*i+0].FBase= &CTessFace::MultipleBindFace;
01918 bind1_4[2*i+0].SonRight= bind.Next[0]->getRootFaceForEdge(bind.Edge[0]);
01919 bind1_4[2*i+0].SonLeft= bind.Next[1]->getRootFaceForEdge(bind.Edge[1]);
01920 bind1_4[2*i+0].VBase= bind.Next[0]->getRootVertexForEdge(bind.Edge[0]);
01921
01922 bind1_4[2*i+1].FBase= &CTessFace::MultipleBindFace;
01923 bind1_4[2*i+1].SonRight= bind.Next[2]->getRootFaceForEdge(bind.Edge[2]);
01924 bind1_4[2*i+1].SonLeft= bind.Next[3]->getRootFaceForEdge(bind.Edge[3]);
01925 bind1_4[2*i+1].VBase= bind.Next[2]->getRootVertexForEdge(bind.Edge[2]);
01926
01927
01928 bind.Next[0]->changeEdgeNeighbor(bind.Edge[0], &CTessFace::MultipleBindFace);
01929 bind.Next[1]->changeEdgeNeighbor(bind.Edge[1], &CTessFace::MultipleBindFace);
01930 bind.Next[2]->changeEdgeNeighbor(bind.Edge[2], &CTessFace::MultipleBindFace);
01931 bind.Next[3]->changeEdgeNeighbor(bind.Edge[3], &CTessFace::MultipleBindFace);
01932 }
01933 else if(bind.NPatchs==5)
01934 {
01935
01936
01937
01938
01939
01940
01941
01942
01943 CVector2f uvi0, uvi1;
01944 switch(i)
01945 {
01946 case 0: uvi0.set(0,0); uvi1.set(0,1); break;
01947 case 1: uvi0.set(0,1); uvi1.set(1,1); break;
01948 case 2: uvi0.set(1,1); uvi1.set(1,0); break;
01949 case 3: uvi0.set(1,0); uvi1.set(0,0); break;
01950 };
01951
01952 uvi0.x*= OrderS;
01953 uvi0.y*= OrderT;
01954 uvi1.x*= OrderS;
01955 uvi1.y*= OrderT;
01956
01957 CBindInfo bindInfo;
01958 getBindNeighbor(i, bindInfo);
01959 nlassert(bindInfo.Zone!=NULL && bindInfo.NPatchs==1);
01960 CPatchUVLocator puvloc;
01961 puvloc.build(this, i, bindInfo);
01962
01963
01964 CVector2f uvo0, uvo1;
01965 uint pid;
01966 CPatch *patchNeighbor;
01967
01968 pid= puvloc.selectPatch(uvi0);
01969 puvloc.locateUV(uvi0, pid, patchNeighbor, uvo0);
01970 nlassert(patchNeighbor == bindInfo.Next[0]);
01971
01972 pid= puvloc.selectPatch(uvi1);
01973 puvloc.locateUV(uvi1, pid, patchNeighbor, uvo1);
01974 nlassert(patchNeighbor == bindInfo.Next[0]);
01975
01976 uvo0.x/= patchNeighbor->OrderS;
01977 uvo0.y/= patchNeighbor->OrderT;
01978 uvo1.x/= patchNeighbor->OrderS;
01979 uvo1.y/= patchNeighbor->OrderT;
01980
01981
01982 CTessFace *faceNeighbor;
01983 faceNeighbor= patchNeighbor->linkTessFaceWithEdge(uvo0, uvo1, this->getRootFaceForEdge(i));
01984 nlassert(faceNeighbor);
01985
01986 this->changeEdgeNeighbor(i, faceNeighbor);
01987 }
01988
01989 }
01990
01991
01992 Son0->updateBind();
01993 Son1->updateBind();
01994
01995 }
01996
01997
01998
01999 void CPatch::forceMergeAtTileLevel()
02000 {
02001 nlassert(Son0 && Son1);
02002
02003 Son0->forceMergeAtTileLevel();
02004 Son1->forceMergeAtTileLevel();
02005 }
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017 CPatchRdrPass *CPatch::getTileRenderPass(sint tileId, sint pass)
02018 {
02019
02020 nlassert(pass==NL3D_TILE_PASS_RGB0 || pass==NL3D_TILE_PASS_RGB1 || pass==NL3D_TILE_PASS_RGB2 ||
02021 pass==NL3D_TILE_PASS_ADD);
02022
02023 bool additive= (pass==NL3D_TILE_PASS_ADD);
02024 sint passNum= pass-NL3D_TILE_PASS_RGB0;
02025
02026 if(additive)
02027 {
02028
02029 passNum= 0;
02030
02031 if(Tiles[tileId].Tile[1]!=0xFFFF)
02032 {
02033 passNum= 1;
02034
02035 if(Tiles[tileId].Tile[2]!=0xFFFF)
02036 passNum= 2;
02037 }
02038 }
02039
02040 sint tileNumber= Tiles[tileId].Tile[passNum];
02041 if(tileNumber==0xFFFF)
02042 {
02043
02044 if(pass==NL3D_TILE_PASS_RGB0)
02045 return Zone->Landscape->getTileRenderPass(0xFFFF, false);
02046
02047 return NULL;
02048 }
02049 else
02050 {
02051
02052 return Zone->Landscape->getTileRenderPass(tileNumber, additive);
02053 }
02054 }
02055
02056
02057 void CPatch::getTileUvInfo(sint tileId, sint pass, bool alpha, uint8 &orient, CVector &uvScaleBias, bool &is256x256, uint8 &uvOff)
02058 {
02059
02060 nlassert(pass==NL3D_TILE_PASS_RGB0 || pass==NL3D_TILE_PASS_RGB1 || pass==NL3D_TILE_PASS_RGB2 ||
02061 pass==NL3D_TILE_PASS_ADD);
02062
02063 bool additive= (pass==NL3D_TILE_PASS_ADD);
02064 sint passNum= pass-NL3D_TILE_PASS_RGB0;
02065
02066 if(additive)
02067 {
02068
02069 passNum= 0;
02070
02071 if(Tiles[tileId].Tile[1]!=0xFFFF)
02072 {
02073 passNum= 1;
02074
02075 if(Tiles[tileId].Tile[2]!=0xFFFF)
02076 passNum= 2;
02077 }
02078 }
02079
02080 sint tileNumber= Tiles[tileId].Tile[passNum];
02081 if(tileNumber==0xFFFF)
02082 {
02083
02084 orient= 0;
02085 uvScaleBias.x=0;
02086 uvScaleBias.y=0;
02087 uvScaleBias.z=1;
02088 is256x256=false;
02089 uvOff=0;
02090 }
02091 else
02092 {
02093 orient= Tiles[tileId].getTileOrient(passNum);
02094 Tiles[tileId].getTile256Info(is256x256, uvOff);
02095 CTile::TBitmap type;
02096
02097 if(alpha)
02098 type= CTile::alpha;
02099 else
02100 {
02101 if(additive)
02102 type= CTile::additive;
02103 else
02104 type= CTile::diffuse;
02105 }
02106
02107 uint8 rotalpha;
02108 Zone->Landscape->getTileUvScaleBiasRot(tileNumber, type, uvScaleBias, rotalpha);
02109
02110
02111 if(alpha)
02112 orient= (orient+rotalpha)&3;
02113 }
02114
02115 }
02116
02117
02118
02119 void CPatch::deleteTileUvs()
02120 {
02121 Son0->deleteTileUvs();
02122 Son1->deleteTileUvs();
02123 }
02124
02125
02126
02127 void CPatch::recreateTileUvs()
02128 {
02129
02130 for(sint tb=0; tb<(sint)TessBlocks.size();tb++)
02131 {
02132
02133 TessBlocks[tb].NearVertexList.clear();
02134 for(sint i=0;i<NL3D_TESSBLOCK_TILESIZE;i++)
02135 {
02136 CTileMaterial *tm= TessBlocks[tb].RdrTileRoot[i];
02137 if(tm)
02138 {
02139 for(sint pass=0;pass<NL3D_MAX_TILE_FACE;pass++)
02140 {
02141 tm->TileFaceList[pass].clear();
02142 }
02143 }
02144 }
02145 }
02146
02147 Son0->recreateTileUvs();
02148 Son1->recreateTileUvs();
02149 }
02150
02151
02152
02153 void CPatch::appendTessellationLeaves(std::vector<const CTessFace*> &leaves) const
02154 {
02155 nlassert(Son0);
02156 nlassert(Son1);
02157 Son0->appendTessellationLeaves(leaves);
02158 Son1->appendTessellationLeaves(leaves);
02159 }
02160
02161
02162
02163 CLandscape *CPatch::getLandscape () const
02164 {
02165 return Zone->getLandscape();
02166 }
02167
02168
02169
02170
02171
02172
02173 uint8 CPatch::getOrderForEdge(sint8 edge) const
02174 {
02175 uint e= ((sint)edge + 256)&3;
02176
02177 if( e&1 ) return OrderS;
02178 else return OrderT;
02179 }
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190 void CPatch::getBindNeighbor(uint edge, CBindInfo &neighborEdge) const
02191 {
02192 nlassert(edge<4);
02193
02194 if(_BindZoneNeighbor[edge]!=NULL)
02195 {
02196 getZone()->buildBindInfo(PatchId, edge, _BindZoneNeighbor[edge], neighborEdge);
02197 }
02198 else
02199 {
02200 neighborEdge.Zone= NULL;
02201 neighborEdge.NPatchs= 0;
02202 neighborEdge.MultipleBindNum= 0;
02203 }
02204 }
02205
02206
02208
02209 {
02210 for (uint s = 0; s <= OrderS; ++s)
02211 {
02212 for (uint t = 0; t <= OrderT; ++t)
02213 {
02214 uint index = std::min(t, (uint) (OrderT - 1)) * OrderS
02215 + std::min(s, (uint) (OrderS - 1));
02216 TileColors[s + t * (OrderS + 1)].Color565 = colors[(uint) (Tiles[index].getVegetableState())].get565();
02217 }
02218 }
02219 }
02220
02221
02222 void CPatch::copyTileFlagsFromPatch(const CPatch *src)
02223 {
02224 nlassert(OrderS == src->OrderS
02225 && OrderT == src->OrderT);
02226
02227 for (uint k = 0; k < Tiles.size(); ++k)
02228 {
02229 Tiles[k].copyFlagsFromOther(src->Tiles[k]);
02230 }
02231 }
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242 CTileElement *CPatch::getTileElement(const CUV &uv)
02243 {
02244
02245 sint ts, tt;
02246
02247
02248
02249 ts= OptFastFloor(uv.U* (OrderS<<8) + 128); ts>>=8;
02250 tt= OptFastFloor(uv.V* (OrderT<<8) + 128); tt>>=8;
02251 clamp(ts, 0, OrderS-1);
02252 clamp(tt, 0, OrderT-1);
02253
02254
02255 return &(Tiles[ts+tt*OrderS]);
02256 }
02257
02258
02259 }
02260