00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/vegetable.h"
00029 #include "nel/misc/common.h"
00030 #include "3d/vegetable_manager.h"
00031 #include "3d/fast_floor.h"
00032
00033
00034 using namespace std;
00035 using namespace NLMISC;
00036
00037
00038 namespace NL3D
00039 {
00040
00041
00042
00043
00044 static CNoiseValue RandomGenerator(0,1, 7.68f);
00045
00046
00047
00048 CVegetable::CVegetable()
00049 {
00050
00051 setAngleGround(0);
00052
00053
00054 MaxDensity= -1;
00055
00056
00057 Sxy.Abs= Sz.Abs= 1;
00058 Sxy.Rand= Sz.Rand= 0;
00059
00060 Rx.Abs= Ry.Abs= Rz.Abs= 0;
00061 Rx.Rand= Ry.Rand= Rz.Rand= 0;
00062
00063 BendFactor.Abs= 1;
00064 BendFactor.Rand= 0;
00065 BendFrequencyFactor= 1;
00066
00067
00068 DistType= 0;
00069
00070 _Manager= NULL;
00071 }
00072
00073
00074
00075 void CVegetable::setAngleGround(float cosAngleMin)
00076 {
00077 _AngleType= AngleGround;
00078
00079 _CosAngleMin= cosAngleMin;
00080
00081 _CosAngleMax= 1 + (1-cosAngleMin);
00082
00083
00084 _CosAngleMiddle= (_CosAngleMin + _CosAngleMax)/2;
00085 _OOCosAngleDist= _CosAngleMax - _CosAngleMiddle;
00086 if(_OOCosAngleDist)
00087 _OOCosAngleDist= 1.0f / _OOCosAngleDist;
00088 }
00089
00090
00091 void CVegetable::setAngleCeiling(float cosAngleMax)
00092 {
00093 _AngleType= AngleCeiling;
00094
00095 _CosAngleMax= cosAngleMax;
00096
00097 _CosAngleMin= -1 - (cosAngleMax-(-1));
00098
00099
00100 _CosAngleMiddle= (_CosAngleMin + _CosAngleMax)/2;
00101 _OOCosAngleDist= _CosAngleMax - _CosAngleMiddle;
00102 if(_OOCosAngleDist)
00103 _OOCosAngleDist= 1.0f / _OOCosAngleDist;
00104 }
00105
00106
00107 void CVegetable::setAngleWall(float cosAngleMin, float cosAngleMax)
00108 {
00109 _AngleType= AngleWall;
00110
00111 _CosAngleMin= cosAngleMin;
00112 _CosAngleMax= cosAngleMax;
00113
00114
00115 _CosAngleMiddle= (_CosAngleMin + _CosAngleMax)/2;
00116 _OOCosAngleDist= _CosAngleMax - _CosAngleMiddle;
00117 if(_OOCosAngleDist)
00118 _OOCosAngleDist= 1.0f / _OOCosAngleDist;
00119 }
00120
00121
00122
00123 void CVegetable::registerToManager(CVegetableManager *manager)
00124 {
00125 nlassert(manager);
00126 _Manager= manager;
00127 _VegetableShape= _Manager->getVegetableShape(ShapeName);
00128 }
00129
00130
00131
00132 void CVegetable::generateGroupEx(float nbInst, const CVector &posInWorld, const CVector &surfaceNormal, uint vegetSeed, std::vector<CVector2f> &instances) const
00133 {
00134
00135
00136
00137
00138
00139 float cosAngle= surfaceNormal.z;
00140
00141 float angleFact= 1 - sqr((cosAngle - _CosAngleMiddle) * _OOCosAngleDist);
00142 angleFact= max(0.f, angleFact);
00143
00144 nbInst*= angleFact;
00145
00146
00147
00148
00149
00150 nbInst+= 0.99f * RandomGenerator.evalOneLevelRandom(posInWorld);
00151
00152
00153 sint nbInstances= OptFastFloor(nbInst);
00154 nbInstances= max(0, nbInstances);
00155
00156
00157 instances.resize(nbInstances);
00158
00159
00160
00161
00162 static CVector2f dSeed(0.513f, 0.267f);
00163 CVector seed= posInWorld;
00164 seed.z+= vegetSeed * 0.723f;
00165 for(sint i=0; i<nbInstances; i++)
00166 {
00167 instances[i].x= RandomGenerator.evalOneLevelRandom(seed);
00168 seed.x+= dSeed.x;
00169 instances[i].y= RandomGenerator.evalOneLevelRandom(seed);
00170 seed.y+= dSeed.y;
00171 }
00172 }
00173
00174
00175
00176 void CVegetable::generateGroup(const CVector &posInWorld, const CVector &surfaceNormal, float area, uint vegetSeed, std::vector<CVector2f> &instances) const
00177 {
00178
00179 float dens= Density.eval(posInWorld);
00180 if(MaxDensity >= 0)
00181 dens= min(dens, MaxDensity);
00182 float nbInst= area * dens;
00183
00184
00185 generateGroupEx(nbInst, posInWorld, surfaceNormal, vegetSeed, instances);
00186 }
00187
00188
00189
00190 void CVegetable::generateGroupBiLinear(const CVector &posInWorld, const CVector posInWorldBorder[4], const CVector &surfaceNormal, float area, uint vegetSeed, std::vector<CVector2f> &instances) const
00191 {
00192 sint i;
00193 const float evenDistribFact= 12.25f;
00194
00195
00196
00197 float edgeDensity[4];
00198 for(i=0; i<4; i++)
00199 {
00200
00201 edgeDensity[i]= area * Density.eval(posInWorldBorder[i]);
00202 if(MaxDensity >= 0)
00203 edgeDensity[i]= min(edgeDensity[i], area * MaxDensity);
00204 edgeDensity[i]= max(0.f, edgeDensity[i]);
00205 }
00206
00207 float edgeDensityCenterX;
00208 float edgeDensityCenterY;
00209 edgeDensityCenterX= 0.5f * (edgeDensity[0] + edgeDensity[1]);
00210 edgeDensityCenterY= 0.5f * (edgeDensity[2] + edgeDensity[3]);
00211
00212
00213
00214 float nbInstAverage= 0.5f * (edgeDensityCenterX + edgeDensityCenterY);
00215
00216
00217
00218
00219 generateGroupEx(nbInstAverage, posInWorld, surfaceNormal, vegetSeed, instances);
00220
00221
00222
00223
00224
00225
00226 bool middleX= edgeDensityCenterX<=1;
00227 bool middleY= edgeDensityCenterY<=1;
00228 float OOEdgeDCX=0.0;
00229 float OOEdgeDCY=0.0;
00230 if(!middleX) OOEdgeDCX= 1.0f / edgeDensityCenterX;
00231 if(!middleY) OOEdgeDCY= 1.0f / edgeDensityCenterY;
00232
00233 for(i=0; i<(sint)instances.size(); i++)
00234 {
00235 float x= instances[i].x;
00236 float y= instances[i].y;
00237
00238 CVector randSeed(x*evenDistribFact, y*evenDistribFact, 0);
00239
00240
00241 if(middleX)
00242 {
00243
00244 x= x+x - easeInEaseOut(x);
00245 x= x+x - easeInEaseOut(x);
00246 instances[i].x= x;
00247 }
00248 else
00249 {
00250
00251
00252 float densX= edgeDensity[0]*(1-x) + edgeDensity[1]* x ;
00253
00254 if(densX < edgeDensityCenterX)
00255 {
00256
00257 float rdSwap= (densX * OOEdgeDCX );
00258
00259 rdSwap+= RandomGenerator.evalOneLevelRandom( randSeed );
00260 if(rdSwap<1)
00261 instances[i].x= 1 - instances[i].x;
00262 }
00263 }
00264
00265
00266 if(middleY)
00267 {
00268
00269 y= y+y - easeInEaseOut(y);
00270 y= y+y - easeInEaseOut(y);
00271 instances[i].y= y;
00272 }
00273 else
00274 {
00275
00276
00277 float densY= edgeDensity[2]*(1-y) + edgeDensity[3]* y ;
00278
00279 if(densY < edgeDensityCenterY)
00280 {
00281
00282 float rdSwap= (densY * OOEdgeDCY);
00283
00284 rdSwap+= RandomGenerator.evalOneLevelRandom( randSeed );
00285 if(rdSwap<1)
00286 instances[i].y= 1 - instances[i].y;
00287 }
00288 }
00289
00290 }
00291
00292 }
00293
00294
00295
00296 void CVegetable::reserveIgAddInstances(CVegetableInstanceGroupReserve &vegetIgReserve, TVegetableWater vegetWaterState, uint numInstances) const
00297 {
00298 nlassert(_Manager);
00299
00300 if (_VegetableShape)
00301 _Manager->reserveIgAddInstances(vegetIgReserve, _VegetableShape, (CVegetableManager::TVegetableWater)vegetWaterState, numInstances);
00302 }
00303
00304
00305
00306 void CVegetable::generateInstance(CVegetableInstanceGroup *ig, const NLMISC::CMatrix &posInWorld,
00307 const NLMISC::CRGBAF &modulateAmbientColor, const NLMISC::CRGBAF &modulateDiffuseColor, float blendDistMax,
00308 TVegetableWater vegetWaterState, CVegetableUV8 dlmUV) const
00309 {
00310 nlassert(_Manager);
00311
00312
00313 CVector seed= posInWorld.getPos();
00314
00315
00316
00317
00318
00319 CMatrix randomMat;
00320
00321 CVector rot;
00322 rot.x= Rx.eval(seed);
00323 rot.y= Ry.eval(seed);
00324 rot.z= Rz.eval(seed);
00325 randomMat.setRot(rot, CMatrix::ZXY);
00326
00327 if(Sxy.Abs!=0 || Sxy.Rand!=0 || Sz.Abs!=0 || Sz.Rand!=0)
00328 {
00329 CVector scale;
00330 scale.x= scale.y= Sxy.eval(seed);
00331 scale.z= Sz.eval(seed);
00332 randomMat.scale(scale);
00333 }
00334
00335
00336 CMatrix finalMatrix;
00337 finalMatrix= posInWorld * randomMat;
00338
00339
00340
00341 CRGBAF materialColor(1,1,1,1);
00342
00343 Color.eval(seed, materialColor);
00344
00345 CRGBAF ambient, diffuse;
00346 ambient= modulateAmbientColor * materialColor;
00347 diffuse= modulateDiffuseColor * materialColor;
00348
00349
00350 float bendFactor= BendFactor.eval(seed);
00351
00352 float bendPhase= BendPhase.eval(seed);
00353
00354
00355
00356
00357 if (_VegetableShape)
00358 {
00359 _Manager->addInstance(ig, _VegetableShape, finalMatrix, ambient, diffuse,
00360 bendFactor, bendPhase, BendFrequencyFactor, blendDistMax,
00361 (CVegetableManager::TVegetableWater)vegetWaterState, dlmUV);
00362 }
00363 }
00364
00365
00366
00367 void CVegetable::serial(NLMISC::IStream &f)
00368 {
00369
00370
00371
00372
00373
00374
00375 sint ver= f.serialVersion(1);
00376
00377 f.serial(ShapeName);
00378 f.serial(Density);
00379 f.serial(MaxDensity);
00380 f.serial(_CosAngleMin, _CosAngleMax, _CosAngleMiddle, _OOCosAngleDist);
00381 f.serialEnum(_AngleType);
00382 f.serial(Sxy, Sz);
00383 f.serial(Rx, Ry, Rz);
00384 f.serial(BendFactor);
00385 f.serial(BendPhase);
00386 f.serial(Color);
00387 f.serial(DistType);
00388
00389 if(ver>=1)
00390 f.serial(BendFrequencyFactor);
00391 else
00392 BendFrequencyFactor= 1;
00393 }
00394
00395
00396 }