00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028
00029 #include "3d/patch.h"
00030 #include "3d/vegetable.h"
00031 #include "3d/vegetable_manager.h"
00032 #include "3d/landscape_vegetable_block.h"
00033 #include "3d/landscape.h"
00034 #include "nel/misc/vector.h"
00035 #include "nel/misc/common.h"
00036 #include "3d/fast_floor.h"
00037 #include "3d/tile_vegetable_desc.h"
00038 #include "3d/vegetable_light_ex.h"
00039 #include "3d/patchdlm_context.h"
00040
00041
00042 using namespace std;
00043 using namespace NLMISC;
00044
00045 namespace NL3D
00046 {
00047
00048
00049
00050 void CPatch::generateTileVegetable(CVegetableInstanceGroup *vegetIg, uint distType, uint ts, uint tt,
00051 CLandscapeVegetableBlockCreateContext &vbCreateCtx)
00052 {
00053 uint i;
00054
00055
00056
00057
00058
00059 CTileElement::TVegetableInfo vegetWaterState= Tiles[tt * OrderS + ts].getVegetableState();
00060
00061 if(vegetWaterState == CTileElement::VegetableDisabled)
00062 return;
00063
00064
00065 uint tileId= Tiles[tt * OrderS + ts].Tile[0];
00066
00067
00068 const CTileVegetableDesc &tileVegetDesc= getLandscape()->getTileVegetableDesc(tileId);
00069 const std::vector<CVegetable> &vegetableList= tileVegetDesc.getVegetableList(distType);
00070 uint distAddSeed= tileVegetDesc.getVegetableSeed(distType);
00071 uint numVegetable= vegetableList.size();
00072
00073
00074 if(numVegetable==0)
00075 return;
00076
00077
00078 float tileU= (ts + 0.5f) / (float)OrderS;
00079 float tileV= (tt + 0.5f) / (float)OrderT;
00080 CBezierPatch *bpatch= unpackIntoCache();
00081
00082 CVector tilePos= bpatch->eval(tileU, tileV);
00083
00084
00085 CVector tileNormal= bpatch->evalNormal(tileU, tileV);
00086
00087
00088 CVector tilePosBiLinear[4];
00089 float OOos= 1.0f / OrderS;
00090 float OOot= 1.0f / OrderT;
00091 tilePosBiLinear[0]= bpatch->eval( (ts + 0.0f) * OOos, (tt + 0.5f) * OOot);
00092 tilePosBiLinear[1]= bpatch->eval( (ts + 1.0f) * OOos, (tt + 0.5f) * OOot);
00093 tilePosBiLinear[2]= bpatch->eval( (ts + 0.5f) * OOos, (tt + 0.0f) * OOot);
00094 tilePosBiLinear[3]= bpatch->eval( (ts + 0.5f) * OOos, (tt + 1.0f) * OOot);
00095
00096
00097
00098 CMatrix matInstance;
00099 matInstance.setRot(CVector::I, CVector::J, tileNormal);
00100
00101
00102 if(fabs(tileNormal.y) > fabs(tileNormal.x))
00103 matInstance.normalize(CMatrix::ZXY);
00104 else
00105 matInstance.normalize(CMatrix::ZYX);
00106
00107
00108
00109
00110
00111
00112 CRGBAF ambientF= CRGBAF(1,1,1,1);
00113
00114
00115 static uint8 tileLumelmap[NL_LUMEL_BY_TILE * NL_LUMEL_BY_TILE];
00116 getTileLumelmapPrecomputed(ts, tt, tileLumelmap, NL_LUMEL_BY_TILE);
00117
00118 CRGBAF diffuseColorF[NL_LUMEL_BY_TILE * NL_LUMEL_BY_TILE];
00119
00120
00121 for(i= 0; i<NL_LUMEL_BY_TILE*NL_LUMEL_BY_TILE; i++)
00122 {
00123
00124 sint tileLumel= 2*tileLumelmap[i];
00125 tileLumel= min(tileLumel, 255);
00126 float tlf= tileLumel / 255.f;
00127 diffuseColorF[i].R= tlf;
00128 diffuseColorF[i].G= tlf;
00129 diffuseColorF[i].B= tlf;
00130 diffuseColorF[i].A= 1;
00131 }
00132
00133
00134
00135 static vector<CPointLightInfluence> lightList;
00136 lightList.clear();
00137 appendTileLightInfluences( CUV(tileU, tileV), lightList);
00138
00139 for(i=0; i<lightList.size();i++)
00140 {
00141 CPointLight *pl= lightList[i].PointLight;
00142
00143 float att= pl->computeLinearAttenuation(tilePos);
00144
00145 lightList[i].BkupInfluence= lightList[i].Influence;
00146 lightList[i].Influence*= att;
00147 }
00148
00149 sort(lightList.begin(), lightList.end());
00150
00151 CVegetableLightEx &vegetLex= vegetIg->VegetableLightEx;
00152
00153 vegetLex.NumLights= min((uint)CVegetableLightEx::MaxNumLight, lightList.size());
00154 for(i=0;i<vegetLex.NumLights;i++)
00155 {
00156 CPointLight *pl= lightList[i].PointLight;
00157
00158 vegetLex.PointLight[i]= pl;
00159
00160 vegetLex.PointLightFactor[i]= (uint)(256* lightList[i].Influence);
00161
00162 vegetLex.Direction[i]= tilePos - pl->getPosition();
00163 vegetLex.Direction[i].normalize();
00164 }
00165
00166 vegetLex.computeCurrentColors();
00167
00168
00169
00170 nlassert(_DLMContext);
00171 CUV dlmUV;
00172
00173 dlmUV.U= _DLMContext->DLMUBias + _DLMContext->DLMUScale * tileU;
00174 dlmUV.V= _DLMContext->DLMVBias + _DLMContext->DLMVScale * tileV;
00175
00176 CVegetableUV8 dlmUV8;
00177 dlmUV8.U= (uint8)OptFastFloor(dlmUV.U * 255 + 0.5f);
00178 dlmUV8.V= (uint8)OptFastFloor(dlmUV.V * 255 + 0.5f);
00179
00180 clamp(dlmUV8.U, _DLMContext->MinU8, _DLMContext->MaxU8);
00181 clamp(dlmUV8.V, _DLMContext->MinV8, _DLMContext->MaxV8);
00182
00183
00184
00185
00186
00187
00188 typedef std::vector<NLMISC::CVector2f> TPositionVector;
00189 static std::vector<TPositionVector> instanceUVArray;
00190
00191 if(instanceUVArray.size() < numVegetable)
00192 {
00193
00194 contReset(instanceUVArray);
00195
00196 instanceUVArray.resize(numVegetable);
00197 }
00198
00199
00200 for(i= 0; i<numVegetable; i++)
00201 {
00202
00203 const CVegetable &veget= vegetableList[i];
00204
00205
00206 veget.generateGroupBiLinear(tilePos, tilePosBiLinear, tileNormal, NL3D_PATCH_TILE_AREA, i + distAddSeed, instanceUVArray[i]);
00207 }
00208
00209
00210 CVegetableInstanceGroupReserve vegetIgReserve;
00211 for(i= 0; i<numVegetable; i++)
00212 {
00213
00214 const CVegetable &veget= vegetableList[i];
00215
00216
00217
00218 veget.reserveIgAddInstances(vegetIgReserve, (CVegetable::TVegetableWater)vegetWaterState, instanceUVArray[i].size());
00219 }
00220
00221 getLandscape()->_VegetableManager->reserveIgCompile(vegetIg, vegetIgReserve);
00222
00223
00224
00225 for(i= 0; i<numVegetable; i++)
00226 {
00227
00228 const CVegetable &veget= vegetableList[i];
00229
00230
00231 std::vector<CVector2f> &instanceUV= instanceUVArray[i];
00232
00233
00234 for(uint j=0; j<instanceUV.size(); j++)
00235 {
00236
00237
00238 CVector instancePos;
00239 vbCreateCtx.eval(ts, tt, instanceUV[j].x, instanceUV[j].y, instancePos);
00240
00241 matInstance.setPos( instancePos );
00242
00243
00244 sint lumelS= OptFastFloor(instanceUV[j].x * NL_LUMEL_BY_TILE);
00245 sint lumelT= OptFastFloor(instanceUV[j].y * NL_LUMEL_BY_TILE);
00246 clamp(lumelS, 0, NL_LUMEL_BY_TILE-1);
00247 clamp(lumelT, 0, NL_LUMEL_BY_TILE-1);
00248
00249
00250 veget.generateInstance(vegetIg, matInstance, ambientF,
00251 diffuseColorF[ (lumelT<<NL_LUMEL_BY_TILE_SHIFT) + lumelS ],
00252 (distType+1) * NL3D_VEGETABLE_BLOCK_ELTDIST, (CVegetable::TVegetableWater)vegetWaterState, dlmUV8);
00253 }
00254 }
00255 }
00256
00257
00258
00259 void CPatch::recreateAllVegetableIgs()
00260 {
00261
00262 for(uint numtb=0; numtb<TessBlocks.size(); numtb++)
00263 {
00264
00265 if( TessBlocks[numtb].VegetableBlock==NULL && TessBlocks[numtb].TileMaterialRefCount>0
00266 && getLandscape()->isVegetableActive())
00267 {
00268
00269 uint tbWidth= OrderS>>1;
00270 uint ts= numtb&(tbWidth-1);
00271 uint tt= numtb/tbWidth;
00272
00273 createVegetableBlock(numtb, ts*2, tt*2);
00274 }
00275 }
00276
00277 }
00278
00279
00280
00281 void CPatch::deleteAllVegetableIgs()
00282 {
00283
00284 for(uint i=0; i<TessBlocks.size(); i++)
00285 {
00286 releaseVegetableBlock(i);
00287 }
00288
00289 }
00290
00291
00292
00293 void CPatch::createVegetableBlock(uint numTb, uint ts, uint tt)
00294 {
00295
00296 uint tbWidth= OrderS >> 1;
00297
00298 uint nTbPerCb= NL3D_PATCH_VEGETABLE_NUM_TESSBLOCK_PER_CLIPBLOCK;
00299 uint cbWidth= (tbWidth + nTbPerCb-1) >> NL3D_PATCH_VEGETABLE_NUM_TESSBLOCK_PER_CLIPBLOCK_SHIFT;
00300
00301
00302 uint tbs ,tbt;
00303 tbs= ts >> 1;
00304 tbt= tt >> 1;
00305
00306 uint cbs,cbt;
00307 cbs= tbs >> NL3D_PATCH_VEGETABLE_NUM_TESSBLOCK_PER_CLIPBLOCK_SHIFT;
00308 cbt= tbt >> NL3D_PATCH_VEGETABLE_NUM_TESSBLOCK_PER_CLIPBLOCK_SHIFT;
00309
00310
00311 CLandscapeVegetableBlock *vegetBlock= new CLandscapeVegetableBlock;
00312
00313
00314 CBezierPatch *bpatch= unpackIntoCache();
00315 CVector center= bpatch->eval( (float)(tbs*2+1)/OrderS, (float)(tbt*2+1)/OrderT );
00316
00317 vegetBlock->init(center, getLandscape()->_VegetableManager, VegetableClipBlocks[cbt *cbWidth + cbs], this, tbs*2, tbt*2, getLandscape()->_VegetableBlockList);
00318
00319
00320 TessBlocks[numTb].VegetableBlock= vegetBlock;
00321 }
00322
00323
00324
00325 void CPatch::releaseVegetableBlock(uint numTb)
00326 {
00327
00328 if(TessBlocks[numTb].VegetableBlock)
00329 {
00330
00331 TessBlocks[numTb].VegetableBlock->release(getLandscape()->_VegetableManager, getLandscape()->_VegetableBlockList);
00332
00333 delete TessBlocks[numTb].VegetableBlock;
00334 TessBlocks[numTb].VegetableBlock= NULL;
00335 }
00336 }
00337
00338
00339
00340
00341
00342 }