00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "std3d.h"
00025
00026 #include "nel/3d/ps_tail_dot.h"
00027 #include "nel/3d/ps_macro.h"
00028 #include "nel/3d/driver.h"
00029 #include "nel/3d/particle_system.h"
00030 #include "nel/3d/texture_mem.h"
00031 #include "nel/misc/smart_ptr.h"
00032
00033 #include <memory>
00034
00035 namespace NL3D
00036 {
00037 static NLMISC::CRGBA GradientB2W[] = {NLMISC::CRGBA(0, 0, 0, 0), NLMISC::CRGBA(255, 255, 255, 255) };
00038
00040 static ITexture *CreateGradientTexture()
00041 {
00042 NL_PS_FUNC(CreateGradientTexture)
00043 std::auto_ptr<CTextureMem> tex(new CTextureMem((uint8 *) &GradientB2W,
00044 sizeof(GradientB2W),
00045 false,
00046 false,
00047 2, 1)
00048 );
00049 tex->setWrapS(ITexture::Clamp);
00050 tex->setShareName("#GradBW");
00051 return tex.release();
00052 }
00053
00054
00056
00058
00059 CPSTailDot::TVBMap CPSTailDot::_VBMap;
00060 CPSTailDot::TVBMap CPSTailDot::_FadedVBMap;
00061 CPSTailDot::TVBMap CPSTailDot::_ColoredVBMap;
00062 CPSTailDot::TVBMap CPSTailDot::_FadedColoredVBMap;
00063
00064
00065 CPSTailDot::CPSTailDot() : _ColorFading(false),
00066 _GlobalColor(false),
00067 _Lighted(false),
00068 _ForceLighted(false),
00069 _Touch(true)
00070 {
00071 NL_PS_FUNC(CPSTailDot_CPSTailDot)
00072 setInterpolationMode(Linear);
00073 setSegDuration(0.06f);
00074 if (CParticleSystem::getSerializeIdentifierFlag()) _Name = std::string("TailDot");
00075 }
00076
00077
00078 CPSTailDot::~CPSTailDot()
00079 {
00080 NL_PS_FUNC(CPSTailDot_CPSTailDotDtor)
00081
00082 }
00083
00084
00085 void CPSTailDot::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00086 {
00087 NL_PS_FUNC(CPSTailDot_serial)
00088
00089 sint ver = f.serialVersion(3);
00090 if (ver == 1)
00091 {
00092 nlassert(f.isReading());
00093
00096 sint ver2 = f.serialVersion(2);
00097
00098
00099 sint ver3 = f.serialVersion(4);
00100 f.serialPtr(_Owner);
00101 if (ver3 > 1) f.serialEnum(_LOD);
00102 if (ver3 > 2) f.serial(_Name);
00103 if (ver3 > 3)
00104 {
00105 if (f.isReading())
00106 {
00107 uint32 id;
00108 f.serial(id);
00109 setExternID(id);
00110 }
00111 else
00112 {
00113 f.serial(_ExternID);
00114 }
00115 }
00116
00117 if (ver2 >= 2)
00118 {
00119 bool bDisableAutoLOD;
00120 f.serial(bDisableAutoLOD);
00121 disableAutoLOD(bDisableAutoLOD);
00122 }
00123
00124 uint32 tailNbSegs;
00125 bool colorFading;
00126 bool systemBasisEnabled;
00127
00128 CPSColoredParticle::serialColorScheme(f);
00129 f.serial(tailNbSegs, colorFading, systemBasisEnabled);
00130
00131 _ColorFading = colorFading;
00132 _NbSegs = tailNbSegs >> 1;
00133 if (_NbSegs < 2) _NbSegs = 2;
00134 setInterpolationMode(Linear);
00135 serialMaterial(f);
00136
00137
00138 nlassert(_Owner);
00139 resize(_Owner->getMaxSize());
00140 initDateVect();
00141 resetFromOwner();
00142 }
00143
00144 if (ver >= 2)
00145 {
00146 CPSRibbonBase::serial(f);
00147 CPSColoredParticle::serialColorScheme(f);
00148 CPSMaterial::serialMaterial(f);
00149 bool colorFading = _ColorFading;
00150 f.serial(colorFading);
00151 _ColorFading = colorFading;
00152 if (ver >= 3)
00153 {
00154 uint32 tailNbSegs = _NbSegs;
00155 f.serial(tailNbSegs);
00156 }
00157 if (f.isReading())
00158 {
00159 setTailNbSeg(_NbSegs);
00160 touch();
00161 }
00162 }
00163 }
00164
00165
00166
00167 void CPSTailDot::step(TPSProcessPass pass)
00168 {
00169 NL_PS_FUNC(CPSTailDot_step)
00170 if (pass == PSMotion)
00171 {
00172 if (!_Parametric)
00173 {
00174 updateGlobals();
00175 }
00176 }
00177 else
00178 if (
00179 (pass == PSBlendRender && hasTransparentFaces())
00180 || (pass == PSSolidRender && hasOpaqueFaces())
00181 )
00182 {
00183 uint32 step;
00184 uint numToProcess;
00185 computeSrcStep(step, numToProcess);
00186 if (!numToProcess) return;
00187
00189 CParticleSystem &ps = *(_Owner->getOwner());
00190 if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
00191 {
00192 _Mat.setColor(ps.getGlobalColorLighted());
00193 }
00194 else
00195 {
00196 _Mat.setColor(ps.getGlobalColor());
00197 }
00198
00203 displayRibbons(numToProcess, step);
00204
00205 }
00206 else
00207 if (pass == PSToolRender)
00208 {
00209
00210 }
00211 }
00212
00213
00214
00215 void CPSTailDot::newElement(const CPSEmitterInfo &info)
00216 {
00217 NL_PS_FUNC(CPSTailDot_newElement)
00218 CPSRibbonBase::newElement(info);
00219 newColorElement(info);
00220 }
00221
00222
00223
00224 void CPSTailDot::deleteElement(uint32 index)
00225 {
00226 NL_PS_FUNC(CPSTailDot_deleteElement)
00227 CPSRibbonBase::deleteElement(index);
00228 deleteColorElement(index);
00229 }
00230
00231
00232
00233 void CPSTailDot::resize(uint32 size)
00234 {
00235 NL_PS_FUNC(CPSTailDot_resize)
00236 nlassert(size < (1 << 16));
00237 CPSRibbonBase::resize(size);
00238 resizeColor(size);
00239 }
00240
00241
00242 void CPSTailDot::updateMatAndVbForColor(void)
00243 {
00244 NL_PS_FUNC(CPSTailDot_updateMatAndVbForColor)
00245 touch();
00246 }
00247
00248
00249 void CPSTailDot::displayRibbons(uint32 nbRibbons, uint32 srcStep)
00250 {
00251
00252 NL_PS_FUNC(CPSTailDot_displayRibbons)
00253 if (!nbRibbons) return;
00254 nlassert(_Owner);
00255 CPSRibbonBase::updateLOD();
00256 if (_UsedNbSegs < 2) return;
00257 const float date = _Owner->getOwner()->getSystemDate();
00258 uint8 *currVert;
00259 CVBnPB &VBnPB = getVBnPB();
00260 CVertexBuffer &VB = VBnPB.VB;
00261 CIndexBuffer &PB = VBnPB.PB;
00262 const uint32 vertexSize = VB.getVertexSize();
00263 uint colorOffset=0;
00264
00265 IDriver *drv = this->getDriver();
00266 #ifdef NL_DEBUG
00267 nlassert(drv);
00268 #endif
00269 drv->setupModelMatrix(getLocalToWorldTrailMatrix());
00270 _Owner->incrementNbDrawnParticles(nbRibbons);
00271 const uint numRibbonBatch = getNumRibbonsInVB();
00272 if (_UsedNbSegs == 0) return;
00273
00275
00277 CParticleSystem &ps = *(_Owner->getOwner());
00278 bool useGlobalColor = ps.getColorAttenuationScheme() != NULL || ps.isUserColorUsed();
00279 if (useGlobalColor != _GlobalColor)
00280 {
00281 _GlobalColor = useGlobalColor;
00282 touch();
00283 }
00284 if (usesGlobalColorLighting() != _Lighted)
00285 {
00286 _Lighted = usesGlobalColorLighting();
00287 touch();
00288 }
00289 if (ps.getForceGlobalColorLightingFlag() != _ForceLighted)
00290 {
00291 _ForceLighted = ps.getForceGlobalColorLightingFlag();
00292 touch();
00293 }
00294 updateMaterial();
00295 setupGlobalColor();
00296
00297 if (_ColorScheme)
00298 {
00299 colorOffset = VB.getColorOff();
00300 }
00301
00303
00305
00306 uint toProcess;
00307 uint ribbonIndex = 0;
00308 uint32 fpRibbonIndex = 0;
00309 if (_ColorScheme)
00310 {
00311 _ColorScheme->setColorType(drv->getVertexColorFormat());
00312 }
00313 do
00314 {
00315 toProcess = std::min((uint) (nbRibbons - ribbonIndex) , numRibbonBatch);
00316 VB.setNumVertices((_UsedNbSegs + 1) * toProcess);
00317 {
00318 CVertexBufferReadWrite vba;
00319 VB.lock (vba);
00320 currVert = (uint8 *) vba.getVertexCoordPointer();
00321
00323 if (_ColorScheme)
00324 {
00325 _ColorScheme->makeN(this->_Owner, ribbonIndex, currVert + colorOffset, vertexSize, toProcess, _UsedNbSegs + 1, srcStep);
00326 }
00327 uint k = toProcess;
00329
00331 if (!_Parametric)
00332 {
00333
00335
00337 do
00338 {
00339
00340 computeRibbon((uint) (fpRibbonIndex >> 16), (CVector *) currVert, vertexSize);
00341 currVert += vertexSize * (_UsedNbSegs + 1);
00342 fpRibbonIndex += srcStep;
00343 }
00344 while (--k);
00345 }
00346 else
00347 {
00349
00351 do
00352 {
00353
00354 _Owner->integrateSingle(date - _UsedSegDuration * (_UsedNbSegs + 1), _UsedSegDuration, _UsedNbSegs + 1, (uint) (fpRibbonIndex >> 16),
00355 (NLMISC::CVector *) currVert, vertexSize);
00356 currVert += vertexSize * (_UsedNbSegs + 1);
00357 fpRibbonIndex += srcStep;
00358 }
00359 while (--k);
00360
00361 }
00362 }
00363 const uint numLine = _UsedNbSegs * toProcess;
00364 PB.setNumIndexes(2 * numLine);
00365
00366 drv->activeIndexBuffer(PB);
00367 drv->activeVertexBuffer(VB);
00368 drv->renderLines (_Mat, 0, numLine);
00369 ribbonIndex += toProcess;
00370 }
00371 while (ribbonIndex != nbRibbons);
00372 }
00373
00374
00375 bool CPSTailDot::hasTransparentFaces(void)
00376 {
00377 NL_PS_FUNC(CPSTailDot_hasTransparentFaces)
00378 return getBlendingMode() != CPSMaterial::alphaTest ;
00379 }
00380
00381
00382
00383 bool CPSTailDot::hasOpaqueFaces(void)
00384 {
00385 NL_PS_FUNC(CPSTailDot_hasOpaqueFaces)
00386 return !hasTransparentFaces();
00387 }
00388
00389
00390 uint32 CPSTailDot::getNumWantedTris() const
00391 {
00392 NL_PS_FUNC(CPSTailDot_getNumWantedTris)
00393 nlassert(_Owner);
00394
00395 return _Owner->getSize() * _NbSegs;
00396 }
00397
00398
00399
00400
00401 CPSTailDot::CVBnPB &CPSTailDot::getVBnPB()
00402 {
00403 NL_PS_FUNC(CPSTailDot_getVBnPB)
00405 TVBMap &map = _ColorScheme ? (_ColorFading ? _FadedColoredVBMap : _ColoredVBMap)
00406 : (_ColorFading ? _FadedVBMap : _VBMap);
00407 TVBMap::iterator it = map.find(_UsedNbSegs + 1);
00408 if (it != map.end())
00409 {
00410 return it->second;
00411 }
00412 else
00413 {
00414 const uint numRibbonInVB = getNumRibbonsInVB();
00415 CVBnPB &VBnPB = map[_UsedNbSegs + 1];
00416
00420 CVertexBuffer &vb = VBnPB.VB;
00421 vb.setPreferredMemory(CVertexBuffer::AGPVolatile, true);
00422 vb.setVertexFormat(CVertexBuffer::PositionFlag
00423 |(_ColorScheme || _ColorFading ? CVertexBuffer::PrimaryColorFlag : 0)
00424 | (_ColorScheme && _ColorFading ? CVertexBuffer::TexCoord0Flag : 0));
00425
00426 vb.setNumVertices((_UsedNbSegs + 1) * numRibbonInVB );
00427
00428
00429 CIndexBuffer &pb = VBnPB.PB;
00430 pb.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
00431 pb.setNumIndexes(2 * _UsedNbSegs * numRibbonInVB);
00433 uint vbIndex = 0;
00434 uint pbIndex = 0;
00435 CIndexBufferReadWrite ibaWrite;
00436 pb.lock (ibaWrite);
00437 CVertexBufferReadWrite vba;
00438 vb.lock (vba);
00439 for (uint i = 0; i < numRibbonInVB; ++i)
00440 {
00441 for (uint k = 0; k < (_UsedNbSegs + 1); ++k)
00442 {
00443
00444 if (_ColorScheme && _ColorFading)
00445 {
00446 vba.setTexCoord(vbIndex, 0, 0.5f - 0.5f * ((float) k / _UsedNbSegs), 0);
00447 }
00448 else if (_ColorFading)
00449 {
00450 uint8 intensity = (uint8) (255 * (1.f - ((float) k / _UsedNbSegs)));
00451 NLMISC::CRGBA col(intensity, intensity, intensity, intensity);
00452 vba.setColor(vbIndex, col);
00453 }
00454
00456 if (k != _UsedNbSegs)
00457 {
00458 ibaWrite.setLine(pbIndex, vbIndex, vbIndex + 1);
00459 pbIndex+=2;
00460 }
00461 ++vbIndex;
00462 }
00463 }
00464 vb.setName("CPSTailDot");
00465 NL_SET_IB_NAME(pb, "CPSTailDot");
00466 return VBnPB;
00467 }
00468 }
00469
00470
00471 uint CPSTailDot::getNumRibbonsInVB() const
00472 {
00473 NL_PS_FUNC(CPSTailDot_getNumRibbonsInVB)
00475 const uint vertexInVB = 256;
00476 return std::max(1u, (uint) (vertexInVB / (_UsedNbSegs + 1)));
00477 }
00478
00479
00480
00481 void CPSTailDot::updateMaterial()
00482 {
00483 NL_PS_FUNC(CPSTailDot_updateMaterial)
00484 if (!_Touch) return;
00485
00486 static NLMISC::CRefPtr<ITexture> ptGradTexture;
00487
00488 CParticleSystem &ps = *(_Owner->getOwner());
00489 if (_ColorScheme)
00490 {
00491 if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting() || ps.getColorAttenuationScheme() || ps.isUserColorUsed())
00492 {
00493 if (_ColorFading)
00494 {
00495
00496
00497 if (ptGradTexture == NULL)
00498 {
00499 ptGradTexture = CreateGradientTexture();
00500 }
00501 _Mat.setTexture(0, ptGradTexture);
00502 CPSMaterial::forceTexturedMaterialStages(2);
00503 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Constant);
00504 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Diffuse);
00505 }
00506 else
00507 {
00508 CPSMaterial::forceTexturedMaterialStages(1);
00509 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00510 }
00511 }
00512 else
00513 {
00514 if (_ColorFading)
00515 {
00516 if (ptGradTexture == NULL)
00517 {
00518 ptGradTexture = CreateGradientTexture();
00519 }
00520 _Mat.setTexture(0, ptGradTexture);
00521 CPSMaterial::forceTexturedMaterialStages(1);
00522 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Diffuse);
00523 }
00524 else
00525 {
00526 CPSMaterial::forceTexturedMaterialStages(0);
00527 }
00528 }
00529 }
00530 else
00531 {
00532 if (_ColorFading)
00533 {
00534 CPSMaterial::forceTexturedMaterialStages(1);
00535 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00536 }
00537 else
00538 {
00539 CPSMaterial::forceTexturedMaterialStages(0);
00540 }
00541 }
00542
00543 _Touch = false;
00544 }
00545
00546
00547 void CPSTailDot::setupGlobalColor()
00548 {
00549 NL_PS_FUNC(CPSTailDot_setupGlobalColor)
00551 CParticleSystem &ps = *(_Owner->getOwner());
00552 if (_ColorScheme)
00553 {
00554 if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
00555 {
00556 _Mat.texConstantColor(0, ps.getGlobalColorLighted());
00557 }
00558 else
00559 {
00560 _Mat.texConstantColor(0, ps.getGlobalColor());
00561 }
00562 }
00563 else
00564 {
00565 if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting())
00566 {
00567 NLMISC::CRGBA col;
00568 col.modulateFromColor(ps.getGlobalColorLighted(), _Color);
00569 if (_ColorFading)
00570 {
00571 _Mat.texConstantColor(0, col);
00572 }
00573 else
00574 {
00575 _Mat.setColor(col);
00576 }
00577 }
00578 else
00579 if (ps.getColorAttenuationScheme() || ps.isUserColorUsed())
00580 {
00581 NLMISC::CRGBA col;
00582 col.modulateFromColor(ps.getGlobalColor(), _Color);
00583 if (_ColorFading)
00584 {
00585 _Mat.texConstantColor(0, col);
00586 }
00587 else
00588 {
00589 _Mat.setColor(col);
00590 }
00591 }
00592 else
00593 {
00594 if (_ColorFading)
00595 {
00596 _Mat.texConstantColor(0, _Color);
00597 }
00598 else
00599 {
00600 _Mat.setColor(_Color);
00601 }
00602 }
00603 }
00604 }
00605
00606 }