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/ps_tail_dot.h"
00029 #include "3d/ps_macro.h"
00030 #include "3d/driver.h"
00031 #include "3d/particle_system.h"
00032 #include "3d/texture_mem.h"
00033 #include "nel/misc/smart_ptr.h"
00034
00035 #include <memory>
00036
00037 namespace NL3D
00038 {
00039 static NLMISC::CRGBA GradientB2W[] = {NLMISC::CRGBA(0, 0, 0, 0), NLMISC::CRGBA(255, 255, 255, 255) };
00040
00042 static ITexture *CreateGradientTexture()
00043 {
00044 std::auto_ptr<CTextureMem> tex(new CTextureMem((uint8 *) &GradientB2W,
00045 sizeof(GradientB2W),
00046 false,
00047 false,
00048 2, 1)
00049 );
00050 tex->setWrapS(ITexture::Clamp);
00051 tex->setShareName("#GradBW");
00052 return tex.release();
00053 }
00054
00055
00057
00059
00060 CPSTailDot::TVBMap CPSTailDot::_VBMap;
00061 CPSTailDot::TVBMap CPSTailDot::_FadedVBMap;
00062 CPSTailDot::TVBMap CPSTailDot::_ColoredVBMap;
00063 CPSTailDot::TVBMap CPSTailDot::_FadedColoredVBMap;
00064
00065
00066 CPSTailDot::CPSTailDot() : _ColorFading(false), _GlobalColor(false), _Touch(true)
00067 {
00068 setInterpolationMode(Linear);
00069 setSegDuration(0.06f);
00070 _Name = std::string("TailDot");
00071 }
00072
00073
00074 CPSTailDot::~CPSTailDot()
00075 {
00076
00077 }
00078
00079
00080 void CPSTailDot::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00081 {
00082
00083 sint ver = f.serialVersion(3);
00084 if (ver == 1)
00085 {
00086 nlassert(f.isReading());
00087
00090 sint ver2 = f.serialVersion(2);
00091
00092
00093 sint ver3 = f.serialVersion(4);
00094 f.serialPtr(_Owner);
00095 if (ver3 > 1) f.serialEnum(_LOD);
00096 if (ver3 > 2) f.serial(_Name);
00097 if (ver3 > 3)
00098 {
00099 if (f.isReading())
00100 {
00101 uint32 id;
00102 f.serial(id);
00103 setExternID(id);
00104 }
00105 else
00106 {
00107 f.serial(_ExternID);
00108 }
00109 }
00110
00111 if (ver2 >= 2)
00112 {
00113 bool bDisableAutoLOD;
00114 f.serial(bDisableAutoLOD);
00115 disableAutoLOD(bDisableAutoLOD);
00116 }
00117
00118 uint32 tailNbSegs;
00119 bool colorFading;
00120 bool systemBasisEnabled;
00121
00122 CPSColoredParticle::serialColorScheme(f);
00123 f.serial(tailNbSegs, colorFading, systemBasisEnabled);
00124
00125 _ColorFading = colorFading;
00126 _NbSegs = tailNbSegs >> 1;
00127 if (_NbSegs < 2) _NbSegs = 2;
00128 setInterpolationMode(Linear);
00129 serialMaterial(f);
00130
00131
00132 nlassert(_Owner);
00133 resize(_Owner->getMaxSize());
00134 initDateVect();
00135 resetFromOwner();
00136 }
00137
00138 if (ver >= 2)
00139 {
00140 CPSRibbonBase::serial(f);
00141 CPSColoredParticle::serialColorScheme(f);
00142 CPSMaterial::serialMaterial(f);
00143 bool colorFading = _ColorFading;
00144 f.serial(colorFading);
00145 _ColorFading = colorFading;
00146 if (ver >= 3)
00147 {
00148 uint32 tailNbSegs = _NbSegs;
00149 f.serial(tailNbSegs);
00150 }
00151 if (f.isReading())
00152 {
00153 setTailNbSeg(_NbSegs);
00154 touch();
00155 }
00156 }
00157 }
00158
00159
00160
00161 void CPSTailDot::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEt)
00162 {
00163 if (pass == PSMotion)
00164 {
00165 if (!_Parametric)
00166 {
00167 updateGlobals();
00168 }
00169 }
00170 else
00171 if (
00172 (pass == PSBlendRender && hasTransparentFaces())
00173 || (pass == PSSolidRender && hasOpaqueFaces())
00174 )
00175 {
00176 uint32 step;
00177 uint numToProcess;
00178 computeSrcStep(step, numToProcess);
00179 if (!numToProcess) return;
00180
00182 CParticleSystem &ps = *(_Owner->getOwner());
00183 _Mat.setColor(ps.getGlobalColor());
00184
00189 displayRibbons(numToProcess, step);
00190
00191 }
00192 else
00193 if (pass == PSToolRender)
00194 {
00195
00196 }
00197 }
00198
00199
00200
00201 void CPSTailDot::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
00202 {
00203 CPSRibbonBase::newElement(emitterLocated, emitterIndex);
00204 newColorElement(emitterLocated, emitterIndex);
00205 }
00206
00207
00208
00209 void CPSTailDot::deleteElement(uint32 index)
00210 {
00211 CPSRibbonBase::deleteElement(index);
00212 deleteColorElement(index);
00213 }
00214
00215
00216
00217 void CPSTailDot::resize(uint32 size)
00218 {
00219 nlassert(size < (1 << 16));
00220 CPSRibbonBase::resize(size);
00221 resizeColor(size);
00222 }
00223
00224
00225 void CPSTailDot::updateMatAndVbForColor(void)
00226 {
00227 touch();
00228 }
00229
00230
00231 void CPSTailDot::displayRibbons(uint32 nbRibbons, uint32 srcStep)
00232 {
00233 if (!nbRibbons) return;
00234 nlassert(_Owner);
00235 CPSRibbonBase::updateLOD();
00236 if (_UsedNbSegs < 2) return;
00237 const float date = _Owner->getOwner()->getSystemDate();
00238 uint8 *currVert;
00239 CVBnPB &VBnPB = getVBnPB();
00240 CVertexBuffer &VB = VBnPB.VB;
00241 CPrimitiveBlock &PB = VBnPB.PB;
00242 const uint32 vertexSize = VB.getVertexSize();
00243 uint colorOffset=0;
00244
00245 IDriver *drv = this->getDriver();
00246 setupDriverModelMatrix();
00247 drv->activeVertexBuffer(VB);
00248 _Owner->incrementNbDrawnParticles(nbRibbons);
00249 const uint numRibbonBatch = getNumRibbonsInVB();
00250 if (_UsedNbSegs == 0) return;
00251
00253
00255
00256 bool useGlobalColor = ps.getColorAttenuationScheme() != NULL;
00257 if (useGlobalColor != _GlobalColor)
00258 {
00259 touch();
00260 }
00261 updateMaterial();
00262 setupGlobalColor();
00263
00264 if (_ColorScheme)
00265 {
00266 colorOffset = VB.getColorOff();
00267 }
00268
00270
00272
00273 uint toProcess;
00274 uint ribbonIndex = 0;
00275 uint32 fpRibbonIndex = 0;
00276 do
00277 {
00278 toProcess = std::min((uint) (nbRibbons - ribbonIndex) , numRibbonBatch);
00279 currVert = (uint8 *) VB.getVertexCoordPointer();
00280
00282 if (_ColorScheme)
00283 {
00284 _ColorScheme->makeN(this->_Owner, ribbonIndex, currVert + colorOffset, vertexSize, toProcess, _UsedNbSegs + 1, srcStep);
00285 }
00286 uint k = toProcess;
00288
00290
00291 {
00292
00294
00296
00297 {
00298
00299 computeRibbon((uint) (fpRibbonIndex >> 16), (CVector *) currVert, vertexSize);
00300 currVert += vertexSize * (_UsedNbSegs + 1);
00301 fpRibbonIndex += srcStep;
00302 }
00303 while (--k);
00304 }
00305 else
00306 {
00308
00310
00311 {
00312
00313 _Owner->integrateSingle(date - _UsedSegDuration * (_UsedNbSegs + 1), _UsedSegDuration, _UsedNbSegs + 1, (uint) (fpRibbonIndex >> 16),
00314 (NLMISC::CVector *) currVert, vertexSize);
00315 currVert += vertexSize * (_UsedNbSegs + 1);
00316 fpRibbonIndex += srcStep;
00317 }
00318 while (--k);
00319
00320 }
00321 PB.setNumLine(_UsedNbSegs * toProcess);
00322
00323 drv->render(PB, _Mat);
00324 ribbonIndex += toProcess;
00325 }
00326 while (ribbonIndex != nbRibbons);
00327 }
00328
00329
00330 bool CPSTailDot::hasTransparentFaces(void)
00331 {
00332 return getBlendingMode() != CPSMaterial::alphaTest ;
00333 }
00334
00335
00336
00337 bool CPSTailDot::hasOpaqueFaces(void)
00338 {
00339 return !hasTransparentFaces();
00340 }
00341
00342
00343 uint32 CPSTailDot::getMaxNumFaces(void) const
00344 {
00345 nlassert(_Owner);
00346 return _Owner->getMaxSize() * _NbSegs;
00347 }
00348
00349
00350
00351
00352 CPSTailDot::CVBnPB &CPSTailDot::getVBnPB()
00353 {
00355 TVBMap &map = _ColorScheme ? (_ColorFading ? _FadedColoredVBMap : _ColoredVBMap)
00356 : (_ColorFading ? _FadedVBMap : _VBMap);
00357 TVBMap::iterator it = map.find(_UsedNbSegs + 1);
00358 if (it != map.end())
00359 {
00360 return it->second;
00361 }
00362 else
00363 {
00364 const uint numRibbonInVB = getNumRibbonsInVB();
00365 CVBnPB &VBnPB = map[_UsedNbSegs + 1];
00366
00370 CVertexBuffer &vb = VBnPB.VB;
00371 vb.setVertexFormat(CVertexBuffer::PositionFlag
00372 |(_ColorScheme || _ColorFading ? CVertexBuffer::PrimaryColorFlag : 0)
00373 | (_ColorScheme && _ColorFading ? CVertexBuffer::TexCoord0Flag : 0));
00374
00375 vb.setNumVertices((_UsedNbSegs + 1) * numRibbonInVB );
00376
00377
00378 CPrimitiveBlock &pb = VBnPB.PB;
00379 pb.setNumLine(_UsedNbSegs * numRibbonInVB);
00381 uint vbIndex = 0;
00382 uint pbIndex = 0;
00383 for (uint i = 0; i < numRibbonInVB; ++i)
00384 {
00385 for (uint k = 0; k < (_UsedNbSegs + 1); ++k)
00386 {
00387
00388 if (_ColorScheme && _ColorFading)
00389 {
00390 vb.setTexCoord(vbIndex, 0, 0.5f - 0.5f * ((float) k / _UsedNbSegs), 0);
00391 }
00392 else if (_ColorFading)
00393 {
00394 uint8 intensity = (uint8) (255 * (1.f - ((float) k / _UsedNbSegs)));
00395 NLMISC::CRGBA col(intensity, intensity, intensity, intensity);
00396 vb.setColor(vbIndex, col);
00397 }
00398
00400 if (k != _UsedNbSegs)
00401 {
00402 pb.setLine(pbIndex ++, vbIndex, vbIndex + 1);
00403 }
00404 ++vbIndex;
00405 }
00406 }
00407 return VBnPB;
00408 }
00409 }
00410
00411
00412 uint CPSTailDot::getNumRibbonsInVB() const
00413 {
00415 const uint vertexInVB = 256;
00416 return std::max(1u, (uint) (vertexInVB / (_UsedNbSegs + 1)));
00417 }
00418
00419
00420
00421 void CPSTailDot::updateMaterial()
00422 {
00423 if (!_Touch) return;
00424
00425 static NLMISC::CRefPtr<ITexture> ptGradTexture;
00426
00427 CParticleSystem &ps = *(_Owner->getOwner());
00428 if (_ColorScheme)
00429 {
00430 if (ps.getColorAttenuationScheme())
00431 {
00432 if (_ColorFading)
00433 {
00434
00435
00436 if (ptGradTexture == NULL)
00437 {
00438 ptGradTexture = CreateGradientTexture();
00439 }
00440 _Mat.setTexture(0, ptGradTexture);
00441 CPSMaterial::forceTexturedMaterialStages(2);
00442 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Constant);
00443 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Diffuse);
00444 }
00445 else
00446 {
00447 CPSMaterial::forceTexturedMaterialStages(1);
00448 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00449 }
00450 }
00451 else
00452 {
00453 if (_ColorFading)
00454 {
00455 if (ptGradTexture == NULL)
00456 {
00457 ptGradTexture = CreateGradientTexture();
00458 }
00459 _Mat.setTexture(0, ptGradTexture);
00460 CPSMaterial::forceTexturedMaterialStages(1);
00461 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00462 }
00463 else
00464 {
00465 CPSMaterial::forceTexturedMaterialStages(0);
00466 }
00467 }
00468 }
00469 else
00470 {
00471 if (_ColorFading)
00472 {
00473 CPSMaterial::forceTexturedMaterialStages(1);
00474 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00475 }
00476 else
00477 {
00478 CPSMaterial::forceTexturedMaterialStages(0);
00479 }
00480 }
00481
00482 _Touch = false;
00483 }
00484
00485
00486 void CPSTailDot::setupGlobalColor()
00487 {
00489 CParticleSystem &ps = *(_Owner->getOwner());
00490 if (_ColorScheme)
00491 {
00492 _Mat.texConstantColor(0, ps.getGlobalColor());
00493 }
00494 else
00495 {
00496 if (ps.getColorAttenuationScheme())
00497 {
00498 NLMISC::CRGBA col;
00499 col.modulateFromColor(ps.getGlobalColor(), _Color);
00500 if (_ColorFading)
00501 {
00502 _Mat.texConstantColor(0, col);
00503 }
00504 else
00505 {
00506 _Mat.setColor(col);
00507 }
00508 }
00509 else
00510 {
00511 if (_ColorFading)
00512 {
00513 _Mat.texConstantColor(0, _Color);
00514 }
00515 else
00516 {
00517 _Mat.setColor(_Color);
00518 }
00519 }
00520 }
00521 }
00522
00523
00524
00525
00526 }