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 #include "3d/zone.h"
00029 #include "3d/landscape.h"
00030 #include "3d/zone_symmetrisation.h"
00031 #include "nel/misc/common.h"
00032
00033
00034 using namespace NLMISC;
00035 using namespace std;
00036
00037
00038
00039
00040
00041
00042 namespace NL3D
00043 {
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 void CPatchInfo::setCornerSmoothFlag(uint corner, bool smooth)
00056 {
00057 nlassert(corner<=3);
00058 uint mask= 1<<corner;
00059 if(smooth)
00060 _CornerSmoothFlag|= mask;
00061 else
00062 _CornerSmoothFlag&= ~mask;
00063 }
00064
00065
00066 bool CPatchInfo::getCornerSmoothFlag(uint corner) const
00067 {
00068 nlassert(corner<=3);
00069 uint mask= 1<<corner;
00070 return (_CornerSmoothFlag & mask)!=0;
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 CZone::CZone()
00083 {
00084 ZoneId= 0;
00085 Compiled= false;
00086 Landscape= NULL;
00087 ClipResult= ClipOut;
00088 }
00089
00090 CZone::~CZone()
00091 {
00092
00093 nlassert(!Compiled);
00094 }
00095
00096
00097
00098 void CZone::computeBBScaleBias(const CAABBox &bb)
00099 {
00100 ZoneBB= bb;
00101
00102 ZoneBB.setHalfSize(ZoneBB.getHalfSize()+CVector(NL3D_NOISE_MAX, NL3D_NOISE_MAX, NL3D_NOISE_MAX));
00103 CVector hs= ZoneBB.getHalfSize();
00104 float rmax= maxof(hs.x, hs.y, hs.z);
00105 PatchScale= rmax / 32760;
00106 PatchBias= ZoneBB.getCenter();
00107 }
00108
00109
00110
00111 void CZone::build(uint16 zoneId, const std::vector<CPatchInfo> &patchs, const std::vector<CBorderVertex> &borderVertices, uint32 numVertices)
00112 {
00113 CZoneInfo zinfo;
00114 zinfo.ZoneId= zoneId;
00115 zinfo.Patchs= patchs;
00116 zinfo.BorderVertices= borderVertices;
00117
00118 build(zinfo, numVertices);
00119 }
00120
00121 void CZone::build(const CZoneInfo &zoneInfo, uint32 numVertices)
00122 {
00123 sint i,j;
00124 nlassert(!Compiled);
00125
00126
00127 uint16 zoneId= zoneInfo.ZoneId;
00128 const std::vector<CPatchInfo> &patchs= zoneInfo.Patchs;
00129 const std::vector<CBorderVertex> &borderVertices= zoneInfo.BorderVertices;
00130
00131
00132 ZoneId= zoneId;
00133 BorderVertices= borderVertices;
00134
00135
00136
00137 CAABBox bb;
00138 if(patchs.size())
00139 bb.setCenter(patchs[0].Patch.Vertices[0]);
00140 bb.setHalfSize(CVector::Null);
00141 for(j=0;j<(sint)patchs.size();j++)
00142 {
00143 const CBezierPatch &p= patchs[j].Patch;
00144 for(i=0;i<4;i++)
00145 bb.extend(p.Vertices[i]);
00146 for(i=0;i<8;i++)
00147 bb.extend(p.Tangents[i]);
00148 for(i=0;i<4;i++)
00149 bb.extend(p.Interiors[i]);
00150 }
00151
00152 computeBBScaleBias(bb);
00153
00154
00155
00156
00157 Patchs.resize(patchs.size());
00158 PatchConnects.resize(patchs.size());
00159 sint maxVertex=-1;
00160 for(j=0;j<(sint)patchs.size();j++)
00161 {
00162 const CPatchInfo &pi= patchs[j];
00163 const CBezierPatch &p= pi.Patch;
00164 CPatch &pa= Patchs[j];
00165 CPatchConnect &pc= PatchConnects[j];
00166
00167
00168 pa.Flags&=~NL_PATCH_SMOOTH_FLAG_MASK;
00169 pa.Flags|=NL_PATCH_SMOOTH_FLAG_MASK&(pi.Flags<<NL_PATCH_SMOOTH_FLAG_SHIFT);
00170
00171
00172
00173
00174 pa.NoiseRotation= pi.NoiseRotation;
00175
00176 for(i=0;i<4;i++)
00177 {
00178 pa.setCornerSmoothFlag(i, pi.getCornerSmoothFlag(i));
00179 }
00180
00181
00182 pa.OrderS= pi.OrderS;
00183 pa.OrderT= pi.OrderT;
00184
00185
00186 for(i=0;i<4;i++)
00187 pa.Vertices[i].pack(p.Vertices[i], PatchBias, PatchScale);
00188 for(i=0;i<8;i++)
00189 pa.Tangents[i].pack(p.Tangents[i], PatchBias, PatchScale);
00190 for(i=0;i<4;i++)
00191 pa.Interiors[i].pack(p.Interiors[i], PatchBias, PatchScale);
00192 pa.Tiles= pi.Tiles;
00193 pa.TileColors= pi.TileColors;
00194
00195
00196
00197
00198
00199 if( pi.TileLightInfluences.size()!= (uint)(pi.OrderS/2+1)*(pi.OrderT/2+1) )
00200 {
00201 pa.resetTileLightInfluences();
00202 }
00203 else
00204 {
00205 pa.TileLightInfluences= pi.TileLightInfluences;
00206 }
00207
00208
00209 uint lumelCount=(pi.OrderS*NL_LUMEL_BY_TILE)*(pi.OrderT*NL_LUMEL_BY_TILE);
00210
00211
00212 if (pi.Lumels.size ()==lumelCount)
00213 {
00214
00215 pa.packShadowMap (&pi.Lumels[0]);
00216 }
00217 else
00218 {
00219
00220 pa.resetCompressedLumels ();
00221 }
00222
00223 nlassert(pa.Tiles.size()== (uint)pi.OrderS*pi.OrderT);
00224 nlassert(pa.TileColors.size()== (uint)(pi.OrderS+1)*(pi.OrderT+1));
00225
00226
00227 pc.ErrorSize= pi.ErrorSize;
00228 for(i=0;i<4;i++)
00229 {
00230 pc.BaseVertices[i]= pi.BaseVertices[i];
00231 maxVertex= max((sint)pc.BaseVertices[i], maxVertex);
00232 }
00233 for(i=0;i<4;i++)
00234 pc.BindEdges[i]= pi.BindEdges[i];
00235 }
00236
00237 NumVertices= maxVertex+1;
00238 NumVertices= max((uint32)NumVertices, numVertices);
00239
00240
00241
00242
00243
00244 std::vector<uint> plRemap;
00245 _PointLightArray.build(zoneInfo.PointLights, plRemap);
00246
00247 for(j=0;j<(sint)patchs.size();j++)
00248 {
00249 CPatch &pa= Patchs[j];
00250 for(uint k= 0; k<pa.TileLightInfluences.size(); k++)
00251 {
00252 CTileLightInfluence &tli= pa.TileLightInfluences[k];
00253 for(uint l=0; l<CTileLightInfluence::NumLightPerCorner; l++)
00254 {
00255
00256 if(tli.Light[l]== 0xFF)
00257 break;
00258 else
00259 {
00260
00261 nlassert(tli.Light[l] < _PointLightArray.getPointLights().size());
00262
00263 tli.Light[l]= plRemap[tli.Light[l]];
00264 }
00265
00266 }
00267 }
00268 }
00269 }
00270
00271
00272 void CZone::retrieve(std::vector<CPatchInfo> &patchs, std::vector<CBorderVertex> &borderVertices)
00273 {
00274 CZoneInfo zinfo;
00275
00276 retrieve(zinfo);
00277
00278 patchs= zinfo.Patchs;
00279 borderVertices= zinfo.BorderVertices;
00280 }
00281
00282
00283 void CZone::retrieve(CZoneInfo &zoneInfo)
00284 {
00285 sint i,j;
00286
00287
00288 std::vector<CPatchInfo> &patchs= zoneInfo.Patchs;
00289 std::vector<CBorderVertex> &borderVertices= zoneInfo.BorderVertices;
00290
00291 zoneInfo.ZoneId= getZoneId();
00292
00293
00294
00295
00296 patchs.resize(Patchs.size());
00297 for(j=0;j<(sint)patchs.size();j++)
00298 {
00299 CPatchInfo &pi= patchs[j];
00300 CBezierPatch &p= pi.Patch;
00301 CPatch &pa= Patchs[j];
00302 CPatchConnect &pc= PatchConnects[j];
00303
00304
00305
00306 pi.Flags= (pa.Flags&NL_PATCH_SMOOTH_FLAG_MASK)>>NL_PATCH_SMOOTH_FLAG_SHIFT;
00307
00308
00309
00310
00311 pi.NoiseRotation= pa.NoiseRotation;
00312
00313 for(i=0;i<4;i++)
00314 {
00315 pi.setCornerSmoothFlag(i, pa.getCornerSmoothFlag(i));
00316 }
00317
00318
00319
00320 for(i=0;i<4;i++)
00321 pa.Vertices[i].unpack(p.Vertices[i], PatchBias, PatchScale);
00322 for(i=0;i<8;i++)
00323 pa.Tangents[i].unpack(p.Tangents[i], PatchBias, PatchScale);
00324 for(i=0;i<4;i++)
00325 pa.Interiors[i].unpack(p.Interiors[i], PatchBias, PatchScale);
00326 pi.Tiles= pa.Tiles;
00327 pi.TileColors= pa.TileColors;
00328 pi.TileLightInfluences= pa.TileLightInfluences;
00329 pi.Lumels.resize ((pa.OrderS*4)*(pa.OrderT*4));
00330 pi.Flags=(pa.Flags&NL_PATCH_SMOOTH_FLAG_MASK)>>NL_PATCH_SMOOTH_FLAG_SHIFT;
00331
00332
00333 pa.unpackShadowMap (&pi.Lumels[0]);
00334
00335
00336 pi.OrderS= pa.OrderS;
00337 pi.OrderT= pa.OrderT;
00338 pi.ErrorSize= pc.ErrorSize;
00339 for(i=0;i<4;i++)
00340 {
00341 pi.BaseVertices[i]= pc.BaseVertices[i];
00342 }
00343 for(i=0;i<4;i++)
00344 pi.BindEdges[i]= pc.BindEdges[i];
00345 }
00346
00347
00348
00349 borderVertices= BorderVertices;
00350
00351
00352
00353 zoneInfo.PointLights= _PointLightArray.getPointLights();
00354
00355 }
00356
00357
00358
00359 void CZone::build(const CZone &zone)
00360 {
00361 nlassert(!Compiled);
00362
00363 ZoneId= zone.ZoneId;
00364 BorderVertices= zone.BorderVertices;
00365
00366
00367
00368 ZoneBB= zone.ZoneBB;
00369 PatchScale= zone.PatchScale;
00370 PatchBias= zone.PatchBias;
00371
00372
00373
00374
00375 Patchs= zone.Patchs;
00376 PatchConnects= zone.PatchConnects;
00377
00378
00379
00380 _PointLightArray= zone._PointLightArray;
00381
00382
00383 NumVertices= zone.NumVertices;
00384 }
00385
00386
00387
00388
00389 void CBorderVertex::serial(NLMISC::IStream &f)
00390 {
00391 (void)f.serialVersion(0);
00392
00393 f.xmlSerial (CurrentVertex, "CURRENT_VERTEX");
00394 f.xmlSerial (NeighborZoneId, "NEIGHTBOR_ZONE_ID");
00395 f.xmlSerial (NeighborVertex, "NEIGHTBOR_VERTEX");
00396 }
00397 void CZone::CPatchConnect::serial(NLMISC::IStream &f)
00398 {
00399 uint ver= f.serialVersion(1);
00400
00401 if (ver<1)
00402 f.serial(OldOrderS, OldOrderT, ErrorSize);
00403 else
00404 f.serial(ErrorSize);
00405 f.xmlSerial (BaseVertices[0], BaseVertices[1], BaseVertices[2], BaseVertices[3], "BASE_VERTICES");
00406 f.xmlSerial (BindEdges[0], BindEdges[1], BindEdges[2], BindEdges[3], "BIND_EDGES");
00407 }
00408 void CPatchInfo::CBindInfo::serial(NLMISC::IStream &f)
00409 {
00410 (void)f.serialVersion(0);
00411 f.xmlSerial(NPatchs, "NPATCH");
00412 nlassert ( (NPatchs==0) | (NPatchs==1) | (NPatchs==2) | (NPatchs==4) | (NPatchs==5) );
00413 f.xmlSerial (ZoneId, "ZONE_ID");
00414 f.xmlSerial (Next[0], Next[1], Next[2], Next[3], "NEXT_PATCH");
00415 f.xmlSerial (Edge[0], Edge[1], Edge[2], Edge[3], "NEXT_EDGE");
00416 }
00417
00418
00419 void CZone::serial(NLMISC::IStream &f)
00420 {
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 uint ver= f.serialVersion(4);
00434
00435
00436 if (ver<3)
00437 {
00438 throw EOlderStream(f);
00439 }
00440
00441 f.serialCheck((uint32)'ENOZ');
00442
00443 f.xmlSerial (ZoneId, "ZONE_ID");
00444 f.xmlSerial (ZoneBB, "BB");
00445 f.xmlSerial (PatchBias, "PATCH_BIAS");
00446 f.xmlSerial (PatchScale, "PATCH_SCALE");
00447 f.xmlSerial (NumVertices, "NUM_VERTICES");
00448
00449 f.xmlPush ("BORDER_VERTICES");
00450 f.serialCont(BorderVertices);
00451 f.xmlPop ();
00452
00453 f.xmlPush ("PATCHES");
00454 f.serialCont(Patchs);
00455 f.xmlPop ();
00456
00457 f.xmlPush ("PATCH_CONNECTS");
00458 f.serialCont(PatchConnects);
00459 f.xmlPop ();
00460
00461 if (ver>=4)
00462 {
00463 f.xmlPush ("POINT_LIGHTS");
00464 f.serial(_PointLightArray);
00465 f.xmlPop ();
00466 }
00467
00468
00469
00470
00471
00472 }
00473
00474
00475
00476 void CZone::compile(CLandscape *landscape, TZoneMap &loadedZones)
00477 {
00478 sint i,j;
00479 TZoneMap neighborZones;
00480
00481
00482
00483
00484 nlassert(!Compiled);
00485 Landscape= landscape;
00486
00487
00488
00489 nlassert(loadedZones.find(ZoneId)==loadedZones.end());
00490 loadedZones[ZoneId]= this;
00491
00492
00493
00494 BaseVertices.clear();
00495 BaseVertices.resize(NumVertices);
00496
00497 for(i=0;i<(sint)BorderVertices.size();i++)
00498 {
00499 sint cur= BorderVertices[i].CurrentVertex;
00500 sint vertto= BorderVertices[i].NeighborVertex;
00501 sint zoneto= BorderVertices[i].NeighborZoneId;
00502 nlassert(cur<NumVertices);
00503
00504 if(loadedZones.find(zoneto)!=loadedZones.end())
00505 {
00506 CZone *zone;
00507 zone= (*loadedZones.find(zoneto)).second;
00508 nlassert(zone!=this);
00509
00510 neighborZones[zoneto]= zone;
00511
00512
00513 BaseVertices[cur]= zone->getBaseVertex(vertto);
00514 }
00515 }
00516
00517 for(i=0;i<(sint)BaseVertices.size();i++)
00518 {
00519 if(BaseVertices[i]==NULL)
00520 {
00521 BaseVertices[i]= new CTessBaseVertex;
00522 }
00523 }
00524
00525
00526
00527
00528 for(j=0;j<(sint)Patchs.size();j++)
00529 {
00530 CPatch &pa= Patchs[j];
00531 CPatchConnect &pc= PatchConnects[j];
00532 CTessVertex *baseVertices[4];
00533
00534 baseVertices[0]= &(BaseVertices[pc.BaseVertices[0]]->Vert);
00535 baseVertices[1]= &(BaseVertices[pc.BaseVertices[1]]->Vert);
00536 baseVertices[2]= &(BaseVertices[pc.BaseVertices[2]]->Vert);
00537 baseVertices[3]= &(BaseVertices[pc.BaseVertices[3]]->Vert);
00538 pa.compile(this, j, pa.OrderS, pa.OrderT, baseVertices, pc.ErrorSize);
00539 };
00540
00541
00542
00543 for(j=0;j<(sint)Patchs.size();j++)
00544 {
00545 CPatch &pa= Patchs[j];
00546 CPatchConnect &pc= PatchConnects[j];
00547
00548
00549 bindPatch(loadedZones, pa, pc, false);
00550 }
00551
00552
00553
00554
00555 ItZoneMap zoneIt;
00556
00557 for(zoneIt= neighborZones.begin(); zoneIt!=neighborZones.end(); zoneIt++)
00558 {
00559 (*zoneIt).second->rebindBorder(loadedZones);
00560 }
00561
00562
00563 Compiled= true;
00564 }
00565
00566
00567 void CZone::release(TZoneMap &loadedZones)
00568 {
00569 sint i,j;
00570
00571 if(!Compiled)
00572 return;
00573
00574
00575
00576 nlassert(loadedZones.find(ZoneId)!=loadedZones.end());
00577 loadedZones.erase(ZoneId);
00578
00579
00580
00581
00582
00583 for(j=0;j<(sint)Patchs.size();j++)
00584 {
00585 CPatch &pa= Patchs[j];
00586 unbindPatch(pa);
00587 }
00588
00589
00590
00591
00592
00593 TZoneMap neighborZones;
00594 for(i=0;i<(sint)BorderVertices.size();i++)
00595 {
00596 sint cur= BorderVertices[i].CurrentVertex;
00597 sint zoneto= BorderVertices[i].NeighborZoneId;
00598 nlassert(cur<NumVertices);
00599
00600 if(loadedZones.find(zoneto)!=loadedZones.end())
00601 {
00602 CZone *zone;
00603 zone= (*loadedZones.find(zoneto)).second;
00604 nlassert(zone!=this);
00605
00606 neighborZones[zoneto]= zone;
00607 }
00608 }
00609
00610 ItZoneMap zoneIt;
00611
00612 for(zoneIt= neighborZones.begin(); zoneIt!=neighborZones.end(); zoneIt++)
00613 {
00614
00615 (*zoneIt).second->rebindBorder(loadedZones);
00616 }
00617
00618
00619
00620
00621
00622 for(j=0;j<(sint)Patchs.size();j++)
00623 {
00624 CPatch &pa= Patchs[j];
00625 pa.release();
00626 }
00627
00628
00629
00630
00631
00632 BaseVertices.clear();
00633
00634
00635
00636 Compiled= false;
00637 Landscape= NULL;
00638 ClipResult= ClipOut;
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 void CZone::rebindBorder(TZoneMap &loadedZones)
00651 {
00652 sint j;
00653
00654
00655 for(j=0;j<(sint)Patchs.size();j++)
00656 {
00657 CPatch &pa= Patchs[j];
00658 CPatchConnect &pc= PatchConnects[j];
00659
00660 if(patchOnBorder(pc))
00661 {
00662
00663 bindPatch(loadedZones, pa, pc, true);
00664 }
00665 }
00666 }
00667
00668
00669 CPatch *CZone::getZonePatch(TZoneMap &loadedZones, sint zoneId, sint patch)
00670 {
00671 #ifdef NL3D_DEBUG_DONT_BIND_PATCH
00672 return NULL;
00673 #endif
00674 if(loadedZones.find(zoneId)==loadedZones.end())
00675 return NULL;
00676 else
00677 return (loadedZones[zoneId])->getPatch(patch);
00678 }
00679
00680
00681
00682 void CZone::buildBindInfo(uint patchId, uint edge, CZone *neighborZone, CPatch::CBindInfo &paBind)
00683 {
00684 nlassert(patchId < Patchs.size());
00685 nlassert(neighborZone);
00686
00687 CPatchConnect &pc= PatchConnects[patchId];
00688
00689
00690
00691 CPatchInfo::CBindInfo &pcBind= pc.BindEdges[edge];
00692 nlassert(pcBind.NPatchs==0 || pcBind.NPatchs==1 || pcBind.NPatchs==2 || pcBind.NPatchs==4 || pcBind.NPatchs==5);
00693
00694
00695
00696 paBind.Zone= neighborZone;
00697
00698
00699
00700 if(pcBind.NPatchs==5)
00701 {
00702 paBind.NPatchs= 1;
00703 paBind.Next[0]= neighborZone->getPatch(pcBind.Next[0]);
00704 paBind.Edge[0]= pcBind.Edge[0];
00705
00706
00707 const CPatchInfo::CBindInfo &pcBindNeighbor=
00708 neighborZone->getPatchConnect(pcBind.Next[0])->BindEdges[pcBind.Edge[0]];
00709
00710 nlassert(pcBindNeighbor.NPatchs == 2 || pcBindNeighbor.NPatchs == 4);
00711
00712
00713 paBind.MultipleBindNum= pcBindNeighbor.NPatchs;
00714
00715
00716 paBind.MultipleBindId= 255;
00717 for(sint i=0; i<paBind.MultipleBindNum; i++)
00718 {
00719 if(pcBindNeighbor.Next[i]==patchId)
00720 paBind.MultipleBindId= i;
00721 }
00722 nlassert(paBind.MultipleBindId!= 255);
00723 }
00724 else
00725 {
00726 paBind.MultipleBindNum= 0;
00727 paBind.NPatchs= pcBind.NPatchs;
00728 for(sint i=0;i<paBind.NPatchs; i++)
00729 {
00730 paBind.Next[i]= neighborZone->getPatch(pcBind.Next[i]);
00731 paBind.Edge[i]= pcBind.Edge[i];
00732 }
00733 }
00734
00735
00736 }
00737
00738
00739
00740 void CZone::bindPatch(TZoneMap &loadedZones, CPatch &pa, CPatchConnect &pc, bool rebind)
00741 {
00742 CPatch::CBindInfo edges[4];
00743
00744
00745 for(sint i=0;i<4;i++)
00746 {
00747 CPatchInfo::CBindInfo &pcBind= pc.BindEdges[i];
00748 CPatch::CBindInfo &paBind= edges[i];
00749
00750 nlassert(pcBind.NPatchs==0 || pcBind.NPatchs==1 || pcBind.NPatchs==2 || pcBind.NPatchs==4 || pcBind.NPatchs==5);
00751 paBind.NPatchs= pcBind.NPatchs;
00752
00753
00754
00755 TZoneMap::iterator itZoneMap;
00756
00757 if( paBind.NPatchs==0 || (itZoneMap=loadedZones.find(pcBind.ZoneId)) == loadedZones.end() )
00758 paBind.Zone= NULL;
00759 else
00760 paBind.Zone= itZoneMap->second;
00761
00762
00763
00764 if(paBind.NPatchs==5)
00765 {
00766 paBind.Edge[0]= pcBind.Edge[0];
00767 paBind.Next[0]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[0]);
00768
00769 if(!paBind.Next[0])
00770 paBind.NPatchs=0;
00771 else
00772 {
00773
00774 CPatch::CBindInfo nbOnMe;
00775 paBind.Next[0]->getBindNeighbor(paBind.Edge[0], nbOnMe);
00776
00777 if( nbOnMe.Zone == NULL )
00778 {
00779
00780
00781 paBind.NPatchs=0;
00782 paBind.Zone= NULL;
00783 }
00784 else
00785 {
00786
00787
00788 continue;
00789 }
00790 }
00791 }
00792
00793
00794
00795 if(paBind.NPatchs>=1)
00796 {
00797 paBind.Edge[0]= pcBind.Edge[0];
00798 paBind.Next[0]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[0]);
00799
00800 if(!paBind.Next[0])
00801 paBind.NPatchs=0;
00802 }
00803 if(paBind.NPatchs>=2)
00804 {
00805 paBind.Edge[1]= pcBind.Edge[1];
00806 paBind.Next[1]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[1]);
00807
00808 if(!paBind.Next[1])
00809 paBind.NPatchs=0;
00810 }
00811 if(paBind.NPatchs>=4)
00812 {
00813 paBind.Edge[2]= pcBind.Edge[2];
00814 paBind.Edge[3]= pcBind.Edge[3];
00815 paBind.Next[2]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[2]);
00816 paBind.Next[3]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[3]);
00817
00818 if(!paBind.Next[2] || !paBind.Next[3])
00819 paBind.NPatchs=0;
00820 }
00821 }
00822
00823
00824 pa.unbind();
00825
00826
00827 pa.bind(edges, rebind);
00828 }
00829
00830
00831
00832 void CZone::unbindPatch(CPatch &pa)
00833 {
00834
00835
00836
00837
00838
00839
00840
00841 pa.unbind();
00842 }
00843
00844
00845
00846 bool CZone::patchOnBorder(const CPatchConnect &pc) const
00847 {
00848
00849
00850
00851 for(sint i=0;i<4;i++)
00852 {
00853 const CPatchInfo::CBindInfo &pcBind= pc.BindEdges[i];
00854
00855 nlassert(pcBind.NPatchs==0 || pcBind.NPatchs==1 || pcBind.NPatchs==2 || pcBind.NPatchs==4 || pcBind.NPatchs==5);
00856 if(pcBind.NPatchs>=1)
00857 {
00858 if(pcBind.ZoneId != ZoneId)
00859 return true;
00860 }
00861 }
00862
00863 return false;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 void CZone::clip(const std::vector<CPlane> &pyramid)
00876 {
00877 nlassert(Compiled);
00878
00879
00880 sint oldClipResult= ClipResult;
00881
00882
00883
00884 ClipResult= ClipIn;
00885 for(sint i=0;i<(sint)pyramid.size();i++)
00886 {
00887
00888 if(!ZoneBB.clipBack(pyramid[i]))
00889 {
00890 ClipResult= ClipOut;
00891
00892 break;
00893 }
00894
00895 else if(ZoneBB.clipFront(pyramid[i]))
00896 {
00897
00898 ClipResult=ClipSide;
00899 }
00900 }
00901
00902
00903
00904 if(Patchs.size()==0)
00905 {
00906 ClipResult= ClipOut;
00907
00908 return;
00909 }
00910
00911
00912
00913
00914 if(ClipResult==ClipOut)
00915 {
00916 CPatch *pPatch= &(*Patchs.begin());
00917 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00918 {
00919
00920 pPatch->forceClip();
00921 pPatch->forceRenderClip();
00922 }
00923 }
00924 else if(ClipResult==ClipIn)
00925 {
00926 CPatch *pPatch= &(*Patchs.begin());
00927 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00928 {
00929
00930 pPatch->forceNoClip();
00931 pPatch->forceNoRenderClip();
00932 }
00933 }
00934 else
00935 {
00936 CPatch *pPatch= &(*Patchs.begin());
00937 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00938 {
00939 pPatch->clip(pyramid);
00940 }
00941 }
00942
00943
00944
00945
00946
00947 if(oldClipResult!=ClipResult || oldClipResult==ClipSide)
00948 {
00949
00950 CPatch *pPatch= &(*Patchs.begin());
00951 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00952 {
00953
00954 pPatch->updateClipPatchVB();
00955 }
00956
00957 }
00958
00959 }
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 void CZone::excludePatchFromRefineAll(uint patch, bool exclude)
01023 {
01024 nlassert(Compiled);
01025 nlassert(patch<Patchs.size());
01026
01027 if(patch>=Patchs.size())
01028 return;
01029
01030 Patchs[patch].ExcludeFromRefineAll= exclude;
01031 }
01032
01033
01034
01035 void CZone::refineAll()
01036 {
01037 nlassert(Compiled);
01038
01039
01040 if(Patchs.size()==0)
01041 return;
01042
01043
01044 CPatch *pPatch= &(*Patchs.begin());
01045 sint n;
01046 for(n=(sint)Patchs.size();n>0;n--, pPatch++)
01047 {
01048 pPatch->forceNoClip();
01049
01050 }
01051
01052
01053
01054
01055 pPatch= &(*Patchs.begin());
01056 for(n=(sint)Patchs.size();n>0;n--, pPatch++)
01057 {
01058
01059 if(!pPatch->ExcludeFromRefineAll)
01060 pPatch->refineAll();
01061 }
01062
01063 }
01064
01065
01066
01067 void CZone::averageTesselationVertices()
01068 {
01069 nlassert(Compiled);
01070
01071
01072 if(Patchs.size()==0)
01073 return;
01074
01075
01076 CPatch *pPatch= &(*Patchs.begin());
01077 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
01078 {
01079 pPatch->averageTesselationVertices();
01080 }
01081 }
01082
01083
01084
01085 void CZone::preRender()
01086 {
01087 nlassert(Compiled);
01088
01089
01090 static const sint updateFarRefineFreq= 15;
01091
01092 sint curDateMod= CLandscapeGlobals::CurrentRenderDate & updateFarRefineFreq;
01093
01094
01095 if(Patchs.empty())
01096 return;
01097
01098
01099
01100
01101
01102
01103
01104 if(ClipResult==ClipOut)
01105 {
01106
01107 if( curDateMod==(ZoneId & updateFarRefineFreq) )
01108 {
01109
01110 CPatch *pPatch= &(*Patchs.begin());
01111 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
01112 pPatch->updateTextureFarOnly();
01113 }
01114 }
01115
01116 else if(ClipResult==ClipSide)
01117 {
01118
01119 CPatch *pPatch= &(*Patchs.begin());
01120 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
01121 {
01122
01123 if(!pPatch->isRenderClipped())
01124 {
01125
01126 pPatch->preRender();
01127 }
01128 else
01129 {
01130
01131
01132 if( curDateMod==((ZoneId+n) & updateFarRefineFreq) )
01133 pPatch->updateTextureFarOnly();
01134 }
01135 }
01136 }
01137 else
01138 {
01139
01140 CPatch *pPatch= &(*Patchs.begin());
01141 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
01142 pPatch->preRender();
01143 }
01144
01145 }
01146
01147
01148
01149 void CZone::resetRenderFarAndDeleteVBFV()
01150 {
01151 CPatch *pPatch=0;
01152 if(Patchs.size()>0)
01153 pPatch= &(*Patchs.begin());
01154 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
01155 {
01156
01157 if(!pPatch->RenderClipped)
01158 {
01159
01160 pPatch->deleteVBAndFaceVector();
01161
01162 pPatch->RenderClipped= true;
01163 }
01164
01165 pPatch->resetRenderFar();
01166 }
01167 }
01168
01169
01170
01171 void CZone::forceMergeAtTileLevel()
01172 {
01173 CPatch *pPatch=0;
01174 if(Patchs.size()>0)
01175 pPatch= &(*Patchs.begin());
01176 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
01177 {
01178 pPatch->forceMergeAtTileLevel();
01179 }
01180 }
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191 void CZone::changePatchTextureAndColor (sint numPatch, const std::vector<CTileElement> *tiles, const std::vector<CTileColor> *colors)
01192 {
01193 nlassert(numPatch>=0);
01194 nlassert(numPatch<getNumPatchs());
01195
01196
01197
01198 if (tiles)
01199 {
01200 nlassert( Patchs[numPatch].Tiles.size() == tiles->size() );
01201 Patchs[numPatch].Tiles = *tiles;
01202 }
01203
01204
01205 if (colors)
01206 {
01207 nlassert( Patchs[numPatch].TileColors.size() == colors->size() );
01208 Patchs[numPatch].TileColors = *colors;
01209 }
01210
01211 if (Compiled)
01212 {
01213
01214 if(!Patchs[numPatch].RenderClipped)
01215 Landscape->updateGlobalsAndLockBuffers(CVector::Null);
01216
01217
01218 Patchs[numPatch].deleteTileUvs();
01219 Patchs[numPatch].recreateTileUvs();
01220
01221
01222 if(!Patchs[numPatch].RenderClipped)
01223 {
01224 Landscape->unlockBuffers();
01225
01226
01227 Landscape->updateTessBlocksFaceVector();
01228 }
01229 }
01230 }
01231
01232
01233
01234 void CZone::refreshTesselationGeometry(sint numPatch)
01235 {
01236 nlassert(numPatch>=0);
01237 nlassert(numPatch<getNumPatchs());
01238 nlassert(Compiled);
01239
01240
01241 Landscape->_RenderMustRefillVB= true;
01242
01243 Patchs[numPatch].refreshTesselationGeometry();
01244 }
01245
01246
01247
01248 const std::vector<CTileElement> &CZone::getPatchTexture(sint numPatch) const
01249 {
01250 nlassert(numPatch>=0);
01251 nlassert(numPatch<getNumPatchs());
01252
01253
01254 return Patchs[numPatch].Tiles;
01255 }
01256
01257
01258
01259 const std::vector<CTileColor> &CZone::getPatchColor(sint numPatch) const
01260 {
01261 nlassert(numPatch>=0);
01262 nlassert(numPatch<getNumPatchs());
01263
01264
01265 return Patchs[numPatch].TileColors;
01266 }
01267
01268
01269
01270 void CZone::debugBinds(FILE *f)
01271 {
01272 fprintf(f, "*****************************\n");
01273 fprintf(f, "ZoneId: %d. NPatchs:%d\n", ZoneId, PatchConnects.size());
01274 sint i;
01275 for(i=0;i<(sint)PatchConnects.size();i++)
01276 {
01277 CPatchConnect &pc= PatchConnects[i];
01278 fprintf(f, "patch%d:\n", i);
01279 for(sint j=0;j<4;j++)
01280 {
01281 CPatchInfo::CBindInfo &bd= pc.BindEdges[j];
01282 fprintf(f, " edge%d: Zone:%d. NPatchs:%d. ", j, bd.ZoneId, bd.NPatchs);
01283 for(sint k=0;k<bd.NPatchs;k++)
01284 {
01285 fprintf(f, "p%de%d - ", bd.Next[k], bd.Edge[k]);
01286 }
01287 fprintf(f, "\n");
01288 }
01289 }
01290
01291 fprintf(f,"Vertices :\n");
01292 for(i=0;i<(sint)BorderVertices.size();i++)
01293 {
01294 fprintf(f,"current : %d -> (zone %d) vertex %d\n",BorderVertices[i].CurrentVertex,
01295 BorderVertices[i].NeighborZoneId,
01296 BorderVertices[i].NeighborVertex);
01297 }
01298 }
01299
01300
01301
01302 void CZone::applyHeightField(const CLandscape &landScape)
01303 {
01304 sint i,j;
01305 vector<CBezierPatch> patchs;
01306
01307
01308 if(Patchs.size()==0)
01309 return;
01310
01311
01312
01313 patchs.resize(Patchs.size());
01314 for(j=0;j<(sint)patchs.size();j++)
01315 {
01316 CBezierPatch &p= patchs[j];
01317 CPatch &pa= Patchs[j];
01318
01319
01320 for(i=0;i<4;i++)
01321 pa.Vertices[i].unpack(p.Vertices[i], PatchBias, PatchScale);
01322 for(i=0;i<8;i++)
01323 pa.Tangents[i].unpack(p.Tangents[i], PatchBias, PatchScale);
01324 for(i=0;i<4;i++)
01325 pa.Interiors[i].unpack(p.Interiors[i], PatchBias, PatchScale);
01326 }
01327
01328
01329
01330 for(j=0;j<(sint)patchs.size();j++)
01331 {
01332 CBezierPatch &p= patchs[j];
01333
01334
01335 for(i=0;i<4;i++)
01336 p.Vertices[i]+= landScape.getHeightFieldDeltaZ(p.Vertices[i].x, p.Vertices[i].y);
01337 for(i=0;i<8;i++)
01338 p.Tangents[i]+= landScape.getHeightFieldDeltaZ(p.Tangents[i].x, p.Tangents[i].y);
01339 for(i=0;i<4;i++)
01340 p.Interiors[i]+= landScape.getHeightFieldDeltaZ(p.Interiors[i].x, p.Interiors[i].y);
01341 }
01342
01343
01344
01345
01346 CAABBox bb;
01347 bb.setCenter(patchs[0].Vertices[0]);
01348 bb.setHalfSize(CVector::Null);
01349 for(j=0;j<(sint)patchs.size();j++)
01350 {
01351
01352 const CBezierPatch &p= patchs[j];
01353 for(i=0;i<4;i++)
01354 bb.extend(p.Vertices[i]);
01355 for(i=0;i<8;i++)
01356 bb.extend(p.Tangents[i]);
01357 for(i=0;i<4;i++)
01358 bb.extend(p.Interiors[i]);
01359 }
01360
01361 computeBBScaleBias(bb);
01362
01363
01364
01365
01366 for(j=0;j<(sint)patchs.size();j++)
01367 {
01368 CBezierPatch &p= patchs[j];
01369 CPatch &pa= Patchs[j];
01370
01371
01372 for(i=0;i<4;i++)
01373 pa.Vertices[i].pack(p.Vertices[i], PatchBias, PatchScale);
01374 for(i=0;i<8;i++)
01375 pa.Tangents[i].pack(p.Tangents[i], PatchBias, PatchScale);
01376 for(i=0;i<4;i++)
01377 pa.Interiors[i].pack(p.Interiors[i], PatchBias, PatchScale);
01378 }
01379 }
01380
01381
01382 void CZone::setupColorsFromTileFlags(const NLMISC::CRGBA colors[4])
01383 {
01384 for (uint k = 0; k < Patchs.size(); ++k)
01385 {
01386 Patchs[k].setupColorsFromTileFlags(colors);
01387 }
01388 }
01389
01390
01391
01392 void CZone::copyTilesFlags(sint destPatchId, const CPatch *srcPatch)
01393 {
01394 CPatch *destPatch = getPatch(destPatchId);
01395
01396 destPatch->copyTileFlagsFromPatch(srcPatch);
01397 }
01398
01399
01400
01401 bool CPatchInfo::getNeighborTile (uint patchId, uint edge, sint position, uint &patchOut, sint &sOut, sint &tOut,
01402 const vector<CPatchInfo> &patchInfos) const
01403 {
01404 nlassert (edge<4);
01405
01406
01407 uint length = (edge&1) ? OrderS : OrderT;
01408 nlassert ((uint)position<length);
01409
01410
01411 switch (BindEdges[edge].NPatchs)
01412 {
01413 case 1:
01414 case 2:
01415 case 4:
01416 {
01417
01418 uint neighborLength = (length / BindEdges[edge].NPatchs);
01419 uint neighbor = position / neighborLength;
01420 uint neighborPosition = neighborLength - (position % neighborLength) - 1;
01421 uint neighborEdge = BindEdges[edge].Edge[neighbor];
01422
01423
01424 patchOut = BindEdges[edge].Next[neighbor];
01425
01426
01427 uint neighborRealLength = (neighborEdge&1) ? patchInfos[patchOut].OrderS : patchInfos[patchOut].OrderT;
01428 if (neighborRealLength == neighborLength)
01429 {
01430
01431 switch (neighborEdge)
01432 {
01433 case 0:
01434 sOut = 0;
01435 tOut = neighborPosition;
01436 break;
01437 case 1:
01438 sOut = neighborPosition;
01439 tOut = patchInfos[patchOut].OrderT-1;
01440 break;
01441 case 2:
01442 sOut = patchInfos[patchOut].OrderS-1;
01443 tOut = patchInfos[patchOut].OrderT-neighborPosition-1;
01444 break;
01445 case 3:
01446 sOut = patchInfos[patchOut].OrderS-neighborPosition-1;
01447 tOut = 0;
01448 break;
01449 }
01450
01451
01452 return true;
01453 }
01454 }
01455 break;
01456
01457 case 5:
01458 {
01459
01460 patchOut = BindEdges[edge].Next[0];
01461 uint neighborEdge = BindEdges[edge].Edge[0];
01462 uint neighborEdgeCount = patchInfos[patchOut].BindEdges[neighborEdge].NPatchs;
01463
01464
01465 uint neighborRealLength = (neighborEdge&1) ? patchInfos[patchOut].OrderS : patchInfos[patchOut].OrderT;
01466
01467
01468 if ((neighborRealLength / neighborEdgeCount) == length)
01469 {
01470
01471 uint neighborPosition;
01472 for (neighborPosition=0; neighborPosition<neighborEdgeCount; neighborPosition++)
01473 {
01474
01475 if (patchInfos[patchOut].BindEdges[neighborEdge].Next[neighborPosition] == patchId)
01476 break;
01477 }
01478
01479
01480 nlassert (neighborPosition!=neighborEdgeCount);
01481 neighborPosition = (neighborPosition + 1) * (neighborRealLength / neighborEdgeCount) - position - 1;
01482
01483
01484 switch (neighborEdge)
01485 {
01486 case 0:
01487 sOut = 0;
01488 tOut = neighborPosition;
01489 break;
01490 case 1:
01491 sOut = neighborPosition;
01492 tOut = patchInfos[patchOut].OrderT-1;
01493 break;
01494 case 2:
01495 sOut = patchInfos[patchOut].OrderS-1;
01496 tOut = patchInfos[patchOut].OrderT-neighborPosition-1;
01497 break;
01498 case 3:
01499 sOut = patchInfos[patchOut].OrderS-neighborPosition-1;
01500 tOut = 0;
01501 break;
01502 }
01503
01504
01505 return true;
01506 }
01507 }
01508 break;
01509 }
01510
01511 return false;
01512 }
01513
01514
01515
01516
01517 bool CPatchInfo::getTileSymmetryRotate (const CTileBank &bank, uint tile, bool &symmetry, uint &rotate)
01518 {
01519
01520 if ( (symmetry || (rotate != 0)) && (tile != 0xffffffff) )
01521 {
01522
01523 if (tile < (uint)bank.getTileCount())
01524 {
01525
01526 int tileSet;
01527 int number;
01528 CTileBank::TTileType type;
01529
01530
01531 bank.getTileXRef ((int)tile, tileSet, number, type);
01532
01533
01534 if (bank.getTileSet (tileSet)->getOriented())
01535 {
01536
01537 rotate = 0;
01538 }
01539
01540
01541 return true;
01542 }
01543
01544 return false;
01545 }
01546 else
01547 return true;
01548 }
01549
01550
01551
01552 bool CPatchInfo::transformTile (const CTileBank &bank, uint &tile, uint &tileRotation, bool symmetry, uint rotate, bool goofy)
01553 {
01554
01555 if ( (rotate!=0) || symmetry )
01556 {
01557 if (tile < (uint)bank.getTileCount())
01558 {
01559
01560 int tileSet;
01561 int number;
01562 CTileBank::TTileType type;
01563
01564
01565 bank.getTileXRef ((int)tile, tileSet, number, type);
01566
01567
01568 if (type == CTileBank::transition)
01569 {
01570
01571 uint transRotate = rotate;
01572
01573
01574 nlassert (number>=0);
01575 nlassert (number<CTileSet::count);
01576
01577
01578 const CTileSet *pTileSet = bank.getTileSet (tileSet);
01579
01580
01581 CTileSet::TFlagBorder oriented[4] =
01582 {
01583 pTileSet->getOrientedBorder (CTileSet::left, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::left)),
01584 pTileSet->getOrientedBorder (CTileSet::bottom, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::bottom)),
01585 pTileSet->getOrientedBorder (CTileSet::right, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::right)),
01586 pTileSet->getOrientedBorder (CTileSet::top, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::top))
01587 };
01588
01589
01590 if (symmetry)
01591 {
01592 if ( (tileRotation & 1) ^ goofy )
01593 {
01594 CTileSet::TFlagBorder tmp = oriented[1];
01595 oriented[1] = CTileSet::getInvertBorder (oriented[3]);
01596 oriented[3] = CTileSet::getInvertBorder (tmp);
01597 oriented[2] = CTileSet::getInvertBorder (oriented[2]);
01598 oriented[0] = CTileSet::getInvertBorder (oriented[0]);
01599 }
01600 else
01601 {
01602 CTileSet::TFlagBorder tmp = oriented[0];
01603 oriented[0] = CTileSet::getInvertBorder (oriented[2]);
01604 oriented[2] = CTileSet::getInvertBorder (tmp);
01605 oriented[1] = CTileSet::getInvertBorder (oriented[1]);
01606 oriented[3] = CTileSet::getInvertBorder (oriented[3]);
01607 }
01608 }
01609
01610
01611 CTileSet::TFlagBorder edges[4];
01612 edges[0] = pTileSet->getOrientedBorder (CTileSet::left, oriented[(0 + transRotate )&3]);
01613 edges[1] = pTileSet->getOrientedBorder (CTileSet::bottom, oriented[(1 + transRotate )&3]);
01614 edges[2] = pTileSet->getOrientedBorder (CTileSet::right, oriented[(2 + transRotate )&3]);
01615 edges[3] = pTileSet->getOrientedBorder (CTileSet::top, oriented[(3 + transRotate )&3]);
01616
01617
01618 CTileSet::TTransition transition = pTileSet->getTransitionTile (edges[3], edges[1], edges[0], edges[2]);
01619 nlassert ((CTileSet::TTransition)transition != CTileSet::notfound);
01620 tile = (uint)(pTileSet->getTransition (transition)->getTile ());
01621 }
01622
01623
01624 tileRotation += rotate;
01625
01626
01627 if (goofy && symmetry)
01628 tileRotation += 2;
01629
01630
01631 tileRotation &= 3;
01632 }
01633 else
01634 return false;
01635 }
01636
01637
01638 return true;
01639 }
01640
01641
01642
01643 void CPatchInfo::transform256Case (const CTileBank &bank, uint8 &case256, uint tileRotation, bool symmetry, uint rotate, bool goofy)
01644 {
01645
01646 if ( (rotate!=0) || symmetry )
01647 {
01648
01649 if (symmetry)
01650 {
01651
01652 uint symArray[4] = {3, 2, 1, 0};
01653 case256 = symArray[case256];
01654
01655 if (goofy && ((tileRotation & 1) ==0))
01656 case256 += 2;
01657 if ((!goofy) && (tileRotation & 1))
01658 case256 += 2;
01659 }
01660
01661
01662 case256 -= rotate;
01663 case256 &= 3;
01664 }
01665 }
01666
01667
01668
01669 bool CPatchInfo::transform (std::vector<CPatchInfo> &patchInfo, NL3D::CZoneSymmetrisation &zoneSymmetry, const NL3D::CTileBank &bank, bool symmetry, uint rotate, float snapCell, float weldThreshold, const NLMISC::CMatrix &toOriginalSpace)
01670 {
01671 uint patchCount = patchInfo.size ();
01672 uint i;
01673
01674
01675
01676
01677
01678 NL3D::CZoneSymmetrisation::CError error;
01679
01680
01681 if (!zoneSymmetry.build (patchInfo, snapCell, weldThreshold, bank, error, toOriginalSpace))
01682 {
01683 return false;
01684 }
01685
01686
01687 if (symmetry)
01688 {
01689 for(i=0 ; i<patchCount; i++)
01690 {
01691
01692 CPatchInfo &pi = patchInfo[i];
01693
01694
01695
01696
01697 CVector tmp = pi.Patch.Vertices[0];
01698 pi.Patch.Vertices[0] = pi.Patch.Vertices[3];
01699 pi.Patch.Vertices[3] = tmp;
01700 tmp = pi.Patch.Vertices[1];
01701 pi.Patch.Vertices[1] = pi.Patch.Vertices[2];
01702 pi.Patch.Vertices[2] = tmp;
01703
01704
01705 tmp = pi.Patch.Tangents[0];
01706 pi.Patch.Tangents[0] = pi.Patch.Tangents[5];
01707 pi.Patch.Tangents[5] = tmp;
01708 tmp = pi.Patch.Tangents[1];
01709 pi.Patch.Tangents[1] = pi.Patch.Tangents[4];
01710 pi.Patch.Tangents[4] = tmp;
01711 tmp = pi.Patch.Tangents[2];
01712 pi.Patch.Tangents[2] = pi.Patch.Tangents[3];
01713 pi.Patch.Tangents[3] = tmp;
01714 tmp = pi.Patch.Tangents[6];
01715 pi.Patch.Tangents[6] = pi.Patch.Tangents[7];
01716 pi.Patch.Tangents[7] = tmp;
01717
01718
01719 tmp = pi.Patch.Interiors[0];
01720 pi.Patch.Interiors[0] = pi.Patch.Interiors[3];
01721 pi.Patch.Interiors[3] = tmp;
01722 tmp = pi.Patch.Interiors[1];
01723 pi.Patch.Interiors[1] = pi.Patch.Interiors[2];
01724 pi.Patch.Interiors[2] = tmp;
01725
01726
01727
01728 uint u,v;
01729 uint countU = pi.OrderS/2+1;
01730 uint countV = pi.OrderT+1;
01731 for (v=0; v<countV; v++)
01732 for (u=0; u<countU; u++)
01733 {
01734
01735 uint index0 = u+v*(pi.OrderS+1);
01736 uint index1 = (pi.OrderS-u)+v*(pi.OrderS+1);
01737
01738
01739 uint16 tmp = pi.TileColors[index0].Color565;
01740 pi.TileColors[index0].Color565 = pi.TileColors[index1].Color565;
01741 pi.TileColors[index1].Color565 = tmp;
01742 }
01743
01744
01745 uint backupFlag = pi.Flags;
01746 for (int edge=0; edge<4; edge+=2)
01747 {
01748
01749 pi.Flags &= (1<<edge);
01750
01751
01752 uint symEdge = ((edge+2)&3);
01753
01754
01755 pi.Flags |= (((backupFlag>>symEdge)&1)<<edge);
01756 }
01757 }
01758
01759
01760
01761
01762 for (i=0 ; i<patchCount; i++)
01763 {
01764
01765 CPatchInfo &pi = patchInfo[i];
01766
01767
01768 swap (pi.BindEdges[0], pi.BindEdges[2]);
01769 swap (pi.BaseVertices[0], pi.BaseVertices[3]);
01770 swap (pi.BaseVertices[1], pi.BaseVertices[2]);
01771
01772
01773 for (uint edge=0; edge<4; edge++)
01774 {
01775
01776 CPatchInfo::CBindInfo &bindEdge = pi.BindEdges[edge];
01777
01778 uint next;
01779
01780 if ( (bindEdge.NPatchs>1) && (bindEdge.NPatchs!=5) )
01781 {
01782 for (next=0; next<(uint)bindEdge.NPatchs/2; next++)
01783 {
01784 swap (bindEdge.Next[bindEdge.NPatchs - next - 1], bindEdge.Next[next]);
01785 swap (bindEdge.Edge[bindEdge.NPatchs - next - 1], bindEdge.Edge[next]);
01786 }
01787 }
01788
01789
01790 uint bindCount = (bindEdge.NPatchs==5) ? 1 : bindEdge.NPatchs;
01791 for (next=0; next<bindCount; next++)
01792 {
01793
01794 if ( (bindEdge.Edge[next] & 1) == 0)
01795 {
01796
01797 bindEdge.Edge[next] += 2;
01798 bindEdge.Edge[next] &= 3;
01799 }
01800 }
01801 }
01802 }
01803 }
01804
01805
01806 for (i=0 ; i<patchCount; i++)
01807 {
01808
01809 CPatchInfo &pi = patchInfo[i];
01810
01811
01812 std::vector<CTileElement> tiles = pi.Tiles;
01813
01814 int u,v;
01815 for (v=0; v<pi.OrderT; v++)
01816 for (u=0; u<pi.OrderS; u++)
01817 {
01818
01819 int uSymmetry = symmetry ? (pi.OrderS-u-1) : u;
01820
01821
01822 CTileElement &element = pi.Tiles[u+v*pi.OrderS];
01823
01824
01825 element = tiles[uSymmetry+v*pi.OrderS];
01826
01827
01828 for (int l=0; l<3; l++)
01829 {
01830
01831 if (element.Tile[l] != 0xffff)
01832 {
01833
01834 uint tile = element.Tile[l];
01835 uint tileRotation = element.getTileOrient (l);
01836
01837
01838 uint tileRotate = rotate;
01839 bool tileSymmetry = symmetry;
01840 bool goofy = symmetry && (zoneSymmetry.getTileState (i, uSymmetry+v*pi.OrderS, l) == CZoneSymmetrisation::Goofy);
01841
01842
01843 if (getTileSymmetryRotate (bank, tile, tileSymmetry, tileRotate))
01844 {
01845
01846 if (!transformTile (bank, tile, tileRotation, tileSymmetry, (4-tileRotate)&3, goofy))
01847 {
01848
01849 nlwarning ("Error getting symmetrical / rotated zone tile.");
01850 return false;
01851 }
01852 }
01853 else
01854 {
01855
01856 nlwarning ("Error getting symmetrical / rotated zone tile.");
01857 return false;
01858 }
01859
01860
01861 element.Tile[l] = tile;
01862 element.setTileOrient (l, (uint8)tileRotation);
01863 }
01864 }
01865
01866
01867 if (element.Tile[0]!=0xffff)
01868 {
01869
01870 bool is256x256;
01871 uint8 uvOff;
01872 element.getTile256Info (is256x256, uvOff);
01873
01874
01875 if (is256x256)
01876 {
01877
01878 uint tileRotate = rotate;
01879 bool tileSymmetry = symmetry;
01880 uint tileRotation = tiles[uSymmetry+v*pi.OrderS].getTileOrient (0);
01881 bool goofy = symmetry && (zoneSymmetry.getTileState (i, uSymmetry+v*pi.OrderS, 0) == CZoneSymmetrisation::Goofy);
01882
01883
01884 getTileSymmetryRotate (bank, element.Tile[0], tileSymmetry, tileRotate);
01885
01886
01887 transform256Case (bank, uvOff, tileRotation, tileSymmetry, (4-tileRotate)&3, goofy);
01888
01889 element.setTile256Info (true, uvOff);
01890 }
01891 }
01892 }
01893 }
01894
01895
01896 return true;
01897 }
01898
01899
01900
01901 }