ps_tail_dot.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
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, /* dont delete */
00046                                                    false, /* not a file */
00047                                                    2, 1)
00048                                   );
00049     tex->setWrapS(ITexture::Clamp);
00050     tex->setShareName("#GradBW");
00051     return tex.release();
00052 }
00053 
00054 
00056 // CPSTailDot implementation //
00058 
00059 CPSTailDot::TVBMap          CPSTailDot::_VBMap;           // index / vertex buffers with no color
00060 CPSTailDot::TVBMap          CPSTailDot::_FadedVBMap;      // index / vertex buffers for constant color with fading
00061 CPSTailDot::TVBMap          CPSTailDot::_ColoredVBMap;    // index / vertex buffer + colors
00062 CPSTailDot::TVBMap          CPSTailDot::_FadedColoredVBMap;    // index / vertex buffer + faded colors
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 //  delete _DyingRibbons;
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         // here is CPSLocatedBindable::serial(f)
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) // edition mode only
00208     {
00209         //showTool();
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 //  if (!FilterPS[8]) return;
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(); // get the appropriate vb (built it if needed)
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); // for benchmark purpose
00271     const uint numRibbonBatch = getNumRibbonsInVB(); // number of ribons to process at once
00272     if (_UsedNbSegs == 0) return;
00273 
00275     // Material setup //
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     // Compute ribbons //
00305 
00306     uint toProcess;
00307     uint ribbonIndex = 0; // index of the first ribbon in the batch being processed
00308     uint32 fpRibbonIndex = 0; // fixed point index in source
00309     if (_ColorScheme)
00310     {
00311         _ColorScheme->setColorType(drv->getVertexColorFormat());
00312     }
00313     do
00314     {
00315         toProcess = std::min((uint) (nbRibbons - ribbonIndex) /* = left to do */, 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             // interpolate and project points the result is directly setup in the vertex buffer //
00331             if (!_Parametric)
00332             {
00333 
00335                 // INCREMENTAL CASE //
00337                 do
00338                 {
00339                     // the parent class has a method to get the ribbons positions
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                 // PARAMETRIC  CASE //
00351                 do
00352                 {
00353                     // we compute each pos thanks to the parametric curve
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         // display the result
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     //return _Owner->getMaxSize() * _NbSegs;
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)        // per ribbon coloçr
00406                                : (_ColorFading ? _FadedVBMap : _VBMap);     // global color
00407     TVBMap::iterator it = map.find(_UsedNbSegs + 1);
00408     if (it != map.end())
00409     {
00410         return it->second;
00411     }
00412     else    // must create this vb, with few different size, it is still interseting, though they are only destroyed at exit
00413     {
00414         const uint numRibbonInVB = getNumRibbonsInVB();
00415         CVBnPB &VBnPB = map[_UsedNbSegs + 1]; // make an entry
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 ); // 1 seg = 1 line + terminal vertices
00427 
00428         // set the primitive block size
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     {   // PER RIBBON COLOR
00491         if (ps.getForceGlobalColorLightingFlag() || usesGlobalColorLighting() || ps.getColorAttenuationScheme() || ps.isUserColorUsed())
00492         {
00493             if (_ColorFading) // global color + fading + per ribbon color
00494             {
00495                 // the first stage is used to get fading * global color
00496                 // the second stage multiply the result by the diffuse colot
00497                 if (ptGradTexture == NULL) // have we got a gradient texture ?
00498                 {
00499                     ptGradTexture = CreateGradientTexture();
00500                 }
00501                 _Mat.setTexture(0, ptGradTexture);
00502                 CPSMaterial::forceTexturedMaterialStages(2); // use constant color 0 * diffuse, 1 stage needed
00503                 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Constant);
00504                 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Diffuse);
00505             }
00506             else // per ribbon color with global color
00507             {
00508                 CPSMaterial::forceTexturedMaterialStages(1); // use constant color 0 * diffuse, 1 stage needed
00509                 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00510             }
00511         }
00512         else
00513         {
00514             if (_ColorFading) // per ribbon color, fading
00515             {
00516                 if (ptGradTexture == NULL) // have we got a gradient texture ?
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 // per color ribbon with no fading, and no global color
00525             {
00526                 CPSMaterial::forceTexturedMaterialStages(0); // no texture use constant diffuse only
00527             }
00528         }
00529     }
00530     else // GLOBAL COLOR
00531     {
00532         if (_ColorFading)
00533         {
00534             CPSMaterial::forceTexturedMaterialStages(1); // use constant color 0 * diffuse, 1 stage needed
00535             SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00536         }
00537         else // constant color
00538         {
00539             CPSMaterial::forceTexturedMaterialStages(0); // no texture use constant diffuse only
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 // GLOBAL COLOR with / without fading
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 // color attenuation, no fading :
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 // color attenuation, no fading :
00588             {
00589                 _Mat.setColor(col);
00590             }
00591         }
00592         else
00593         {
00594             if (_ColorFading)
00595             {
00596                 _Mat.texConstantColor(0, _Color);
00597             }
00598             else // constant color
00599             {
00600                 _Mat.setColor(_Color);
00601             }
00602         }
00603     }
00604 }
00605 
00606 } // NL3D

Generated on Thu Jan 7 08:26:30 2010 for NeL by  doxygen 1.6.1