# 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 "nel/3d/zone.h"
00027 #include "nel/3d/landscape.h"
00028 #include "nel/misc/common.h"
00029 
00030 
00031 using namespace NLMISC;
00032 using namespace std;
00033 
00034 
00035 // define it only for debug bind.
00036 //#define       NL3D_DEBUG_DONT_BIND_PATCH
00037 
00038 
00039 namespace NL3D {
00040 
00041 
00042 const sint      ClipIn= 0;
00043 const sint      ClipOut= 1;
00044 const sint      ClipSide= 2;
00045 
00046 
00047 // ***************************************************************************
00048 CZone::CZone()
00049 {
00050         ComputeTileErrorMetric= false;
00051         ZoneId= 0;
00052         Compiled= false;
00053         Landscape= NULL;
00054 }
00055 // ***************************************************************************
00056 CZone::~CZone()
00057 {
00058         // release() must have been called.
00059         nlassert(!Compiled);
00060 }
00061 
00062 
00063 // ***************************************************************************
00064 void                    CZone::computeBBScaleBias(const CAABBox &bb)
00065 {
00066         ZoneBB= bb;
00067         // Take a security for noise. (usefull for zone clipping).
00068         ZoneBB.setHalfSize(ZoneBB.getHalfSize()+CVector(NL3D_NOISE_MAX, NL3D_NOISE_MAX, NL3D_NOISE_MAX));
00069         CVector hs= ZoneBB.getHalfSize();
00070         float   rmax= maxof(hs.x, hs.y, hs.z);
00071         PatchScale= rmax / 32760;               // Prevent from float imprecision by taking 32760 and not 32767.
00072         PatchBias= ZoneBB.getCenter();
00073 }
00074 
00075 
00076 // ***************************************************************************
00077 void                    CZone::build(uint16 zoneId, const std::vector<CPatchInfo> &patchs, const std::vector<CBorderVertex> &borderVertices)
00078 {
00079         sint    i,j;
00080         nlassert(!Compiled);
00081 
00082         ZoneId= zoneId;
00083         BorderVertices= borderVertices;
00084 
00085         // Compute the bbox and the bias/scale.
00086         //=====================================
00087         CAABBox         bb;
00088         if(patchs.size())
00089                 bb.setCenter(patchs[0].Patch.Vertices[0]);
00090         bb.setHalfSize(CVector::Null);
00091         for(j=0;j<(sint)patchs.size();j++)
00092         {
00093                 const CBezierPatch      &p= patchs[j].Patch;
00094                 for(i=0;i<4;i++)
00095                         bb.extend(p.Vertices[i]);
00096                 for(i=0;i<8;i++)
00097                         bb.extend(p.Tangents[i]);
00098                 for(i=0;i<4;i++)
00099                         bb.extend(p.Interiors[i]);
00100         }
00101         // Compute BBox, and Patch Scale Bias, according to Noise.
00102         computeBBScaleBias(bb);
00103 
00104 
00105         // Compute/compress Patchs.
00106         //=========================
00107         Patchs.resize(patchs.size());
00108         PatchConnects.resize(patchs.size());
00109         sint    maxVertex=-1;
00110         for(j=0;j<(sint)patchs.size();j++)
00111         {
00112                 const CPatchInfo        &pi= patchs[j];
00113                 const CBezierPatch      &p= pi.Patch;
00114                 CPatch                          &pa= Patchs[j];
00115                 CPatchConnect           &pc= PatchConnects[j];
00116 
00117                 // Smoothing flags
00118                 pa.Flags&=~NL_PATCH_SMOOTH_FLAG_MASK;
00119                 pa.Flags|=NL_PATCH_SMOOTH_FLAG_MASK&(pi.Flags<<NL_PATCH_SMOOTH_FLAG_SHIFT);
00120 
00121                 // Build the patch.
00122                 for(i=0;i<4;i++)
00123                         pa.Vertices[i].pack(p.Vertices[i], PatchBias, PatchScale);
00124                 for(i=0;i<8;i++)
00125                         pa.Tangents[i].pack(p.Tangents[i], PatchBias, PatchScale);
00126                 for(i=0;i<4;i++)
00127                         pa.Interiors[i].pack(p.Interiors[i], PatchBias, PatchScale);
00128                 pa.Tiles= pi.Tiles;
00129                 pa.TileColors= pi.TileColors;
00130 
00131                 // Copy order of the patch
00132                 pa.OrderS= pi.OrderS;
00133                 pa.OrderT= pi.OrderT;
00134 
00135                 // Number of lumels in this patch
00136                 uint lumelCount=(pi.OrderS*NL_LUMEL_BY_TILE+1)*(pi.OrderT*NL_LUMEL_BY_TILE+1);
00137 
00138                 // Lumel empty ?
00139                 if (pi.Lumels.size ()==lumelCount)
00140                 {
00141                         // Pack the lumel map
00142                         pa.packShadowMap (&pi.Lumels[0]);
00143                 }
00144                 else
00145                 {
00146                         // Reset lightmap
00147                         pa.resetCompressedLumels ();
00148                 }
00149 
00150                 nlassert(pa.Tiles.size()== (uint)pi.OrderS*pi.OrderT);
00151                 nlassert(pa.TileColors.size()== (uint)(pi.OrderS+1)*(pi.OrderT+1));
00152 
00153                 // Build the patchConnect.
00154                 pc.ErrorSize= pi.ErrorSize;
00155                 for(i=0;i<4;i++)
00156                 {
00157                         pc.BaseVertices[i]= pi.BaseVertices[i];
00158                         maxVertex= max((sint)pc.BaseVertices[i], maxVertex);
00159                 }
00160                 for(i=0;i<4;i++)
00161                         pc.BindEdges[i]= pi.BindEdges[i];
00162         }
00163 
00164         NumVertices= maxVertex+1;
00165 }
00166 
00167 
00168 // ***************************************************************************
00169 void                    CZone::retrieve(std::vector<CPatchInfo> &patchs, std::vector<CBorderVertex> &borderVertices)
00170 {
00171         sint i,j;
00172 
00173         // uncompress Patchs.
00174         //=========================
00175         patchs.resize(Patchs.size());
00176         for(j=0;j<(sint)patchs.size();j++)
00177         {
00178                 CPatchInfo                      &pi= patchs[j];
00179                 CBezierPatch            &p= pi.Patch;
00180                 CPatch                          &pa= Patchs[j];
00181                 CPatchConnect           &pc= PatchConnects[j];
00182 
00183                 // re-Build the uncompressed bezier patch.
00184                 for(i=0;i<4;i++)
00185                         pa.Vertices[i].unpack(p.Vertices[i], PatchBias, PatchScale);
00186                 for(i=0;i<8;i++)
00187                         pa.Tangents[i].unpack(p.Tangents[i], PatchBias, PatchScale);
00188                 for(i=0;i<4;i++)
00189                         pa.Interiors[i].unpack(p.Interiors[i], PatchBias, PatchScale);
00190                 pi.Tiles= pa.Tiles;
00191                 pi.TileColors= pa.TileColors;
00192                 pi.Lumels.resize ((pa.OrderS*4+1)*(pa.OrderT*4+1));
00193 
00194                 // Unpack the lumel map
00195                 pa.unpackShadowMap (&pi.Lumels[0]);
00196 
00197                 // from the patchConnect.
00198                 pi.OrderS= pa.OrderS;
00199                 pi.OrderT= pa.OrderT;
00200                 pi.ErrorSize= pc.ErrorSize;
00201                 for(i=0;i<4;i++)
00202                 {
00203                         pi.BaseVertices[i]= pc.BaseVertices[i];
00204                 }
00205                 for(i=0;i<4;i++)
00206                         pi.BindEdges[i]= pc.BindEdges[i];
00207         }
00208 
00209         // retrieve bordervertices.
00210         //=========================
00211         borderVertices= BorderVertices;
00212 }
00213 
00214 
00215 // ***************************************************************************
00216 void                    CZone::build(const CZone &zone)
00217 {
00218         nlassert(!Compiled);
00219 
00220         ZoneId= zone.ZoneId;
00221         BorderVertices= zone.BorderVertices;
00222 
00223         // Compute the bbox and the bias/scale.
00224         //=====================================
00225         ZoneBB= zone.ZoneBB;
00226         PatchScale= zone.PatchScale;
00227         PatchBias= zone.PatchBias;
00228 
00229 
00230         // Compute/compress Patchs.
00231         //=========================
00232         Patchs= zone.Patchs;
00233         PatchConnects= zone.PatchConnects;
00234 
00235 
00236         NumVertices= zone.NumVertices;
00237 }
00238 
00239 
00240 
00241 // ***************************************************************************
00242 void                    CBorderVertex::serial(NLMISC::IStream &f)
00243 {
00244         uint    ver= f.serialVersion(0);
00245         f.serial(CurrentVertex, NeighborZoneId, NeighborVertex);
00246 }
00247 void                    CZone::CPatchConnect::serial(NLMISC::IStream &f)
00248 {
00249         uint    ver= f.serialVersion(1);
00250 
00251         if (ver<1)
00252                 f.serial(OldOrderS, OldOrderT, ErrorSize);
00253         else
00254                 f.serial(ErrorSize);
00255         f.serial(BaseVertices[0], BaseVertices[1], BaseVertices[2], BaseVertices[3]);
00256         f.serial(BindEdges[0], BindEdges[1], BindEdges[2], BindEdges[3]);
00257 }
00258 void                    CPatchInfo::CBindInfo::serial(NLMISC::IStream &f)
00259 {
00260         int             i;
00261         uint    ver= f.serialVersion(0);
00262         f.serial(NPatchs);
00263         f.serial(ZoneId);
00264         for(i=0;i<4;i++)
00265                 f.serial(Next[i]);
00266         for(i=0;i<4;i++)
00267                 f.serial(Edge[i]);
00268 }
00269 
00270 // ***************************************************************************
00271 void                    CZone::serial(NLMISC::IStream &f)
00272 {
00273         /*
00274         Version 2:
00275                 - Lumels.
00276         Version 1:
00277                 - Tile color.
00278         Version 0:
00279                 - base verison.
00280         */
00281         uint    ver= f.serialVersion(2);
00282 
00283         f.serialCheck((uint32)'ENOZ');
00284         f.serial(ZoneId, ZoneBB, PatchBias, PatchScale, NumVertices);
00285         f.serialCont(BorderVertices);
00286         f.serialCont(Patchs);
00287         f.serialCont(PatchConnects);
00288 
00289         // If read and version 0, must init default TileColors of patchs.
00290         //===============================================================
00291         if(f.isReading() && ver<2)
00292         {
00293                 for(sint j=0;j<(sint)Patchs.size();j++)
00294                 {
00295                         CPatch                          &pa= Patchs[j];
00296                         CPatchConnect           &pc= PatchConnects[j];
00297 
00298                         // Force Order of the patch
00299                         pa.OrderS=pc.OldOrderS;
00300                         pa.OrderT=pc.OldOrderT;
00301 
00302                         // Tile colors exist ?
00303                         if (ver<1)
00304                         {
00305                                 // Leave it as default behavior: Must init the color as pure white...
00306                                 // We must fo it with help of patchconnects OrderS and OrderT.
00307                                 pa.TileColors.resize( (pc.OldOrderS+1)*(pc.OldOrderT+1) );
00308                                 for(sint i=0;i<(sint)pa.TileColors.size();i++)
00309                                 {
00310                                         pa.TileColors[i].Color565= 0xFFFF;
00311                                         pa.TileColors[i].Shade= 0xFF;
00312                                         pa.TileColors[i].LightX= 0xFF;
00313                                         pa.TileColors[i].LightY= 0x00;
00314                                         pa.TileColors[i].LightZ= 0x00;
00315                                 }
00316                         }
00317 
00318                         // Lumels exist ?
00319                         if (ver<2)
00320                         {
00321                                 // Reset shadows
00322                                 pa.resetCompressedLumels ();
00323                         }
00324                 }
00325         }
00326 }
00327 
00328 
00329 // ***************************************************************************
00330 void                    CZone::compile(CLandscape *landscape, TZoneMap &loadedZones)
00331 {
00332         sint    i,j;
00333         TZoneMap                neighborZones;
00334 
00335         // Can't compile if compiled.
00336         nlassert(!Compiled);
00337         Landscape= landscape;
00338 
00339         // Attach this to loadedZones.
00340         //============================
00341         nlassert(loadedZones.find(ZoneId)==loadedZones.end());
00342         loadedZones[ZoneId]= this;
00343         
00344         // Create/link the base vertices according to present neigbor zones.
00345         //============================
00346         BaseVertices.clear();
00347         BaseVertices.resize(NumVertices);
00348         // First try to link vertices to other.
00349         for(i=0;i<(sint)BorderVertices.size();i++)
00350         {
00351                 sint    cur= BorderVertices[i].CurrentVertex;
00352                 sint    vertto= BorderVertices[i].NeighborVertex;
00353                 sint    zoneto= BorderVertices[i].NeighborZoneId;
00354                 nlassert(cur<NumVertices);
00355 
00356                 if(loadedZones.find(zoneto)!=loadedZones.end())
00357                 {
00358                         CZone   *zone;
00359                         zone= (*loadedZones.find(zoneto)).second;
00360                         nlassert(zone!=this);
00361                         // insert the zone in the neigborood (if not done...).
00362                         neighborZones[zoneto]= zone;
00363                         // Doesn't matter if BaseVertices is already linked to an other zone... 
00364                         // This should be the same pointer in this case...
00365                         BaseVertices[cur]=  zone->getBaseVertex(vertto);
00366                 }
00367         }
00368         // Else, create unbounded vertices.
00369         for(i=0;i<(sint)BaseVertices.size();i++)
00370         {
00371                 if(BaseVertices[i]==NULL)
00372                 {
00373                         BaseVertices[i]=  new CTessBaseVertex;
00374                 }
00375         }
00376 
00377 
00378         // compile() the patchs.
00379         //======================
00380         for(j=0;j<(sint)Patchs.size();j++)
00381         {
00382                 CPatch                          &pa= Patchs[j];
00383                 CPatchConnect           &pc= PatchConnects[j];
00384                 CTessVertex                     *baseVertices[4];
00385 
00386                 baseVertices[0]= &(BaseVertices[pc.BaseVertices[0]]->Vert);
00387                 baseVertices[1]= &(BaseVertices[pc.BaseVertices[1]]->Vert);
00388                 baseVertices[2]= &(BaseVertices[pc.BaseVertices[2]]->Vert);
00389                 baseVertices[3]= &(BaseVertices[pc.BaseVertices[3]]->Vert);
00390                 pa.compile(this, pa.OrderS, pa.OrderT, baseVertices, pc.ErrorSize);
00391         };
00392 
00393         // bind() the patchs. (after all compiled).
00394         //===================
00395         for(j=0;j<(sint)Patchs.size();j++)
00396         {
00397                 CPatch                          &pa= Patchs[j];
00398                 CPatchConnect           &pc= PatchConnects[j];
00399 
00400                 bindPatch(loadedZones, pa, pc);
00401         }
00402         
00403         
00404         // rebindBorder() on neighbor zones.
00405         //==================================
00406         ItZoneMap               zoneIt;
00407         // Traverse the neighborood.
00408         for(zoneIt= neighborZones.begin(); zoneIt!=neighborZones.end(); zoneIt++)
00409         {
00410                 (*zoneIt).second->rebindBorder(loadedZones);
00411         }
00412 
00413         // End!!
00414         Compiled= true;
00415 }
00416 
00417 // ***************************************************************************
00418 void                    CZone::release(TZoneMap &loadedZones)
00419 {
00420         sint    i,j;
00421 
00422         if(!Compiled)
00423                 return;
00424 
00425         // detach this zone to loadedZones.
00426         //=================================
00427         nlassert(loadedZones.find(ZoneId)!=loadedZones.end());
00428         loadedZones.erase(ZoneId);
00429         // It doesn't server to unbindPatch(), since patch is not binded to neigbors.
00430 
00431 
00432         // unbind() the patchs.
00433         //=====================
00434         for(j=0;j<(sint)Patchs.size();j++)
00435         {
00436                 CPatch                          &pa= Patchs[j];
00437                 CPatchConnect           &pc= PatchConnects[j];
00438                 unbindPatch(loadedZones, pa, pc);
00439                 /* 
00440                         This patch may be unbinded with exceptions (multiple patch case), but there is no problem, since in this case,
00441                         his neighbor will (or have precedently) unbind.
00442                         Since only Bind 1/1 are permitted on zone neighborood, there should be no problem:
00443                         patch are unbinded with no exceptions.
00444                 */
00445         }
00446 
00447 
00448         // rebindBorder() on neighbor zones.
00449         //==================================
00450         // Build the nieghborood.
00451         TZoneMap                neighborZones;
00452         for(i=0;i<(sint)BorderVertices.size();i++)
00453         {
00454                 sint    cur= BorderVertices[i].CurrentVertex;
00455                 sint    zoneto= BorderVertices[i].NeighborZoneId;
00456                 nlassert(cur<NumVertices);
00457 
00458                 if(loadedZones.find(zoneto)!=loadedZones.end())
00459                 {
00460                         CZone   *zone;
00461                         zone= (*loadedZones.find(zoneto)).second;
00462                         nlassert(zone!=this);
00463                         // insert the zone in the neigborood (if not done...).
00464                         neighborZones[zoneto]= zone;
00465                 }
00466         }
00467         // rebind borders.
00468         ItZoneMap               zoneIt;
00469         // Traverse the neighborood.
00470         for(zoneIt= neighborZones.begin(); zoneIt!=neighborZones.end(); zoneIt++)
00471         {
00472                 // Since 
00473                 (*zoneIt).second->rebindBorder(loadedZones);
00474         }
00475 
00476 
00477         // release() the patchs.
00478         //======================
00479         // unbind() need compiled neigbor patchs, so do the release after all unbind (so after rebindBorder() too...).
00480         for(j=0;j<(sint)Patchs.size();j++)
00481         {
00482                 CPatch                          &pa= Patchs[j];
00483                 pa.release();
00484         }
00485 
00486 
00487         // destroy/unlink the base vertices (internal..), according to present neigbor zones.
00488         //=================================
00489         // Just release the smartptrs (easy!!). Do it after patchs released...
00490         BaseVertices.clear();
00491         
00492 
00493         // End!!
00494         Compiled= false;
00495         Landscape= NULL;
00496 }
00497 
00498 
00499 // ***************************************************************************
00500 // ***************************************************************************
00501 // Private part.
00502 // ***************************************************************************
00503 // ***************************************************************************
00504 
00505 
00506 // ***************************************************************************
00507 void                    CZone::rebindBorder(TZoneMap &loadedZones)
00508 {
00509         sint    j;
00510 
00511         // rebind patchs which are on border.
00512         for(j=0;j<(sint)Patchs.size();j++)
00513         {
00514                 CPatch                          &pa= Patchs[j];
00515                 CPatchConnect           &pc= PatchConnects[j];
00516 
00517                 if(patchOnBorder(pc))
00518                         bindPatch(loadedZones, pa, pc);
00519         }
00520 }
00521 
00522 // ***************************************************************************
00523 CPatch          *CZone::getZonePatch(TZoneMap &loadedZones, sint zoneId, sint patch)
00524 {
00525 #ifdef NL3D_DEBUG_DONT_BIND_PATCH
00526         return NULL;
00527 #endif
00528         if(loadedZones.find(zoneId)==loadedZones.end())
00529                 return NULL;
00530         else
00531                 return (loadedZones[zoneId])->getPatch(patch);
00532 }
00533 
00534 
00535 // ***************************************************************************
00536 void            CZone::unbindAndMakeBindInfo(TZoneMap &loadedZones, CPatch &pa, CPatchConnect &pc, CPatch::CBindInfo    edges[4])
00537 {
00538         CPatch  *exceptions[4]= {NULL, NULL, NULL, NULL};
00539 
00540         /*
00541                 Remind: the old version with CPatch::unbindFrom*() doesn't work because of CZone::release(). This function
00542                 first erase the zone from loadedZones...
00543                 Not matter here. We use CPatch::unbind() which should do all the good job correctly (unbind pa from ohters
00544                 , and unbind others from pa at same time).
00545         */
00546 
00547         // Fill all edges.
00548         for(sint i=0;i<4;i++)
00549         {
00550                 CPatchInfo::CBindInfo   &pcBind= pc.BindEdges[i];
00551                 CPatch::CBindInfo               &paBind= edges[i];
00552 
00553                 nlassert(pcBind.NPatchs==0 || pcBind.NPatchs==1 || pcBind.NPatchs==2 || pcBind.NPatchs==4 || pcBind.NPatchs==5);
00554                 paBind.NPatchs= pcBind.NPatchs;
00555 
00556                 // Special case of a small patch connected to a bigger.
00557                 if(paBind.NPatchs==5)
00558                 {
00559                         // In this case, neither the unbind must not be done, nor the bind.
00560                         exceptions[i]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[0]);
00561                         // This code prevent the bind in CPatch::bind() to be done!!
00562                         // The bind must not be done, since exceptions[] prevent the unbind!
00563                         paBind.NPatchs=0;
00564                         continue;
00565                 }
00566 
00567 
00568                 if(paBind.NPatchs>=1)
00569                 {
00570                         paBind.Edge[0]= pcBind.Edge[0];
00571                         paBind.Next[0]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[0]);
00572                         // If not loaded, don't bind to this edge.
00573                         if(!paBind.Next[0])
00574                                 paBind.NPatchs=0;
00575                 }
00576                 if(paBind.NPatchs>=2)
00577                 {
00578                         paBind.Edge[1]= pcBind.Edge[1];
00579                         paBind.Next[1]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[1]);
00580                         // If not loaded, don't bind to this edge.
00581                         if(!paBind.Next[1])
00582                                 paBind.NPatchs=0;
00583                 }
00584                 if(paBind.NPatchs>=4)
00585                 {
00586                         paBind.Edge[2]= pcBind.Edge[2];
00587                         paBind.Edge[3]= pcBind.Edge[3];
00588                         paBind.Next[2]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[2]);
00589                         paBind.Next[3]= CZone::getZonePatch(loadedZones, pcBind.ZoneId, pcBind.Next[3]);
00590                         // If not loaded, don't bind to this edge.
00591                         if(!paBind.Next[2] || !paBind.Next[3])
00592                                 paBind.NPatchs=0;
00593                 }
00594         }
00595 
00596         pa.unbind(exceptions);
00597 }
00598 
00599 // ***************************************************************************
00600 void            CZone::bindPatch(TZoneMap &loadedZones, CPatch &pa, CPatchConnect &pc)
00601 {
00602         CPatch::CBindInfo       edges[4];
00603 
00604         unbindAndMakeBindInfo(loadedZones, pa, pc, edges);
00605 
00606         pa.bind(edges);
00607 }
00608 
00609 
00610 // ***************************************************************************
00611 void            CZone::unbindPatch(TZoneMap &loadedZones, CPatch &pa, CPatchConnect &pc)
00612 {
00613         CPatch::CBindInfo       edges[4];
00614 
00615         unbindAndMakeBindInfo(loadedZones,  pa, pc, edges);
00616 
00617         // Don't rebind.
00618 }
00619 
00620 
00621 // ***************************************************************************
00622 bool                    CZone::patchOnBorder(const CPatchConnect &pc) const
00623 {
00624         // If only one of neighbor patch is not of this zone, we are on a border.
00625 
00626         // Test all edges.
00627         for(sint i=0;i<4;i++)
00628         {
00629                 const CPatchInfo::CBindInfo     &pcBind= pc.BindEdges[i];
00630 
00631                 nlassert(pcBind.NPatchs==0 || pcBind.NPatchs==1 || pcBind.NPatchs==2 || pcBind.NPatchs==4 || pcBind.NPatchs==5);
00632                 if(pcBind.NPatchs>=1)
00633                 {
00634                         if(pcBind.ZoneId != ZoneId)
00635                                 return true;
00636                 }
00637         }
00638 
00639         return false;
00640 }
00641 
00642 
00643 // ***************************************************************************
00644 // ***************************************************************************
00645 // Render part.
00646 // ***************************************************************************
00647 // ***************************************************************************
00648 
00649 
00650 // ***************************************************************************
00651 void                    CZone::clip(const std::vector<CPlane>   &pyramid)
00652 {
00653         nlassert(Compiled);
00654 
00655         // Store current pyramid.
00656         CurrentPyramid= pyramid;
00657 
00658         // Fill ClipResult.
00659         ClipResult= ClipIn;
00660         for(sint i=0;i<(sint)pyramid.size();i++)
00661         {
00662                 // If entirely out.
00663                 if(!ZoneBB.clipBack(pyramid[i]))
00664                 {
00665                         ClipResult= ClipOut;
00666                         // If out of only one plane, out of all.
00667                         break;
00668                 }
00669                 // If partially IN (ie not entirely out, and not entirely IN)
00670                 else if(ZoneBB.clipFront(pyramid[i]))
00671                 {
00672                         // Force ClipResult to be ClipSide, and not ClipIn.
00673                         ClipResult=ClipSide;
00674                 }
00675         }
00676 
00677         // Fill computeTileErrorMetric.
00678         CBSphere                zonesphere(ZoneBB.getCenter(), ZoneBB.getRadius());
00679         if(zonesphere.intersect(CTessFace::TileFarSphere))
00680                 ComputeTileErrorMetric= true;
00681         else
00682                 ComputeTileErrorMetric= false;
00683 
00684         // Easy Clip  :)
00685         if(Patchs.size()==0)
00686         {
00687                 ClipResult= ClipOut;
00688         }
00689 
00690 
00691         // Clip By Patch Pass.
00692         //--------------------
00693         if(ClipResult==ClipOut)
00694         {
00695                 CPatch          *pPatch= &(*Patchs.begin());
00696                 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00697                 {
00698                         pPatch->forceClip();
00699                 }
00700         }
00701         else if(ClipResult==ClipIn)
00702         {
00703                 CPatch          *pPatch= &(*Patchs.begin());
00704                 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00705                 {
00706                         pPatch->forceNoClip();
00707                 }
00708         }
00709         else
00710         {
00711                 CPatch          *pPatch= &(*Patchs.begin());
00712                 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00713                 {
00714                         pPatch->clip(CurrentPyramid);
00715                 }
00716         }
00717 
00718 }
00719 
00720 
00721 // ***************************************************************************
00722 // DebugYoyo.
00723 // Code for Debug test Only.. Do not erase it, may be used later :)
00724 /*
00725 static  void    cleanTess(CTessFace *face)
00726 {
00727         if(!face->isLeaf())
00728         {
00729                 cleanTess(face->SonLeft);
00730                 cleanTess(face->SonRight);
00731         }
00732         // If has father, clean it.
00733         if(face->Father)
00734         {
00735                 CTessFace       *face1=face->Father;
00736                 CTessFace       *face2=face->Father->FBase;
00737                 face1->FLeft= face1->SonLeft->FBase;
00738                 face1->FRight= face1->SonRight->FBase;
00739                 if(face2!=NULL)
00740                 {
00741                         face2->FLeft= face2->SonLeft->FBase;
00742                         face2->FRight= face2->SonRight->FBase;
00743                 }
00744         }
00745 }
00746 static  void    testTess(CTessFace *face)
00747 {
00748         if(!face->isLeaf())
00749         {
00750                 testTess(face->SonLeft);
00751                 testTess(face->SonRight);
00752         }
00753         // Test validity.
00754         nlassert(!face->FBase || face->FBase->Patch!=(CPatch*)0xdddddddd);
00755         nlassert(!face->FLeft || face->FLeft->Patch!=(CPatch*)0xdddddddd);
00756         nlassert(!face->FRight || face->FRight->Patch!=(CPatch*)0xdddddddd);
00757 }
00758 static  void    checkTess()
00759 {
00760         // This test should be inserted at begin of CZone::refine().
00761         // And it needs hacking public/private.
00762         CPatch          *pPatch;
00763         sint            n;
00764         pPatch= &(*Patchs.begin());
00765         for(n=(sint)Patchs.size();n>0;n--, pPatch++)
00766         {
00767                 cleanTess(pPatch->Son0);
00768                 cleanTess(pPatch->Son1);
00769         }
00770         pPatch= &(*Patchs.begin());
00771         for(n=(sint)Patchs.size();n>0;n--, pPatch++)
00772         {
00773                 testTess(pPatch->Son0);
00774                 testTess(pPatch->Son1);
00775         }
00776 }
00777 */
00778 
00779 
00780 // ***************************************************************************
00781 // DebugYoyo.
00782 //volatile sint pipo1;
00783 //volatile sint pipo2;
00784 void                    CZone::refine()
00785 {
00786         nlassert(Compiled);
00787         // Must be 2^X-1.
00788         static const    sint    hideRefineFreq= 15;
00789 
00790         // DebugYoyo.
00791         // For the monkey bind test.
00792         /*extern sint numFrames;
00793         pipo1=(rand()>>12)&1;
00794         pipo2=(rand()>>12)&1;
00795         //if(pipo1 && numFrames>1360)
00796         if(true)
00797         {
00798                 TZoneMap        pipoMap;
00799                 pipoMap[ZoneId]= this;
00800                 bindPatch(pipoMap, Patchs[0], PatchConnects[0]);
00801         }*/
00802 
00803         
00804         // Force refine of invisible zones only every 8 times.
00805         if(ClipResult==ClipOut && (CTessFace::CurrentDate & hideRefineFreq)!=(ZoneId & hideRefineFreq))
00806                 return;
00807         // Fuck stlport....
00808         if(Patchs.size()==0)
00809                 return;
00810 
00811         CPatch          *pPatch= &(*Patchs.begin());
00812         if(ClipResult==ClipSide)
00813         {
00814                 // Force refine of invisible patchs only every 16 times.
00815                 // NB: do this only if zone is clipSide
00816                 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00817                 {
00818                         // "ZoneId+n", because there is only 70 approx patchs per zone. doing this may stabilize framerate.
00819                         if(pPatch->isClipped() && (CTessFace::CurrentDate & hideRefineFreq)!=((ZoneId+n) & hideRefineFreq))
00820                                 continue;
00821                         pPatch->refine();
00822                 }
00823         }
00824         else
00825         {
00826                 // Else refine ALL patchs (even those which may be invisible).
00827                 for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00828                 {
00829                         pPatch->refine();
00830                 }
00831         }
00832 
00833 }
00834 // ***************************************************************************
00835 void                    CZone::refineAll()
00836 {
00837         nlassert(Compiled);
00838 
00839         // Fuck stlport....
00840         if(Patchs.size()==0)
00841                 return;
00842 
00843         // Do a dummy clip.
00844         ComputeTileErrorMetric= true;
00845         ClipResult= ClipIn;
00846         CPatch          *pPatch= &(*Patchs.begin());
00847         sint n;
00848         for(n=(sint)Patchs.size();n>0;n--, pPatch++)
00849         {
00850                 pPatch->forceNoClip();
00851         }
00852 
00853 
00854         // refine ALL patchs (even those which may be invisible).
00855         pPatch= &(*Patchs.begin());
00856         for(n=(sint)Patchs.size();n>0;n--, pPatch++)
00857         {
00858                 pPatch->refine();
00859         }
00860 
00861 }
00862 
00863 // ***************************************************************************
00864 void                    CZone::preRender(const std::vector<CPlane>      &pyramid)
00865 {
00866         nlassert(Compiled);
00867         if(ClipResult==ClipOut)
00868                 return;
00869 
00870         // PreRender Pass.
00871         CPatch          *pPatch= &(*Patchs.begin());
00872         for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00873         {
00874                 pPatch->preRender(pyramid);
00875         }
00876 }
00877 // ***************************************************************************
00878 void                    CZone::renderFar0()
00879 {
00880         nlassert(Compiled);
00881         if(ClipResult==ClipOut)
00882                 return;
00883 
00884         // RenderFar0.
00885         CPatch          *pPatch= &(*Patchs.begin());
00886         for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00887         {
00888                 pPatch->renderFar0();
00889         }
00890 }
00891 // ***************************************************************************
00892 void                    CZone::renderFar1()
00893 {
00894         nlassert(Compiled);
00895         if(ClipResult==ClipOut)
00896                 return;
00897 
00898         // RenderFar1.
00899         CPatch          *pPatch= &(*Patchs.begin());
00900         for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00901         {
00902                 pPatch->renderFar1();
00903         }
00904 }
00905 // ***************************************************************************
00906 void                    CZone::renderTile(sint pass)
00907 {
00908         nlassert(Compiled);
00909         if(ClipResult==ClipOut)
00910                 return;
00911 
00912         // RenderTile.
00913         CPatch          *pPatch= &(*Patchs.begin());
00914         for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00915         {
00916                 pPatch->renderTile(pass);
00917         }
00918 }
00919 
00920 
00921 // ***************************************************************************
00922 void                    CZone::resetRenderFar()
00923 {
00924         CPatch          *pPatch= &(*Patchs.begin());
00925         for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00926         {
00927                 pPatch->resetRenderFar();
00928         }
00929 }
00930 
00931 
00932 // ***************************************************************************
00933 void                    CZone::forceMergeAtTileLevel()
00934 {
00935         CPatch          *pPatch= &(*Patchs.begin());
00936         for(sint n=(sint)Patchs.size();n>0;n--, pPatch++)
00937         {
00938                 pPatch->forceMergeAtTileLevel();
00939         }
00940 }
00941 
00942 
00943 // ***************************************************************************
00944 // ***************************************************************************
00945 // Misc part.
00946 // ***************************************************************************
00947 // ***************************************************************************
00948 
00949 
00950 // ***************************************************************************
00951 void                    CZone::changePatchTextureAndColor (sint numPatch, const std::vector<CTileElement> *tiles, const std::vector<CTileColor> *colors)
00952 {
00953         nlassert(numPatch>=0);
00954         nlassert(numPatch<getNumPatchs());
00955         
00956 
00957         // Update the patch texture.
00958         if (tiles)
00959         {
00960                 nlassert( Patchs[numPatch].Tiles.size() == tiles->size() );
00961                 Patchs[numPatch].Tiles = *tiles;
00962         }
00963 
00964         // Update the patch colors.
00965         if (colors)
00966         {
00967                 nlassert( Patchs[numPatch].TileColors.size() == colors->size() );
00968                 Patchs[numPatch].TileColors = *colors;
00969         }
00970 
00971         if (Compiled&&(tiles||colors))
00972         {
00973                 Patchs[numPatch].deleteTileUvs();
00974                 Patchs[numPatch].recreateTileUvs();
00975         }
00976 }
00977 
00978 
00979 // ***************************************************************************
00980 const std::vector<CTileElement> &CZone::getPatchTexture(sint numPatch) const
00981 {
00982         nlassert(numPatch>=0);
00983         nlassert(numPatch<getNumPatchs());
00984 
00985         // Update the patch texture.
00986         return Patchs[numPatch].Tiles;
00987 }
00988 
00989 
00990 // ***************************************************************************
00991 const std::vector<CTileColor> &CZone::getPatchColor(sint numPatch) const
00992 {
00993         nlassert(numPatch>=0);
00994         nlassert(numPatch<getNumPatchs());
00995 
00996         // Update the patch texture.
00997         return Patchs[numPatch].TileColors;
00998 }
00999 
01000 
01001 // ***************************************************************************
01002 void                    CZone::debugBinds(FILE *f)
01003 {
01004         fprintf(f, "*****************************\n");
01005         fprintf(f, "ZoneId: %d. NPatchs:%d\n", ZoneId, PatchConnects.size());
01006         sint i;
01007         for(i=0;i<(sint)PatchConnects.size();i++)
01008         {
01009                 CPatchConnect   &pc= PatchConnects[i];
01010                 fprintf(f, "patch%d:\n", i);
01011                 for(sint j=0;j<4;j++)
01012                 {
01013                         CPatchInfo::CBindInfo   &bd= pc.BindEdges[j];
01014                         fprintf(f, "    edge%d: Zone:%d. NPatchs:%d. ", j, bd.ZoneId, bd.NPatchs);
01015                         for(sint k=0;k<bd.NPatchs;k++)
01016                         {
01017                                 fprintf(f, "p%de%d - ", bd.Next[k], bd.Edge[k]);
01018                         }
01019                         fprintf(f, "\n");
01020                 }
01021         }
01022 
01023         fprintf(f,"Vertices :\n");
01024         for(i=0;i<(sint)BorderVertices.size();i++)
01025         {
01026                 fprintf(f,"current : %d -> (zone %d) vertex %d\n",BorderVertices[i].CurrentVertex,
01027                                                                                         BorderVertices[i].NeighborZoneId,
01028                                                                                         BorderVertices[i].NeighborVertex);
01029         }
01030 }
01031 
01032 
01033 // ***************************************************************************
01034 void                    CZone::applyHeightField(const CLandscape &landScape)
01035 {
01036         sint    i,j;
01037         vector<CBezierPatch>    patchs;
01038 
01039         // no patch, do nothing.
01040         if(Patchs.size()==0)
01041                 return;
01042 
01043         // 0. Unpack patchs to Bezier Patchs.
01044         //===================================
01045         patchs.resize(Patchs.size());
01046         for(j=0;j<(sint)patchs.size();j++)
01047         {
01048                 CBezierPatch            &p= patchs[j];
01049                 CPatch                          &pa= Patchs[j];
01050 
01051                 // re-Build the uncompressed bezier patch.
01052                 for(i=0;i<4;i++)
01053                         pa.Vertices[i].unpack(p.Vertices[i], PatchBias, PatchScale);
01054                 for(i=0;i<8;i++)
01055                         pa.Tangents[i].unpack(p.Tangents[i], PatchBias, PatchScale);
01056                 for(i=0;i<4;i++)
01057                         pa.Interiors[i].unpack(p.Interiors[i], PatchBias, PatchScale);
01058         }
01059 
01060         // 1. apply heightfield on bezier patchs.
01061         //===================================
01062         for(j=0;j<(sint)patchs.size();j++)
01063         {
01064                 CBezierPatch            &p= patchs[j];
01065 
01066                 // apply delta.
01067                 for(i=0;i<4;i++)
01068                         p.Vertices[i]+= landScape.getHeightFieldDeltaZ(p.Vertices[i].x, p.Vertices[i].y);
01069                 for(i=0;i<8;i++)
01070                         p.Tangents[i]+= landScape.getHeightFieldDeltaZ(p.Tangents[i].x, p.Tangents[i].y);
01071                 for(i=0;i<4;i++)
01072                         p.Interiors[i]+= landScape.getHeightFieldDeltaZ(p.Interiors[i].x, p.Interiors[i].y);
01073         }
01074 
01075 
01076         // 2. Re-compute Patch Scale/Bias, and Zone BBox.
01077         //===================================
01078         CAABBox         bb;
01079         bb.setCenter(patchs[0].Vertices[0]);
01080         bb.setHalfSize(CVector::Null);
01081         for(j=0;j<(sint)patchs.size();j++)
01082         {
01083                 // extend bbox.
01084                 const CBezierPatch      &p= patchs[j];
01085                 for(i=0;i<4;i++)
01086                         bb.extend(p.Vertices[i]);
01087                 for(i=0;i<8;i++)
01088                         bb.extend(p.Tangents[i]);
01089                 for(i=0;i<4;i++)
01090                         bb.extend(p.Interiors[i]);
01091         }
01092         // Compute BBox, and Patch Scale Bias, according to Noise.
01093         computeBBScaleBias(bb);
01094 
01095 
01096         // 3. Re-pack patchs.
01097         //===================================
01098         for(j=0;j<(sint)patchs.size();j++)
01099         {
01100                 CBezierPatch            &p= patchs[j];
01101                 CPatch                          &pa= Patchs[j];
01102 
01103                 // Build the packed patch.
01104                 for(i=0;i<4;i++)
01105                         pa.Vertices[i].pack(p.Vertices[i], PatchBias, PatchScale);
01106                 for(i=0;i<8;i++)
01107                         pa.Tangents[i].pack(p.Tangents[i], PatchBias, PatchScale);
01108                 for(i=0;i<4;i++)
01109                         pa.Interiors[i].pack(p.Interiors[i], PatchBias, PatchScale);
01110         }
01111 }
01112 
01113 
01114 
01115 } // NL3D