# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

ps_tail_dot.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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, /* dont delete */
00047                                                                                                    false, /* not a file */
00048                                                                                                    2, 1)
00049                                                                   );
00050         tex->setWrapS(ITexture::Clamp);
00051         tex->setShareName("#GradBW");
00052         return tex.release();
00053 }
00054 
00055 
00057 // CPSTailDot implementation //
00059 
00060 CPSTailDot::TVBMap                      CPSTailDot::_VBMap;                       // index / vertex buffers with no color
00061 CPSTailDot::TVBMap                      CPSTailDot::_FadedVBMap;          // index / vertex buffers for constant color with fading
00062 CPSTailDot::TVBMap                      CPSTailDot::_ColoredVBMap;    // index / vertex buffer + colors
00063 CPSTailDot::TVBMap                      CPSTailDot::_FadedColoredVBMap;    // index / vertex buffer + faded colors
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 //      delete _DyingRibbons;
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                 // here is CPSLocatedBindable::serial(f)
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) // edition mode only
00194         {                       
00195                 //showTool();
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(); // get the appropriate vb (built it if needed)
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); // for benchmark purpose          
00249         const uint numRibbonBatch = getNumRibbonsInVB(); // number of ribons to process at once         
00250         if (_UsedNbSegs == 0) return;
00251 
00253         // Material setup //
00255                 CParticleSystem &ps = *(_Owner->getOwner());
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         // Compute ribbons //
00272         
00273         uint toProcess;
00274         uint ribbonIndex = 0; // index of the first ribbon in the batch being processed 
00275         uint32 fpRibbonIndex = 0; // fixed point index in source
00276         do
00277         {
00278                 toProcess = std::min((uint) (nbRibbons - ribbonIndex) /* = left to do */, 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                 // interpolate and project points the result is directly setup in the vertex buffer //
00290                 if (!_Parametric)
00291                 {
00292 
00294                         // INCREMENTAL CASE //
00296                         do
00297                         {
00298                                 // the parent class has a method to get the ribbons positions
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                         // PARAMETRIC  CASE //
00310                         do
00311                         {
00312                                 // we compute each pos thanks to the parametric curve                           
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                 // display the result
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)                // per ribbon coloçr
00356                                                            : (_ColorFading ? _FadedVBMap : _VBMap);     // global color
00357         TVBMap::iterator it = map.find(_UsedNbSegs + 1);
00358         if (it != map.end())
00359         {
00360                 return it->second;
00361         }
00362         else    // must create this vb, with few different size, it is still interseting, though they are only destroyed at exit
00363         {
00364                 const uint numRibbonInVB = getNumRibbonsInVB();
00365                 CVBnPB &VBnPB = map[_UsedNbSegs + 1]; // make an entry
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 ); // 1 seg = 1 line + terminal vertices
00376 
00377                 // set the primitive block size
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         {       // PER RIBBON COLOR
00430                 if (ps.getColorAttenuationScheme())
00431                 {
00432                         if (_ColorFading) // global color + fading + per ribbon color
00433                         {
00434                                 // the first stage is used to get fading * global color
00435                                 // the second stage multiply the result by the diffuse colot
00436                                 if (ptGradTexture == NULL) // have we got a gradient texture ?
00437                                 {
00438                                         ptGradTexture = CreateGradientTexture();
00439                                 }
00440                                 _Mat.setTexture(0, ptGradTexture);
00441                                 CPSMaterial::forceTexturedMaterialStages(2); // use constant color 0 * diffuse, 1 stage needed                          
00442                                 SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Constant);
00443                                 SetupModulatedStage(_Mat, 1, CMaterial::Previous, CMaterial::Diffuse);
00444                         }
00445                         else // per ribbon color with global color 
00446                         {
00447                                 CPSMaterial::forceTexturedMaterialStages(1); // use constant color 0 * diffuse, 1 stage needed                          
00448                                 SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00449                         }
00450                 }
00451                 else
00452                 {       
00453                         if (_ColorFading) // per ribbon color, fading
00454                         {                               
00455                                 if (ptGradTexture == NULL) // have we got a gradient texture ?
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 // per color ribbon with no fading, and no global color
00464                         {
00465                                 CPSMaterial::forceTexturedMaterialStages(0); // no texture use constant diffuse only
00466                         }
00467                 }
00468         }
00469         else // GLOBAL COLOR
00470         {               
00471                 if (_ColorFading)
00472                 {
00473                         CPSMaterial::forceTexturedMaterialStages(1); // use constant color 0 * diffuse, 1 stage needed
00474                         SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
00475                 }
00476                 else // constant color
00477                 {
00478                         CPSMaterial::forceTexturedMaterialStages(0); // no texture use constant diffuse only                    
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 // GLOBAL COLOR with / without fading
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 // color attenuation, no fading : 
00505                         {                                                       
00506                                 _Mat.setColor(col);
00507                         }
00508                 }
00509                 else
00510                 {
00511                         if (_ColorFading)
00512                         {
00513                                 _Mat.texConstantColor(0, _Color);                               
00514                         }
00515                         else // constant color
00516                         {
00517                                 _Mat.setColor(_Color);
00518                         }
00519                 }
00520         }
00521 }
00522 
00523 
00524 
00525 
00526 } // NL3D