From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/ps__fan__light_8cpp-source.html | 592 +++++++++++++++++++++++ 1 file changed, 592 insertions(+) create mode 100644 docs/doxygen/nel/ps__fan__light_8cpp-source.html (limited to 'docs/doxygen/nel/ps__fan__light_8cpp-source.html') diff --git a/docs/doxygen/nel/ps__fan__light_8cpp-source.html b/docs/doxygen/nel/ps__fan__light_8cpp-source.html new file mode 100644 index 00000000..ad7fabe3 --- /dev/null +++ b/docs/doxygen/nel/ps__fan__light_8cpp-source.html @@ -0,0 +1,592 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# 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_fan_light.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_fan_light.h"
+00029 #include "3d/ps_macro.h"
+00030 #include "3d/ps_attrib_maker.h"
+00031 #include "3d/ps_iterator.h"
+00032 #include "3d/particle_system.h"
+00033 #include "3d/driver.h"
+00034 
+00035 
+00036 
+00037 namespace NL3D 
+00038 {
+00039 
+00040 
+00041 
+00043 // fan light implementation //
+00045 
+00046 
+00047 uint8 CPSFanLight::_RandomPhaseTab[32][128];
+00048 bool CPSFanLight::_RandomPhaseTabInitialized = false;
+00049 
+00050 CPSFanLight::TVBMap                             CPSFanLight::_VBMap; // fanlight, no texture
+00051 CPSFanLight::TVBMap                             CPSFanLight::_TexVBMap; // fanlight, textured
+00052 CPSFanLight::TVBMap                             CPSFanLight::_ColoredVBMap; // fanlight, no texture, varying color
+00053 CPSFanLight::TVBMap                             CPSFanLight::_ColoredTexVBMap; // fanlight, textured, varying color
+00054 CPSFanLight::TIBMap                             CPSFanLight::_IBMap;
+00055 
+00056 
+00057 static const uint FanLightBufSize  = 128; // the size of a buffer of particle to deal with at a time
+00058 static const uint NumVertsInBuffer = 4 * FanLightBufSize;
+00059 
+00060 
+00062 
+00068 class CPSFanLightHelper
+00069 {
+00070 public:
+00071         template <class T, class U>     
+00072         static void drawFanLight(T posIt, U timeIt, CPSFanLight &f, uint size, uint32 srcStep)
+00073         {
+00074                 PARTICLES_CHECK_MEM;
+00075                 nlassert(f._RandomPhaseTabInitialized);
+00076                 //
+00077                 f.setupDriverModelMatrix();
+00078                 const CVector I = f.computeI();
+00079                 const CVector K = f.computeK();         
+00080                 //              
+00081                 CVertexBuffer *vb;
+00082                 CPSFanLight::TIndexBuffer  *ib;
+00083                 // get (and build if necessary) the vb and the ib
+00084                 f.getVBnIB(vb, ib);
+00085                 IDriver *driver = f.getDriver();
+00086                 driver->activeVertexBuffer(*vb);
+00087                 const uint maxNumFanLightToDealWith = std::min(FanLightBufSize, f.getNumFanlightsInVB());       
+00088                 uint8 *randomPhaseTab = &f._RandomPhaseTab[f._PhaseSmoothness][0];
+00089                 f._Owner->incrementNbDrawnParticles(size); // for benchmark purpose                     
+00090                 float pSizes[FanLightBufSize];
+00091                 float pAngles[FanLightBufSize];
+00092                 T endPosIt;             
+00093 
+00094                 sint32 k; // helps to count the fans
+00095 
+00096                 
+00097                  // if so, we need to deal process separatly group of particles                 
+00098                 const uint32 stride = vb->getVertexSize();
+00099 
+00100                 float currentAngle;
+00101                 const float angleStep = 256.0f / f._NbFans;     
+00102 
+00103                 
+00104                 float *currentSizePt; // it points either the particle constant size, or a size in a table
+00105                 float *currentAnglePt; // it points either the particle constant angle, or an angle in a table
+00106 
+00107                 
+00108                 const uint32 currentSizePtIncrement = f._SizeScheme ? 1 : 0; // increment to get the next size for the size pointer. It is 0 if the size is constant
+00109                 const uint32 currentAnglePtIncrement = f._Angle2DScheme ? 1 : 0; // increment to get the next angle for the angle pointer. It is 0 if the size is constant
+00110                                 
+00111 
+00112                 uint leftToDo = size;
+00113                 do
+00114                 {                               
+00115                         uint8 *ptVect = (uint8 *) vb->getVertexCoordPointer();
+00116                         uint toProcess = std::min(leftToDo, maxNumFanLightToDealWith);                                                  
+00117                         // compute individual colors if needed
+00118                         if (f._ColorScheme)
+00119                         {
+00120                                 // we change the color at each fan light center
+00121                                 f._ColorScheme->make(f._Owner, size - leftToDo, vb->getColorPointer(), vb->getVertexSize() * (f._NbFans + 2), toProcess, false, srcStep);
+00122                         }
+00123                         if (f._SizeScheme)
+00124                         {
+00125                                 currentSizePt  = (float *) (f._SizeScheme->make(f._Owner, size - leftToDo, pSizes, sizeof(float), toProcess, true, srcStep));
+00126                                 currentSizePt = pSizes;
+00127                         }
+00128                         else
+00129                         {
+00130                                 currentSizePt = &f._ParticleSize;
+00131                         }
+00132                         if (f._Angle2DScheme)
+00133                         {
+00134                                 currentAnglePt = (float *) (f._Angle2DScheme->make(f._Owner, size - leftToDo, pAngles, sizeof(float), toProcess, true, srcStep));                                       
+00135                         }
+00136                         else
+00137                         {
+00138                                 currentAnglePt = &f._Angle2D;
+00139                         }                       
+00140                         //                                                              
+00141                         float fSize, firstSize, sizeStepBase=0.0, sizeStep;
+00142                         if (f._PhaseSmoothness)
+00143                         {
+00144                                 sizeStepBase = 1.f / f._PhaseSmoothness;
+00145                         }
+00146                         endPosIt = posIt + toProcess;
+00147                         for (;posIt != endPosIt; ++posIt, ++timeIt)
+00148                         {       
+00149                                 
+00150                                 CHECK_VERTEX_BUFFER(*vb, ptVect);
+00151                                 *(CVector *) ptVect = *posIt;                           
+00152                                 // the start angle
+00153                                 currentAngle = *currentAnglePt;
+00154                                 const uint8 phaseAdd = (uint8) (f._PhaseSpeed * (*timeIt));
+00155                                 ptVect += stride;
+00156                                 const float fanSize = *currentSizePt * 0.5f;
+00157                                 const float moveIntensity = f._MoveIntensity * fanSize;                         
+00158                                 // compute radius & vect for first fan
+00159                                 firstSize  = fanSize + (moveIntensity * CPSUtil::getCos(randomPhaseTab[0] + phaseAdd));
+00160                                 *(CVector *) ptVect = (*posIt) + I * firstSize * (CPSUtil::getCos((sint32) currentAngle))
+00161                                                                           + K * firstSize * (CPSUtil::getSin((sint32) currentAngle));
+00162                                 currentAngle += angleStep;
+00163                                 ptVect += stride;
+00164                                 fSize = firstSize;
+00165                                 // computes other fans
+00166                                 const sint32 upperBound = (sint32) (f._NbFans - f._PhaseSmoothness - 1);
+00167                                 for (k = 1; k <= upperBound; ++k)
+00168                                 {
+00169                                         fSize  = fanSize + (moveIntensity * CPSUtil::getCos(randomPhaseTab[k] + phaseAdd));
+00170                                         *(CVector *) ptVect = (*posIt) + I * fSize * (CPSUtil::getCos((sint32) currentAngle))
+00171                                                                                   + K * fSize * (CPSUtil::getSin((sint32) currentAngle));
+00172                                         currentAngle += angleStep;
+00173                                         ptVect += stride;
+00174                                 }
+00175 
+00176                                 // interpolate radius, so that the fanlight loops correctly
+00177                                 sizeStep = sizeStepBase * (firstSize - fSize);
+00178                                 for (; k <= (sint32) (f._NbFans - 1); ++k)
+00179                                 {                               
+00180                                         *(CVector *) ptVect = (*posIt) + I * fSize * (CPSUtil::getCos((sint32) currentAngle))
+00181                                                                                   + K * fSize * (CPSUtil::getSin((sint32) currentAngle));
+00182                                         currentAngle += angleStep;
+00183                                         ptVect += stride;
+00184                                         fSize  += sizeStep;
+00185                                 }
+00186                                 // last fan
+00187                                 *(CVector *) ptVect = (*posIt) + I * firstSize * (CPSUtil::getCos((sint32) *currentAnglePt))
+00188                                                                                   + K * firstSize * (CPSUtil::getSin((sint32) *currentAnglePt));
+00189                                 ptVect += stride;
+00190                                 currentSizePt += currentSizePtIncrement;
+00191                                 currentAnglePt += currentAnglePtIncrement;
+00192                         }                       
+00193                         driver->renderTriangles(f._Mat, &((*ib)[0]), toProcess * f._NbFans);
+00194                         leftToDo -= toProcess;
+00195                 }               
+00196                 while (leftToDo != 0);
+00197                 PARTICLES_CHECK_MEM;
+00198         }
+00199 };
+00200 
+00201         
+00203 // this blur a tab of bytes once
+00204 static void BlurBytesTab(const uint8 *src, uint8 *dest, uint size)
+00205 {
+00206         std::vector<uint8> b(src, src + size);
+00207         for (sint k = 1 ; k < (sint) (size - 1); ++k)
+00208         {
+00209                 dest[k] = (uint8) (((uint16) b[k - 1] + (uint16) b[k + 1])>>1);
+00210         }
+00211 }
+00212 
+00214 void CPSFanLight::initFanLightPrecalc(void)
+00215 {
+00216         // build several random tab, and linearly interpolate between l values
+00217         float currPhase, nextPhase, phaseStep;
+00218         for (uint l = 0; l < 32 ; l++)
+00219         {
+00220                 nextPhase = (float) (uint8) (rand()&0xFF);
+00221                 uint32 k = 0;
+00222                 while (k < 128)
+00223                 {
+00224                         currPhase = nextPhase;
+00225                         nextPhase = (float) (uint8) (rand()&0xFF);
+00226                         phaseStep = (nextPhase - currPhase) / (l + 1);
+00227 
+00228                         for (uint32 m = 0; m <= l; ++m)
+00229                         {
+00230                                 _RandomPhaseTab[l][k] = (uint8) currPhase;
+00231                                 currPhase += phaseStep;
+00232                                 ++k;
+00233                                 if (k >= 128) break;
+00234                         }
+00235                 }
+00236                 for (uint m = 0; m < 2 * l; ++m)
+00237                         BlurBytesTab(&_RandomPhaseTab[l][0], &_RandomPhaseTab[l][0], 128);
+00238         }       
+00239         //#ifdef NL_DEBUG
+00240                 _RandomPhaseTabInitialized = true;
+00241         //#endif
+00242 }
+00243 
+00245 uint32 CPSFanLight::getMaxNumFaces(void) const
+00246 {
+00247         nlassert(_Owner);
+00248         return _Owner->getMaxSize() * _NbFans;
+00249 }
+00250 
+00252 bool CPSFanLight::hasTransparentFaces(void)
+00253 {
+00254         return getBlendingMode() != CPSMaterial::alphaTest ;
+00255 }
+00256 
+00258 bool CPSFanLight::hasOpaqueFaces(void)
+00259 {
+00260         return !hasTransparentFaces();
+00261 }
+00262 
+00264 void CPSFanLight::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+00265 {
+00266         newColorElement(emitterLocated, emitterIndex);
+00267         newSizeElement(emitterLocated, emitterIndex);
+00268         newAngle2DElement(emitterLocated, emitterIndex);
+00269 }
+00270 
+00272 void CPSFanLight::deleteElement(uint32 index)
+00273 {
+00274         deleteColorElement(index);
+00275         deleteSizeElement(index);
+00276         deleteAngle2DElement(index);
+00277 }
+00278 
+00280 void CPSFanLight::setPhaseSpeed(float multiplier)
+00281 {
+00282         _PhaseSpeed = 256.0f * multiplier;
+00283 }
+00284 
+00286 inline void CPSFanLight::setupMaterial()
+00287 {
+00288         CParticleSystem &ps = *(_Owner->getOwner());
+00289         bool useGlobalColor = (ps.getColorAttenuationScheme() != NULL);
+00290         if (useGlobalColor != _UseGlobalColor)
+00291         {
+00292                 touch();
+00293                 _UseGlobalColor = useGlobalColor;
+00294         }
+00295         if (_Touched)
+00296         {               
+00298                 if (_Tex == NULL)
+00299                 {                               
+00300                         forceTexturedMaterialStages(1);
+00301                         SetupModulatedStage(_Mat, 0, CMaterial::Diffuse, CMaterial::Constant);
+00302                 }
+00303                 else
+00304                 {
+00305                         _Mat.setTexture(0, _Tex);
+00306                         forceTexturedMaterialStages(2);                         
+00307                         SetupModulatedStage(_Mat, 0, CMaterial::Texture, CMaterial::Constant);
+00308                         SetupModulatedStage(_Mat, 1, CMaterial::Diffuse, CMaterial::Previous);          
+00309                 }
+00310 
+00311                 if (!useGlobalColor)
+00312                 {
+00313                         if (!_ColorScheme)
+00314                         {
+00315                                 _Mat.texConstantColor(0, _Color);
+00316                         }
+00317                         else
+00318                         {
+00319                                 _Mat.texConstantColor(0, NLMISC::CRGBA::White);
+00320                         }
+00321                 }
+00322                 _Touched = false;
+00323         }       
+00324 
+00325         // always setup global colors 
+00326         if (useGlobalColor)
+00327         {                               
+00328                 if (_ColorScheme)
+00329                 {
+00330                         _Mat.texConstantColor(0, ps.getGlobalColor());
+00331                 }
+00332                 else
+00333                 {
+00334                         NLMISC::CRGBA col;
+00335                         col.modulateFromColor(ps.getGlobalColor(), _Color);
+00336                         _Mat.texConstantColor(0, col);
+00337                 }
+00338         }
+00339 }
+00340 
+00342 void CPSFanLight::draw(bool opaque)
+00343 {
+00344         PARTICLES_CHECK_MEM;    
+00345         if (!_Owner->getSize()) return; 
+00346 
+00347         uint32 step;
+00348         uint   numToProcess;
+00349         computeSrcStep(step, numToProcess);     
+00350         if (!numToProcess) return;
+00351         
+00352         setupMaterial();        
+00353         
+00354         if (step == (1 << 16))
+00355         {
+00356                 CPSFanLightHelper::drawFanLight(_Owner->getPos().begin(),
+00357                                                                             _Owner->getTime().begin(),
+00358                                                                            *this,
+00359                                                                                 numToProcess,
+00360                                                                                 step
+00361                                                                            );
+00362         }
+00363         else
+00364         {               
+00365                 CPSFanLightHelper::drawFanLight(TIteratorVectStep1616(_Owner->getPos().begin(), 0, step),
+00366                                                                                 TIteratorTimeStep1616(_Owner->getTime().begin(), 0, step),
+00367                                                                             *this,
+00368                                                                             numToProcess,
+00369                                                                             step                                
+00370                                                                            );
+00371         }
+00372         
+00373         PARTICLES_CHECK_MEM;
+00374 }
+00375 
+00377 void CPSFanLight::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+00378 {
+00379         sint ver = f.serialVersion(2);
+00380         CPSParticle::serial(f);
+00381         CPSColoredParticle::serialColorScheme(f);       
+00382         CPSSizedParticle::serialSizeScheme(f);  
+00383         CPSRotated2DParticle::serialAngle2DScheme(f);
+00384         f.serial(_NbFans);
+00385         serialMaterial(f);
+00386         if (ver > 1)
+00387         {
+00388                 f.serial(_PhaseSmoothness, _MoveIntensity);
+00389                 ITexture *tex = _Tex;
+00390                 f.serialPolyPtr(tex);
+00391                 if (f.isReading()) _Tex = tex ;
+00392         }
+00393         if (f.isReading())
+00394         {
+00395                 init();         
+00396         }       
+00397 }
+00398 
+00400 bool CPSFanLight::completeBBox(NLMISC::CAABBox &box) const
+00401 {
+00402         // TODO
+00403 
+00404         return false;
+00405 }
+00406 
+00408 CPSFanLight::CPSFanLight(uint32 nbFans) : _NbFans(nbFans),
+00409                                                                                   _PhaseSmoothness(0),
+00410                                                                                   _MoveIntensity(1.5f),
+00411                                                                                   _Tex(NULL),
+00412                                                                                   _PhaseSpeed(256),
+00413                                                                                   _Touched(true),
+00414                                                                                   _UseGlobalColor(false)
+00415 
+00416 {
+00417         nlassert(nbFans >= 3);
+00418 
+00419 
+00420         init();
+00421         _Name = std::string("FanLight");
+00422 }
+00423 
+00424 
+00426 CPSFanLight::~CPSFanLight()
+00427 {
+00428 }
+00429 
+00430 
+00432 void CPSFanLight::setNbFans(uint32 nbFans)
+00433 {
+00434         _NbFans = nbFans;
+00435 
+00436         resize(_Owner->getMaxSize());
+00437 
+00438         notifyOwnerMaxNumFacesChanged();
+00439 }
+00440 
+00442 void CPSFanLight::resize(uint32 size)
+00443 {       
+00444         nlassert(size < (1 << 16));
+00445         resizeColor(size);
+00446         resizeAngle2D(size);
+00447         resizeSize(size);
+00448         
+00449 }
+00450 
+00452 void CPSFanLight::init(void)
+00453 {
+00454         _Mat.setLighting(false);        
+00455         _Mat.setZFunc(CMaterial::less);
+00456         _Mat.setDoubleSided(true);
+00457         _Mat.setColor(NLMISC::CRGBA::White);
+00458 
+00459         updateMatAndVbForColor();
+00460 }
+00461 
+00463 void CPSFanLight::updateMatAndVbForColor(void)
+00464 {       
+00465         touch();
+00466 }
+00467 
+00469 void CPSFanLight::getVBnIB(CVertexBuffer *&retVb, CPSFanLight::TIndexBuffer *&retIb)
+00470 {
+00471         TVBMap &vbMap = _ColorScheme ? (_Tex == NULL  ? _ColoredVBMap : _ColoredTexVBMap)
+00472                                                                  : (_Tex == NULL  ? _VBMap : _TexVBMap);
+00473         TVBMap::iterator vbIt = vbMap.find(_NbFans);
+00474         if (vbIt != vbMap.end())
+00475         {
+00476                 retVb = &(vbIt->second);
+00477                 TIBMap::iterator pbIt = _IBMap.find(_NbFans);
+00478                 nlassert(pbIt != _IBMap.end());
+00479                 retIb = &(pbIt->second);
+00480         }
+00481         else // we need to create the vb
+00482         {               
+00483                 // create an entry (we setup the primitive block at the same time, this could be avoided, but doesn't make much difference)             
+00484                 CVertexBuffer &vb = vbMap[_NbFans]; // create a vb
+00485                 TIndexBuffer &ib = _IBMap[_NbFans]; // eventually create a pb
+00486                 const uint32 size = getNumFanlightsInVB();
+00487                 vb.setVertexFormat(CVertexBuffer::PositionFlag |
+00488                                                    CVertexBuffer::PrimaryColorFlag |
+00489                                                    (_Tex != NULL ?  CVertexBuffer::TexCoord0Flag : 0) 
+00490                                                   );
+00491                 vb.setNumVertices(size * (2 + _NbFans));                        
+00492                 ib.resize(size * _NbFans * 3);          
+00493                 // pointer on the current index to fill
+00494                 TIndexBuffer::iterator ptIndex = ib.begin();    
+00495                 
+00496                 // index of the first vertex of the current fanFilght
+00497                 uint currVertFan = 0;
+00498 
+00499                 uint l; // the current fan in the current fanlight
+00500                 uint k; // the current fan light
+00501 
+00502                 for (k = 0; k < size; ++k)
+00503                 {
+00504                         for (l = 0; l < _NbFans; ++l)
+00505                         {
+00506                                 *ptIndex++ = currVertFan;
+00507                                 *ptIndex++ = currVertFan + (l + 1);
+00508                                 *ptIndex++ = currVertFan + (l + 2);
+00509                         }                                       
+00510                         currVertFan += 2 + _NbFans;
+00511                 }
+00512                         
+00513                 for (k = 0; k < size; ++k)
+00514                 {                       
+00515                         if (_Tex)
+00516                         {
+00517                                 vb.setTexCoord(k * (_NbFans + 2), 0, NLMISC::CUV(0, 0));
+00518                         }
+00519                         if (!_ColorScheme)
+00520                         {
+00521                                 vb.setColor(k * (_NbFans + 2), CRGBA::White);                   
+00522                         }               
+00523                         if (!_Tex)
+00524                         {
+00525                                 for(l = 1; l <= _NbFans + 1; ++l)
+00526                                 {
+00527                                         vb.setColor(l + k * (_NbFans + 2), CRGBA(0, 0, 0));
+00528                                 }
+00529                         }
+00530                         else
+00531                         {
+00532                                 for(l = 1; l <= _NbFans + 1; ++l)
+00533                                 {
+00534                                         vb.setColor(l + k * (_NbFans + 2), CRGBA(0, 0, 0));
+00535                                         vb.setTexCoord(l + k * (_NbFans + 2), 0, NLMISC::CUV((l - 1) / (float) _NbFans, 1));
+00536                                 }
+00537                         }
+00538                 }
+00539                 
+00540                 retVb = &vb;
+00541                 retIb = &ib;
+00542         }       
+00543 }
+00544 
+00546 uint CPSFanLight::getNumFanlightsInVB() const
+00547 {
+00548         const uint numRib = NumVertsInBuffer / (2 + _NbFans);
+00549         return std::max(1u, numRib);
+00550 }
+00551 
+00552 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1