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

zone.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 #include "std3d.h"
+00027 
+00028 #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 // define it only for debug bind.
+00039 //#define       NL3D_DEBUG_DONT_BIND_PATCH
+00040 
+00041 
+00042 namespace NL3D 
+00043 {
+00044 
+00045 
+00046 
+00047 // ***************************************************************************
+00048 // ***************************************************************************
+00049 // CPatchInfo
+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 // CZone
+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         // release() must have been called.
+00093         nlassert(!Compiled);
+00094 }
+00095 
+00096 
+00097 // ***************************************************************************
+00098 void                    CZone::computeBBScaleBias(const CAABBox &bb)
+00099 {
+00100         ZoneBB= bb;
+00101         // Take a security for noise. (usefull for zone clipping).
+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;               // Prevent from float imprecision by taking 32760 and not 32767.
+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         // Ref inupt
+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         // Compute the bbox and the bias/scale.
+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         // Compute BBox, and Patch Scale Bias, according to Noise.
+00152         computeBBScaleBias(bb);
+00153 
+00154 
+00155         // Compute/compress Patchs.
+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                 // Smoothing flags
+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                 // Noise Data
+00173                 // copy noise rotation.
+00174                 pa.NoiseRotation= pi.NoiseRotation;
+00175                 // copy all noise smoothing info.
+00176                 for(i=0;i<4;i++)
+00177                 {
+00178                         pa.setCornerSmoothFlag(i, pi.getCornerSmoothFlag(i));
+00179                 }
+00180 
+00181                 // Copy order of the patch
+00182                 pa.OrderS= pi.OrderS;
+00183                 pa.OrderT= pi.OrderT;
+00184 
+00185                 // Build the patch.
+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                 /* Copy TileLightInfluences. It is possible that pi.TileLightInfluences.size()!= 0
+00195                         and pi.TileLightInfluences.size()!= (uint)(pi.OrderS/2+1)*(pi.OrderT/2+1)
+00196                         Because of a preceding bug where pa.OrderS and pa.OrderT were not initialized before the 
+00197                         pa.resetTileLightInfluences();
+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                 // Number of lumels in this patch
+00209                 uint lumelCount=(pi.OrderS*NL_LUMEL_BY_TILE)*(pi.OrderT*NL_LUMEL_BY_TILE);
+00210 
+00211                 // Lumel empty ?
+00212                 if (pi.Lumels.size ()==lumelCount)
+00213                 {
+00214                         // Pack the lumel map
+00215                         pa.packShadowMap (&pi.Lumels[0]);
+00216                 }
+00217                 else
+00218                 {
+00219                         // Reset lightmap
+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                 // Build the patchConnect.
+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         // Copy PointLights.
+00242         //=========================
+00243         // build array, lights are sorted
+00244         std::vector<uint>       plRemap;
+00245         _PointLightArray.build(zoneInfo.PointLights, plRemap);
+00246         // Check TileLightInfluences integrity, and remap PointLight Indices.
+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                                 // If NULL light, break and continue to next TileLightInfluence.
+00256                                 if(tli.Light[l]== 0xFF)
+00257                                         break;
+00258                                 else
+00259                                 {
+00260                                         // Check good index.
+00261                                         nlassert(tli.Light[l] < _PointLightArray.getPointLights().size());
+00262                                         // Remap index, because of light sorting.
+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         // Ref on input.
+00288         std::vector<CPatchInfo> &patchs= zoneInfo.Patchs;
+00289         std::vector<CBorderVertex> &borderVertices= zoneInfo.BorderVertices;
+00290         // Copy zoneId.
+00291         zoneInfo.ZoneId= getZoneId();
+00292 
+00293 
+00294         // uncompress Patchs.
+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                 // Smoothing flags
+00306                 pi.Flags= (pa.Flags&NL_PATCH_SMOOTH_FLAG_MASK)>>NL_PATCH_SMOOTH_FLAG_SHIFT;
+00307 
+00308 
+00309                 // Noise Data
+00310                 // copy noise rotation.
+00311                 pi.NoiseRotation= pa.NoiseRotation;
+00312                 // copy all noise smoothing info.
+00313                 for(i=0;i<4;i++)
+00314                 {
+00315                         pi.setCornerSmoothFlag(i, pa.getCornerSmoothFlag(i));
+00316                 }
+00317 
+00318 
+00319                 // re-Build the uncompressed bezier patch.
+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                 // Unpack the lumel map
+00333                 pa.unpackShadowMap (&pi.Lumels[0]);
+00334 
+00335                 // from the patchConnect.
+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         // retrieve bordervertices.
+00348         //=========================
+00349         borderVertices= BorderVertices;
+00350 
+00351         // retrieve PointLights.
+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         // Compute the bbox and the bias/scale.
+00367         //=====================================
+00368         ZoneBB= zone.ZoneBB;
+00369         PatchScale= zone.PatchScale;
+00370         PatchBias= zone.PatchBias;
+00371 
+00372 
+00373         // Compute/compress Patchs.
+00374         //=========================
+00375         Patchs= zone.Patchs;
+00376         PatchConnects= zone.PatchConnects;
+00377 
+00378         // copy pointLights.
+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         Version 4:
+00423                 - PointLights
+00424         Version 3:
+00425                 - Lumels compression version 2.
+00426         Version 2:
+00427                 - Lumels.
+00428         Version 1:
+00429                 - Tile color.
+00430         Version 0:
+00431                 - base verison.
+00432         */
+00433         uint    ver= f.serialVersion(4);
+00434 
+00435         // No more compatibility before version 3
+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         // If read and version 0, must init default TileColors of patchs.
+00469         //===============================================================
+00470         // if(f.isReading() && ver<2) ... 
+00471         // Deprecated, because ver<3 not supported
+00472 }
+00473 
+00474 
+00475 // ***************************************************************************
+00476 void                    CZone::compile(CLandscape *landscape, TZoneMap &loadedZones)
+00477 {
+00478         sint    i,j;
+00479         TZoneMap                neighborZones;
+00480 
+00481         //nlinfo("Compile Zone: %d \n", (sint32)getZoneId());
+00482 
+00483         // Can't compile if compiled.
+00484         nlassert(!Compiled);
+00485         Landscape= landscape;
+00486 
+00487         // Attach this to loadedZones.
+00488         //============================
+00489         nlassert(loadedZones.find(ZoneId)==loadedZones.end());
+00490         loadedZones[ZoneId]= this;
+00491         
+00492         // Create/link the base vertices according to present neigbor zones.
+00493         //============================
+00494         BaseVertices.clear();
+00495         BaseVertices.resize(NumVertices);
+00496         // First try to link vertices to other.
+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                         // insert the zone in the neigborood (if not done...).
+00510                         neighborZones[zoneto]= zone;
+00511                         // Doesn't matter if BaseVertices is already linked to an other zone... 
+00512                         // This should be the same pointer in this case...
+00513                         BaseVertices[cur]=  zone->getBaseVertex(vertto);
+00514                 }
+00515         }
+00516         // Else, create unbounded vertices.
+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         // compile() the patchs.
+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         // bind() the patchs. (after all compiled).
+00542         //===================
+00543         for(j=0;j<(sint)Patchs.size();j++)
+00544         {
+00545                 CPatch                          &pa= Patchs[j];
+00546                 CPatchConnect           &pc= PatchConnects[j];
+00547 
+00548                 // bind the patch. This is the original bind, not a rebind.
+00549                 bindPatch(loadedZones, pa, pc, false);
+00550         }
+00551         
+00552         
+00553         // rebindBorder() on neighbor zones.
+00554         //==================================
+00555         ItZoneMap               zoneIt;
+00556         // Traverse the neighborood.
+00557         for(zoneIt= neighborZones.begin(); zoneIt!=neighborZones.end(); zoneIt++)
+00558         {
+00559                 (*zoneIt).second->rebindBorder(loadedZones);
+00560         }
+00561 
+00562         // End!!
+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         // detach this zone to loadedZones.
+00575         //=================================
+00576         nlassert(loadedZones.find(ZoneId)!=loadedZones.end());
+00577         loadedZones.erase(ZoneId);
+00578         // It doesn't server to unbindPatch(), since patch is not binded to neigbors.
+00579 
+00580 
+00581         // unbind() the patchs.
+00582         //=====================
+00583         for(j=0;j<(sint)Patchs.size();j++)
+00584         {
+00585                 CPatch                          &pa= Patchs[j];
+00586                 unbindPatch(pa);
+00587         }
+00588 
+00589 
+00590         // rebindBorder() on neighbor zones.
+00591         //==================================
+00592         // Build the nieghborood.
+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                         // insert the zone in the neigborood (if not done...).
+00606                         neighborZones[zoneto]= zone;
+00607                 }
+00608         }
+00609         // rebind borders.
+00610         ItZoneMap               zoneIt;
+00611         // Traverse the neighborood.
+00612         for(zoneIt= neighborZones.begin(); zoneIt!=neighborZones.end(); zoneIt++)
+00613         {
+00614                 // Since 
+00615                 (*zoneIt).second->rebindBorder(loadedZones);
+00616         }
+00617 
+00618 
+00619         // release() the patchs.
+00620         //======================
+00621         // unbind() need compiled neigbor patchs, so do the release after all unbind (so after rebindBorder() too...).
+00622         for(j=0;j<(sint)Patchs.size();j++)
+00623         {
+00624                 CPatch                          &pa= Patchs[j];
+00625                 pa.release();
+00626         }
+00627 
+00628 
+00629         // destroy/unlink the base vertices (internal..), according to present neigbor zones.
+00630         //=================================
+00631         // Just release the smartptrs (easy!!). Do it after patchs released...
+00632         BaseVertices.clear();
+00633         
+00634 
+00635         // End!!
+00636         Compiled= false;
+00637         Landscape= NULL;
+00638         ClipResult= ClipOut;
+00639 }
+00640 
+00641 
+00642 // ***************************************************************************
+00643 // ***************************************************************************
+00644 // Private part.
+00645 // ***************************************************************************
+00646 // ***************************************************************************
+00647 
+00648 
+00649 // ***************************************************************************
+00650 void                    CZone::rebindBorder(TZoneMap &loadedZones)
+00651 {
+00652         sint    j;
+00653 
+00654         // rebind patchs which are on border.
+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                         // rebind the patch. This is a rebind.
+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         // Get the bind info of this patch to his neighbor on "edge".
+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         // copy zone ptr.
+00696         paBind.Zone= neighborZone;
+00697 
+00698 
+00699         // Special case of a small patch connected to a bigger.
+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                 // Get the twin bindInfo of pcBind.
+00707                 const CPatchInfo::CBindInfo     &pcBindNeighbor= 
+00708                         neighborZone->getPatchConnect(pcBind.Next[0])->BindEdges[pcBind.Edge[0]];
+00709                 // must have a multiple bind.   
+00710                 nlassert(pcBindNeighbor.NPatchs == 2 || pcBindNeighbor.NPatchs == 4);
+00711 
+00712                 // number of bind is stored on the twin bindInfo.
+00713                 paBind.MultipleBindNum= pcBindNeighbor.NPatchs;
+00714 
+00715                 // Search our patchId on neighbor;
+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         // Fill all edges.
+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                 // Find the zone.
+00755                 TZoneMap::iterator      itZoneMap;
+00756                 // If no neighbor, or if zone neighbor not loaded.
+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                 // Special case of a small patch connected to a bigger.
+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                         // If not loaded, don't bind to this edge.
+00769                         if(!paBind.Next[0])
+00770                                 paBind.NPatchs=0;
+00771                         else
+00772                         {
+00773                                 // Get the BindInfo on me stored in our neighbor bigger CPatch
+00774                                 CPatch::CBindInfo       nbOnMe;
+00775                                 paBind.Next[0]->getBindNeighbor(paBind.Edge[0], nbOnMe);
+00776                                 // if this patch has not already been binded on me, nbOnMe.Zone==NULL
+00777                                 if( nbOnMe.Zone == NULL )
+00778                                 {
+00779                                         // Simple case: do nothing: don't need to rebind() to the bigger patch since 
+00780                                         // himself is not bound
+00781                                         paBind.NPatchs=0;
+00782                                         paBind.Zone= NULL;
+00783                                 }
+00784                                 else
+00785                                 {
+00786                                         // pa.bind() will do the job.
+00787                                         // Leave it flagged with NPatchs==5.
+00788                                         continue;
+00789                                 }
+00790                         }
+00791                 }
+00792 
+00793 
+00794                 // Bind 1/1 and 1/2,1/4
+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                         // If not loaded, don't bind to this edge.
+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                         // If not loaded, don't bind to this edge.
+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                         // If not loaded, don't bind to this edge.
+00818                         if(!paBind.Next[2] || !paBind.Next[3])
+00819                                 paBind.NPatchs=0;
+00820                 }
+00821         }
+00822 
+00823         // First, unbind.
+00824         pa.unbind();
+00825 
+00826         // Then bind.
+00827         pa.bind(edges, rebind);
+00828 }
+00829 
+00830 
+00831 // ***************************************************************************
+00832 void            CZone::unbindPatch(CPatch &pa)
+00833 {
+00834         /*
+00835                 Remind: the old version with CPatch::unbindFrom*() doesn't work because of CZone::release(). This function
+00836                 first erase the zone from loadedZones...
+00837                 Not matter here. We use CPatch::unbind() which should do all the good job correctly (unbind pa from ohters
+00838                 , and unbind others from pa at same time).
+00839         */
+00840 
+00841         pa.unbind();
+00842 }
+00843 
+00844 
+00845 // ***************************************************************************
+00846 bool                    CZone::patchOnBorder(const CPatchConnect &pc) const
+00847 {
+00848         // If only one of neighbor patch is not of this zone, we are on a border.
+00849 
+00850         // Test all edges.
+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 // Render part.
+00870 // ***************************************************************************
+00871 // ***************************************************************************
+00872 
+00873 
+00874 // ***************************************************************************
+00875 void                    CZone::clip(const std::vector<CPlane>   &pyramid)
+00876 {
+00877         nlassert(Compiled);
+00878 
+00879         // bkup old ClipResult. NB: by default, it is ClipOut (no VB created).
+00880         sint    oldClipResult= ClipResult;
+00881 
+00882         // Compute ClipResult.
+00883         //-------------------
+00884         ClipResult= ClipIn;
+00885         for(sint i=0;i<(sint)pyramid.size();i++)
+00886         {
+00887                 // If entirely out.
+00888                 if(!ZoneBB.clipBack(pyramid[i]))
+00889                 {
+00890                         ClipResult= ClipOut;
+00891                         // If out of only one plane, out of all.
+00892                         break;
+00893                 }
+00894                 // If partially IN (ie not entirely out, and not entirely IN)
+00895                 else if(ZoneBB.clipFront(pyramid[i]))
+00896                 {
+00897                         // Force ClipResult to be ClipSide, and not ClipIn.
+00898                         ClipResult=ClipSide;
+00899                 }
+00900         }
+00901 
+00902 
+00903         // Easy Clip  :)
+00904         if(Patchs.size()==0)
+00905         {
+00906                 ClipResult= ClipOut;
+00907                 // don't need to go below...
+00908                 return;
+00909         }
+00910 
+00911 
+00912         // Clip By Patch Pass.
+00913         //--------------------
+00914         if(ClipResult==ClipOut)
+00915         {
+00916                 CPatch          *pPatch= &(*Patchs.begin());
+00917                 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
+00918                 {
+00919                         // The patch is entirely clipped, and so on for Render.
+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                         // The patch is entirely unclipped, and so on for Render.
+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         // delete / reallocate / fill VBuffers.
+00945         //-------------------
+00946         // If there is a change in the Clip of the zone, or if patchs may have change (ie ClipSide is undetermined).
+00947         if(oldClipResult!=ClipResult || oldClipResult==ClipSide)
+00948         {
+00949                 // Then, we must test by patch.
+00950                 CPatch          *pPatch= &(*Patchs.begin());
+00951                 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
+00952                 {
+00953                         // For all patchs, we may delete or allocate / Fill VBs.
+00954                         pPatch->updateClipPatchVB();
+00955                 }
+00956 
+00957         }
+00958 
+00959 }
+00960 
+00961 
+00962 // ***************************************************************************
+00963 // DebugYoyo.
+00964 // Code for Debug test Only.. Do not erase it, may be used later :)
+00965 /*
+00966 static  void    cleanTess(CTessFace *face)
+00967 {
+00968         if(!face->isLeaf())
+00969         {
+00970                 cleanTess(face->SonLeft);
+00971                 cleanTess(face->SonRight);
+00972         }
+00973         // If has father, clean it.
+00974         if(face->Father)
+00975         {
+00976                 CTessFace       *face1=face->Father;
+00977                 CTessFace       *face2=face->Father->FBase;
+00978                 face1->FLeft= face1->SonLeft->FBase;
+00979                 face1->FRight= face1->SonRight->FBase;
+00980                 if(face2!=NULL)
+00981                 {
+00982                         face2->FLeft= face2->SonLeft->FBase;
+00983                         face2->FRight= face2->SonRight->FBase;
+00984                 }
+00985         }
+00986 }
+00987 static  void    testTess(CTessFace *face)
+00988 {
+00989         if(!face->isLeaf())
+00990         {
+00991                 testTess(face->SonLeft);
+00992                 testTess(face->SonRight);
+00993         }
+00994         // Test validity.
+00995         nlassert(!face->FBase || face->FBase->Patch!=(CPatch*)0xdddddddd);
+00996         nlassert(!face->FLeft || face->FLeft->Patch!=(CPatch*)0xdddddddd);
+00997         nlassert(!face->FRight || face->FRight->Patch!=(CPatch*)0xdddddddd);
+00998 }
+00999 static  void    checkTess()
+01000 {
+01001         // This test should be inserted at begin of CZone::refine().
+01002         // And it needs hacking public/private.
+01003         CPatch          *pPatch;
+01004         sint            n;
+01005         pPatch= &(*Patchs.begin());
+01006         for(n=(sint)Patchs.size();n>0;n--, pPatch++)
+01007         {
+01008                 cleanTess(pPatch->Son0);
+01009                 cleanTess(pPatch->Son1);
+01010         }
+01011         pPatch= &(*Patchs.begin());
+01012         for(n=(sint)Patchs.size();n>0;n--, pPatch++)
+01013         {
+01014                 testTess(pPatch->Son0);
+01015                 testTess(pPatch->Son1);
+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         // Fuck stlport....
+01040         if(Patchs.size()==0)
+01041                 return;
+01042 
+01043         // Do a dummy clip.
+01044         CPatch          *pPatch= &(*Patchs.begin());
+01045         sint n;
+01046         for(n=(sint)Patchs.size();n>0;n--, pPatch++)
+01047         {
+01048                 pPatch->forceNoClip();
+01049                 // DO NOT do a forceNoRenderClip(), to avoid big allocation of Near/Far VB vertices in driver.
+01050         }
+01051         // DO NOT modify ClipResult, to avoid big allocation of Near/Far VB vertices in driver.
+01052 
+01053 
+01054         // refine ALL patchs (even those which may be invisible).
+01055         pPatch= &(*Patchs.begin());
+01056         for(n=(sint)Patchs.size();n>0;n--, pPatch++)
+01057         {
+01058                 // For Pacs construction: may exclude some patch from refineAll (for speed improvement).
+01059                 if(!pPatch->ExcludeFromRefineAll)
+01060                         pPatch->refineAll();
+01061         }
+01062 
+01063 }
+01064 
+01065 
+01066 // ***************************************************************************
+01067 void                    CZone::averageTesselationVertices()
+01068 {
+01069         nlassert(Compiled);
+01070 
+01071         // Fuck stlport....
+01072         if(Patchs.size()==0)
+01073                 return;
+01074 
+01075         // averageTesselationVertices of ALL patchs.
+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         // Must be 2^X-1.
+01090         static const    sint    updateFarRefineFreq= 15;
+01091         // Take the renderDate here.
+01092         sint            curDateMod= CLandscapeGlobals::CurrentRenderDate & updateFarRefineFreq;
+01093 
+01094         // If no patchs, do nothing.
+01095         if(Patchs.empty())
+01096                 return;
+01097 
+01098         /* If patchs invisible, must still update their Far Textures,
+01099                 else, there may be slowdown when we turn the head.
+01100         */
+01101 
+01102 
+01103         // If all the zone is invisible.
+01104         if(ClipResult==ClipOut)
+01105         {
+01106                 // No patchs are visible, but maybe update the far textures.
+01107                 if( curDateMod==(ZoneId & updateFarRefineFreq) )
+01108                 {
+01109                         // updateTextureFarOnly for all patchs.
+01110                         CPatch          *pPatch= &(*Patchs.begin());
+01111                         for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
+01112                                 pPatch->updateTextureFarOnly();
+01113                 }
+01114         }
+01115         // else If some patchs only are visible.
+01116         else if(ClipResult==ClipSide)
+01117         {
+01118                 // PreRender Pass, or updateTextureFarOnly(), according to RenderClipped state.
+01119                 CPatch          *pPatch= &(*Patchs.begin());
+01120                 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
+01121                 {
+01122                         // If the patch is visible
+01123                         if(!pPatch->isRenderClipped())
+01124                         {
+01125                                 // Then preRender it.
+01126                                 pPatch->preRender();
+01127                         }
+01128                         else
+01129                         {
+01130                                 // else maybe updateFar it.
+01131                                 // ZoneId+n for better repartition.
+01132                                 if( curDateMod==((ZoneId+n) & updateFarRefineFreq) )
+01133                                         pPatch->updateTextureFarOnly();
+01134                         }
+01135                 }
+01136         }
+01137         else    // ClipResult==ClipIn
+01138         {
+01139                 // PreRender Pass for All
+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                 // If patch is visible
+01157                 if(!pPatch->RenderClipped)
+01158                 {
+01159                         // release VertexBuffer, and FaceBuffer
+01160                         pPatch->deleteVBAndFaceVector();
+01161                         // Flag.
+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 // Misc part.
+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         // Update the patch texture.
+01198         if (tiles)
+01199         {
+01200                 nlassert( Patchs[numPatch].Tiles.size() == tiles->size() );
+01201                 Patchs[numPatch].Tiles = *tiles;
+01202         }
+01203 
+01204         // Update the patch colors.
+01205         if (colors)
+01206         {
+01207                 nlassert( Patchs[numPatch].TileColors.size() == colors->size() );
+01208                 Patchs[numPatch].TileColors = *colors;
+01209         }
+01210 
+01211         if (Compiled)
+01212         {
+01213                 // If the patch is visible, then we must LockBuffers, because new VertexVB may be created.
+01214                 if(!Patchs[numPatch].RenderClipped)
+01215                         Landscape->updateGlobalsAndLockBuffers(CVector::Null);
+01216 
+01217                 // Recompute UVs for new setup of Tiles.
+01218                 Patchs[numPatch].deleteTileUvs();
+01219                 Patchs[numPatch].recreateTileUvs();
+01220 
+01221                 // unlockBuffers() if necessary.
+01222                 if(!Patchs[numPatch].RenderClipped)
+01223                 {
+01224                         Landscape->unlockBuffers();
+01225                         // This patch is visible, and TileFaces have been deleted / added.
+01226                         // So must update TessBlock.
+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         // At next render, we must re-fill the entire unclipped VB, so change are taken into account.
+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         // Update the patch texture.
+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         // Update the patch texture.
+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         // no patch, do nothing.
+01308         if(Patchs.size()==0)
+01309                 return;
+01310 
+01311         // 0. Unpack patchs to Bezier Patchs.
+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                 // re-Build the uncompressed bezier patch.
+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         // 1. apply heightfield on bezier patchs.
+01329         //===================================
+01330         for(j=0;j<(sint)patchs.size();j++)
+01331         {
+01332                 CBezierPatch            &p= patchs[j];
+01333 
+01334                 // apply delta.
+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         // 2. Re-compute Patch Scale/Bias, and Zone BBox.
+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                 // extend bbox.
+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         // Compute BBox, and Patch Scale Bias, according to Noise.
+01361         computeBBScaleBias(bb);
+01362 
+01363 
+01364         // 3. Re-pack patchs.
+01365         //===================================
+01366         for(j=0;j<(sint)patchs.size();j++)
+01367         {
+01368                 CBezierPatch            &p= patchs[j];
+01369                 CPatch                          &pa= Patchs[j];
+01370 
+01371                 // Build the packed patch.
+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         // S or T ?
+01407         uint length = (edge&1) ? OrderS : OrderT;
+01408         nlassert ((uint)position<length);
+01409 
+01410         // What kind of case ?
+01411         switch (BindEdges[edge].NPatchs)
+01412         {
+01413         case 1:
+01414         case 2:
+01415         case 4:
+01416                 {
+01417                         // Get neighbor index and position in neighbor
+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                         // Patch id
+01424                         patchOut = BindEdges[edge].Next[neighbor];
+01425 
+01426                         // Check neighbor
+01427                         uint neighborRealLength = (neighborEdge&1) ? patchInfos[patchOut].OrderS : patchInfos[patchOut].OrderT;
+01428                         if (neighborRealLength == neighborLength)
+01429                         {
+01430                                 // Get final coordinate
+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                                 // Ok todo remove
+01452                                 return true;
+01453                         }
+01454                 }
+01455                 break;
+01456         
+01457         case 5:
+01458                 {
+01459                         // Find in the neighbor where we are
+01460                         patchOut = BindEdges[edge].Next[0];
+01461                         uint neighborEdge = BindEdges[edge].Edge[0];
+01462                         uint neighborEdgeCount = patchInfos[patchOut].BindEdges[neighborEdge].NPatchs;
+01463 
+01464                         // Check neighbor
+01465                         uint neighborRealLength = (neighborEdge&1) ? patchInfos[patchOut].OrderS : patchInfos[patchOut].OrderT;
+01466 
+01467                         // Good length ?
+01468                         if ((neighborRealLength / neighborEdgeCount) == length)
+01469                         {
+01470                                 // Find us in the neighbor
+01471                                 uint neighborPosition;
+01472                                 for (neighborPosition=0; neighborPosition<neighborEdgeCount; neighborPosition++)
+01473                                 {
+01474                                         // Found ?
+01475                                         if (patchInfos[patchOut].BindEdges[neighborEdge].Next[neighborPosition] == patchId)
+01476                                                 break;
+01477                                 }
+01478 
+01479                                 // Must be found
+01480                                 nlassert (neighborPosition!=neighborEdgeCount);
+01481                                 neighborPosition = (neighborPosition + 1) * (neighborRealLength / neighborEdgeCount) - position - 1;
+01482 
+01483                                 // Get final coordinate
+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                                 // Ok
+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         // Need check the tile ?
+01520         if ( (symmetry || (rotate != 0)) && (tile != 0xffffffff) )
+01521         {
+01522                 // Tile exist ?
+01523                 if (tile < (uint)bank.getTileCount())
+01524                 {
+01525                         // Get xref
+01526                         int tileSet;
+01527                         int number;
+01528                         CTileBank::TTileType type;
+01529 
+01530                         // Get tile xref
+01531                         bank.getTileXRef ((int)tile, tileSet, number, type);
+01532 
+01533                         // Is it an oriented tile ?
+01534                         if (bank.getTileSet (tileSet)->getOriented())
+01535                         {
+01536                                 // New rotation value
+01537                                 rotate = 0;
+01538                         }
+01539 
+01540                         // Ok
+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         // Tile exist ?
+01555         if ( (rotate!=0) || symmetry )
+01556         {
+01557                 if (tile < (uint)bank.getTileCount())
+01558                 {
+01559                         // Get xref
+01560                         int tileSet;
+01561                         int number;
+01562                         CTileBank::TTileType type;
+01563 
+01564                         // Get tile xref
+01565                         bank.getTileXRef ((int)tile, tileSet, number, type);
+01566 
+01567                         // Transition ?
+01568                         if (type == CTileBank::transition)
+01569                         {
+01570                                 // Rotation for transition
+01571                                 uint transRotate = rotate;
+01572 
+01573                                 // Number should be ok
+01574                                 nlassert (number>=0);
+01575                                 nlassert (number<CTileSet::count);
+01576 
+01577                                 // Tlie set number
+01578                                 const CTileSet *pTileSet = bank.getTileSet (tileSet);
+01579 
+01580                                 // Get border desc
+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                                 // Symmetry ?
+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                                 // Rotation
+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                                 // Get the good tile number
+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                         // Transform rotation: invert rotation
+01624                         tileRotation += rotate;
+01625 
+01626                         // If goofy, add +2
+01627                         if (goofy && symmetry)
+01628                                 tileRotation += 2;
+01629 
+01630                         // Mask the rotation
+01631                         tileRotation &= 3;
+01632                 }
+01633                 else
+01634                         return false;
+01635         }
+01636 
+01637         // Ok
+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         // Tile exist ?
+01646         if ( (rotate!=0) || symmetry )
+01647         {
+01648                 // Symmetry ?
+01649                 if (symmetry)
+01650                 {
+01651                         // Take the symmetry
+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                 // Rotation ?
+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         // --- Export tile info Symmetry of the bind info.
+01675         // --- Parse each patch and each edge
+01676 
+01677         // For each patches
+01678         NL3D::CZoneSymmetrisation::CError error;
+01679         
+01680         // Build the structure
+01681         if (!zoneSymmetry.build (patchInfo, snapCell, weldThreshold, bank, error, toOriginalSpace))
+01682         {
+01683                 return false;
+01684         }
+01685         
+01686         // Symmetry ?
+01687         if (symmetry)
+01688         {
+01689                 for(i=0 ; i<patchCount; i++)
+01690                 {
+01691                         // Ref on the current patch
+01692                         CPatchInfo &pi = patchInfo[i];
+01693 
+01694                         // --- Symmetry vertex indexes
+01695 
+01696                         // Vertices
+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                         // Tangents
+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                         // Interior
+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                         // ** Symmetries tile colors
+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                                 // Store it in the tile info
+01735                                 uint index0 = u+v*(pi.OrderS+1);
+01736                                 uint index1 = (pi.OrderS-u)+v*(pi.OrderS+1);
+01737 
+01738                                 // XChg
+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                         // Smooth flags
+01745                         uint backupFlag = pi.Flags;
+01746                         for (int edge=0; edge<4; edge+=2)
+01747                         {
+01748                                 // Clear smooth flags
+01749                                 pi.Flags &= (1<<edge);
+01750 
+01751                                 // Symmetry edge
+01752                                 uint symEdge = ((edge+2)&3);
+01753 
+01754                                 // Copy the flag
+01755                                 pi.Flags |= (((backupFlag>>symEdge)&1)<<edge);
+01756                         }
+01757                 }
+01758 
+01759                 // --- Symmetry of the bind info.
+01760                 // --- Parse each patch and each edge
+01761                 // For each patches
+01762                 for (i=0 ; i<patchCount; i++)
+01763                 {
+01764                         // Ref on the patch info
+01765                         CPatchInfo &pi = patchInfo[i];
+01766 
+01767                         // Xchg left and right
+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                         // Flip edges
+01773                         for (uint edge=0; edge<4; edge++)
+01774                         {
+01775                                 // Ref on the patch info
+01776                                 CPatchInfo::CBindInfo &bindEdge = pi.BindEdges[edge];
+01777 
+01778                                 uint next;
+01779                                 // Look if it is a bind ?
+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                                 // Look if we are binded on a reversed edge
+01790                                 uint bindCount = (bindEdge.NPatchs==5) ? 1 : bindEdge.NPatchs;
+01791                                 for (next=0; next<bindCount; next++)
+01792                                 {
+01793                                         // Left or right ?
+01794                                         if ( (bindEdge.Edge[next] & 1) == 0)
+01795                                         {
+01796                                                 // Invert
+01797                                                 bindEdge.Edge[next] += 2;
+01798                                                 bindEdge.Edge[next] &= 3;
+01799                                         }
+01800                                 }
+01801                         }
+01802                 }
+01803         }
+01804 
+01805         // For each patches
+01806         for (i=0 ; i<patchCount; i++)
+01807         {
+01808                 // Tile infos
+01809                 CPatchInfo &pi = patchInfo[i];
+01810 
+01811                 // Backup tiles
+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                         // U tile
+01819                         int uSymmetry = symmetry ? (pi.OrderS-u-1) : u;
+01820 
+01821                         // Destination tile
+01822                         CTileElement &element = pi.Tiles[u+v*pi.OrderS];
+01823 
+01824                         // Copy the orginal symmetrical element
+01825                         element = tiles[uSymmetry+v*pi.OrderS];
+01826 
+01827                         // For each layer
+01828                         for (int l=0; l<3; l++)
+01829                         {
+01830                                 // Empty ?
+01831                                 if (element.Tile[l] != 0xffff)
+01832                                 {
+01833                                         // Get the tile index
+01834                                         uint tile = element.Tile[l];
+01835                                         uint tileRotation = element.getTileOrient (l);
+01836 
+01837                                         // Get rot and symmetry for this tile
+01838                                         uint tileRotate = rotate;
+01839                                         bool tileSymmetry = symmetry;
+01840                                         bool goofy = symmetry && (zoneSymmetry.getTileState (i, uSymmetry+v*pi.OrderS, l) == CZoneSymmetrisation::Goofy);
+01841 
+01842                                         // Transform the transfo
+01843                                         if (getTileSymmetryRotate (bank, tile, tileSymmetry, tileRotate))
+01844                                         {
+01845                                                 // Transform the tile
+01846                                                 if (!transformTile (bank, tile, tileRotation, tileSymmetry, (4-tileRotate)&3, goofy))
+01847                                                 {
+01848                                                         // Info
+01849                                                         nlwarning ("Error getting symmetrical / rotated zone tile.");
+01850                                                         return false;
+01851                                                 }
+01852                                         }
+01853                                         else
+01854                                         {
+01855                                                 // Info
+01856                                                 nlwarning ("Error getting symmetrical / rotated zone tile.");
+01857                                                 return false;
+01858                                         }
+01859 
+01860                                         // Set the tile
+01861                                         element.Tile[l] = tile;
+01862                                         element.setTileOrient (l, (uint8)tileRotation);
+01863                                 }
+01864                         }
+01865 
+01866                         // Empty ?
+01867                         if (element.Tile[0]!=0xffff)
+01868                         {
+01869                                 // Get 256 info
+01870                                 bool is256x256;
+01871                                 uint8 uvOff;
+01872                                 element.getTile256Info (is256x256, uvOff);
+01873 
+01874                                 // 256 ?
+01875                                 if (is256x256)
+01876                                 {
+01877                                         // Get rot and symmetry for this tile
+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                                         // Transform the transfo
+01884                                         getTileSymmetryRotate (bank, element.Tile[0], tileSymmetry, tileRotate);
+01885 
+01886                                         // Transform the case
+01887                                         transform256Case (bank, uvOff, tileRotation, tileSymmetry, (4-tileRotate)&3, goofy);
+01888 
+01889                                         element.setTile256Info (true, uvOff);
+01890                                 }
+01891                         }
+01892                 }
+01893         }
+01894 
+01895         // Ok
+01896         return true;
+01897 }
+01898 
+01899 // ***************************************************************************
+01900 
+01901 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1