# 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  

landscape_vegetable_block.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 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/landscape_vegetable_block.h"
00029 #include "3d/vegetable_manager.h"
00030 #include "3d/vegetable_clip_block.h"
00031 #include "3d/vegetable_instance_group.h"
00032 #include "3d/patch.h"
00033 #include "3d/bezier_patch.h"
00034 
00035 
00036 using namespace std;
00037 using namespace NLMISC;
00038 
00039 
00040 namespace NL3D 
00041 {
00042 
00043 
00044 // ***************************************************************************
00045 /*
00046         Distances type squared.
00047 */
00048 class   CLVBSqrDistLUT
00049 {
00050 public:
00051         static  float           Array[NL3D_VEGETABLE_BLOCK_NUMDIST+1];
00052 
00053         CLVBSqrDistLUT()
00054         {
00055                 // 0, 10, 20, 30, 40, 50
00056                 for(uint i=0;i<NL3D_VEGETABLE_BLOCK_NUMDIST+1;i++)
00057                 {
00058                         Array[i]= i*NL3D_VEGETABLE_BLOCK_ELTDIST;
00059                         Array[i]= sqr(Array[i]);
00060                 }
00061         }
00062 
00063 };
00064 
00065 
00066 CLVBSqrDistLUT  NL3D_InitSqrDistLUT;
00067 float           CLVBSqrDistLUT::Array[NL3D_VEGETABLE_BLOCK_NUMDIST+1];
00068 
00069 
00070 // ***************************************************************************
00071 CLandscapeVegetableBlock::CLandscapeVegetableBlock()
00072 {
00073         _VegetableClipBlock= NULL;
00074         _CurDistType= NL3D_VEGETABLE_BLOCK_NUMDIST;
00075 
00076         for(uint j=0;j<NL3D_TESSBLOCK_TILESIZE;j++)
00077         {
00078                 _VegetableSortBlock[j]= NULL;
00079                 for(uint i=0;i<NL3D_VEGETABLE_BLOCK_NUMDIST;i++)
00080                 {
00081                         _VegetableIG[j][i]= NULL;
00082                 }
00083         }
00084 }
00085 
00086 
00087 
00088 // ***************************************************************************
00089 void                    CLandscapeVegetableBlock::init(const CVector &center, CVegetableManager *vegetManager, 
00090         CVegetableClipBlock *vegetableClipBlock, CPatch *patch, uint ts, uint tt, CTessList<CLandscapeVegetableBlock> &vblist)
00091 {
00092         nlassert(patch);
00093         _Center= center;
00094         _VegetableClipBlock= vegetableClipBlock;
00095         _Patch= patch;
00096         _Ts= ts;
00097         _Tt= tt;
00098 
00099         // Create the Vegetable SortBlocks
00100         sint    tms,tmt;
00101         // for all tiles
00102         nlassert(NL3D_TESSBLOCK_TILESIZE==4);
00103         for(tmt= _Tt; tmt<_Tt+2; tmt++)
00104         {
00105                 for(tms= _Ts; tms<_Ts+2; tms++)
00106                 {
00107                         // compute approximate center of the tile.
00108                         float   s= (tms + 0.5f) / _Patch->getOrderS();
00109                         float   t= (tmt + 0.5f) / _Patch->getOrderT();
00110                         CBezierPatch    *bpatch= _Patch->unpackIntoCache();
00111                         CVector center= bpatch->eval(s, t);
00112 
00113                         // create the sortBlock. NB: very approximate SortBlock radius....
00114                         _VegetableSortBlock[(tmt-_Tt)*2 + (tms-_Ts)]= vegetManager->createSortBlock(_VegetableClipBlock, center, NL3D_PATCH_TILE_RADIUS);
00115                 }
00116         }
00117 
00118         // append to list.
00119         vblist.append(this);
00120 }
00121 
00122 
00123 // ***************************************************************************
00124 void                    CLandscapeVegetableBlock::release(CVegetableManager *vegeManager, CTessList<CLandscapeVegetableBlock> &vblist)
00125 {
00126         // release all Igs, and all Sbs.
00127         for(uint j=0;j<NL3D_TESSBLOCK_TILESIZE;j++)
00128         {
00129                 // release IGs first.
00130                 for(uint i=0;i<NL3D_VEGETABLE_BLOCK_NUMDIST;i++)
00131                 {
00132                         if(_VegetableIG[j][i])
00133                         {
00134                                 vegeManager->deleteIg(_VegetableIG[j][i]);
00135                                 _VegetableIG[j][i]= NULL;
00136                         }
00137                 }
00138 
00139                 // release SB
00140                 if(_VegetableSortBlock[j])
00141                 {
00142                         vegeManager->deleteSortBlock(_VegetableSortBlock[j]);
00143                         _VegetableSortBlock[j]= NULL;
00144                 }
00145         }
00146 
00147         // reset state.
00148         _CurDistType= NL3D_VEGETABLE_BLOCK_NUMDIST;
00149 
00150         // remove from list.
00151         vblist.remove(this);
00152 }
00153 
00154 // ***************************************************************************
00155 void                    CLandscapeVegetableBlock::update(const CVector &viewCenter, CVegetableManager *vegeManager)
00156 {
00157         float   sqrDist= (viewCenter-_Center).sqrnorm();
00158 
00159         // compute new distance type. Incremental mode.
00160         uint    newDistType= _CurDistType;
00161         while(sqrDist<CLVBSqrDistLUT::Array[newDistType])
00162         {
00163                 newDistType--;
00164         }
00165         while(newDistType<NL3D_VEGETABLE_BLOCK_NUMDIST && sqrDist>CLVBSqrDistLUT::Array[newDistType+1])
00166         {
00167                 newDistType++;
00168         }
00169         /*
00170                 NB: to test but may be better than 
00171                         newDistType= floor()(delta.norm() / NL3D_VEGETABLE_BLOCK_ELTDIST);
00172         */
00173 
00174 
00175         // Change of distance type??
00176         if(newDistType!=_CurDistType)
00177         {
00178                 // Erase or create IGs.
00179                 if(newDistType>_CurDistType)
00180                 {
00181                         // For all tiles
00182                         for(uint j=0;j<NL3D_TESSBLOCK_TILESIZE;j++)
00183                         {
00184                                 // Erase no more needed Igs.
00185                                 for(uint i=_CurDistType; i<newDistType; i++)
00186                                 {
00187                                         if(_VegetableIG[j][i])
00188                                         {
00189                                                 vegeManager->deleteIg(_VegetableIG[j][i]);
00190                                                 _VegetableIG[j][i]= NULL;
00191                                         }
00192                                 }
00193 
00194                                 // update the sort block for this tile
00195                                 _VegetableSortBlock[j]->updateSortBlock(*vegeManager);
00196                         }
00197                 }
00198                 else
00199                 {
00200                         // Create a context for creation.
00201                         CLandscapeVegetableBlockCreateContext   ctx;
00202                         ctx.init(_Patch, _Ts, _Tt);
00203 
00204                         // create new Igs, for all tiles
00205                         for(uint i=newDistType; i<_CurDistType; i++)
00206                         {
00207                                 createVegetableIGForDistType(i, vegeManager, ctx);
00208                         }
00209 
00210                         // For all tiles
00211                         for(uint j=0;j<NL3D_TESSBLOCK_TILESIZE;j++)
00212                         {
00213                                 // update the sort block for this tile
00214                                 _VegetableSortBlock[j]->updateSortBlock(*vegeManager);
00215                         }
00216                 }
00217 
00218                 // copy new dist type.
00219                 _CurDistType= newDistType;
00220         }
00221 
00222 
00223 }
00224 
00225 
00226 // ***************************************************************************
00227 void                    CLandscapeVegetableBlock::createVegetableIGForDistType(uint i, CVegetableManager *vegeManager,
00228         CLandscapeVegetableBlockCreateContext &vbCreateCtx)
00229 {
00230         // check
00231         nlassert(NL3D_TESSBLOCK_TILESIZE==4);
00232         nlassert(_VegetableIG[0][i]==NULL);
00233         nlassert(_VegetableIG[1][i]==NULL);
00234         nlassert(_VegetableIG[2][i]==NULL);
00235         nlassert(_VegetableIG[3][i]==NULL);
00236 
00237         // Create vegetables instances per tile_material.
00238         sint    tms,tmt;
00239         // for all tiles
00240         nlassert(NL3D_TESSBLOCK_TILESIZE==4);
00241         for(tmt= _Tt; tmt<_Tt+2; tmt++)
00242         {
00243                 for(tms= _Ts; tms<_Ts+2; tms++)
00244                 {
00245                         uint    tileId= tms-_Ts + (tmt-_Tt)*2;
00246 
00247                         // create the instance group in the good sortBlock
00248                         CVegetableInstanceGroup         *vegetIg= vegeManager->createIg(_VegetableSortBlock[tileId]);
00249                         _VegetableIG[tileId][i]= vegetIg;
00250 
00251                         // generate 
00252                         _Patch->generateTileVegetable(vegetIg, i, tms, tmt, vbCreateCtx);
00253 
00254                         // If the ig is empty, delete him. This optimize rendering because no unusefull ig are 
00255                         // tested for rendering. This speed up some 1/10 of ms...
00256                         if(vegetIg->isEmpty())
00257                         {
00258                                 vegeManager->deleteIg(vegetIg);
00259                                 _VegetableIG[tileId][i]= NULL;
00260                         }
00261 
00262                         // NB: vegtable SortBlock is updated in CLandscapeVegetableBlock::update() after
00263                 }
00264         }
00265 
00266 }
00267 
00268 
00269 // ***************************************************************************
00270 // ***************************************************************************
00271 // CLandscapeVegetableIGCreateContext
00272 // ***************************************************************************
00273 // ***************************************************************************
00274 
00275 
00276 // ***************************************************************************
00277 CLandscapeVegetableBlockCreateContext::CLandscapeVegetableBlockCreateContext()
00278 {
00279         _Patch= NULL;
00280 }
00281 
00282 
00283 // ***************************************************************************
00284 void                    CLandscapeVegetableBlockCreateContext::init(CPatch *patch, uint ts, uint tt)
00285 {
00286         nlassert(patch);
00287         _Empty= true;
00288         _Patch= patch;
00289         _Ts= ts;
00290         _Tt= tt;
00291 }
00292 
00293 
00294 // ***************************************************************************
00295 void                    CLandscapeVegetableBlockCreateContext::eval(uint ts, uint tt, float x, float y, CVector &pos)
00296 {
00297         nlassert(NL3D_TESSBLOCK_TILESIZE==4);
00298 
00299         // If never created, do it now
00300         // ==================
00301         if(_Empty)
00302         {
00303                 // Eval Position and normals for the 9 vertices (around the 2x2 tiles)
00304                 for(uint j=0; j<3;j++)
00305                 {
00306                         float   t= (float)(_Tt+j)/_Patch->getOrderT();
00307                         for(uint i=0; i<3;i++)
00308                         {
00309                                 float   s= (float)(_Ts+i)/_Patch->getOrderS();
00310                                 // eval position.
00311                                 // use computeVertex() and not bpatch->eval() because vegetables must follow the 
00312                                 // noise (at least at tile precision...). It is slower but necessary.
00313                                 _Pos[j*3+i]= _Patch->computeVertex(s, t);
00314                         }
00315                 }
00316 
00317                 // Ok, it's done
00318                 _Empty= false;
00319         }
00320 
00321 
00322         // Eval, with simple bilinear
00323         // ==================
00324         nlassert(ts==_Ts || ts==_Ts+1);
00325         nlassert(tt==_Tt || tt==_Tt+1);
00326         uint    ds= ts-_Ts;
00327         uint    dt= tt-_Tt;
00328         // Indices.
00329         uint    v00= dt*3 + ds;
00330         uint    v10= v00 + 1;
00331         uint    v01= v00 + 3;
00332         uint    v11= v00 + 4;
00333         // BiLinearFactor.
00334         float   dxdy= (1-x)*(1-y);
00335         float   dx2dy= x*(1-y);
00336         float   dxdy2= (1-x)*y;
00337         float   dx2dy2= x*y;
00338 
00339         // Compute Pos.
00340         pos = _Pos[v00] * dxdy;
00341         pos+= _Pos[v10] * dx2dy;
00342         pos+= _Pos[v01] * dxdy2;
00343         pos+= _Pos[v11] * dx2dy2;
00344 }
00345 
00346 
00347 } // NL3D