ps_light.cpp

Go to the documentation of this file.
00001 
00004 /* Copyright, 2000, 2001, 2002, 2003 Nevrax Ltd.
00005  *
00006  * This file is part of NEVRAX NEL.
00007  * NEVRAX NEL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2, or (at your option)
00010  * any later version.
00011 
00012  * NEVRAX NEL is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015  * General Public License for more details.
00016 
00017  * You should have received a copy of the GNU General Public License
00018  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00019  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00020  * MA 02111-1307, USA.
00021  */
00022 
00023 
00024 #include "std3d.h"
00025 #include "nel/3d/ps_light.h"
00026 #include "nel/3d/point_light_model.h"
00027 #include "nel/3d/scene.h"
00028 #include "nel/3d/particle_system.h"
00029 #include "nel/3d/particle_system_model.h"
00030 #include "nel/3d/ps_util.h"
00031 #include "nel/misc/matrix.h"
00032 #include "nel/misc/vector.h"
00033 
00034 namespace NL3D
00035 {
00036 
00037 
00038 //***************************************************************************************************************
00039 CPSLight::CPSLight() : _Color(CRGBA::White),
00040                        _ColorScheme(NULL),
00041                        _AttenStart(0.1f),
00042                        _AttenStartScheme(NULL),
00043                        _AttenEnd(1.f),
00044                        _AttenEndScheme(NULL)
00045 {
00046     NL_PS_FUNC(CPSLight_CPSLight)
00047 }
00048 
00049 //***************************************************************************************************************
00050 CPSLight::~CPSLight()
00051 {
00052     NL_PS_FUNC(CPSLight_CPSLight)
00053     if (_Owner && _Owner->getOwner())
00054     {
00055         // check that all lights have been deleted
00056         for(uint k = 0; k < _Lights.getSize(); ++k)
00057         {
00058             if (_Lights[k]) _Owner->getOwner()->getScene()->deleteModel(_Lights[k]);
00059         }
00060     }
00061     else
00062     {
00063         #ifdef NL_DEBUG
00064             // check that all lights have been deleted
00065             for(uint k = 0; k < _Lights.getSize(); ++k)
00066             {
00067                 nlassert(_Lights[k] == NULL); // error there's  leak!
00068             }
00069         #endif
00070     }
00071     delete _ColorScheme;
00072     delete _AttenStartScheme;
00073     delete _AttenEndScheme;
00074 }
00075 
00076 //***************************************************************************************************************
00077 void CPSLight::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00078 {
00079     NL_PS_FUNC(CPSLight_serial)
00080     CPSLocatedBindable::serial(f);
00081     // version 1 : in version 0, scheme where not resized correctly; Fixed in this version
00082     // version 0 : color, start attenuation radius, end attenuation radius.
00083     sint ver = f.serialVersion(1);
00084     // color
00085     bool hasColorScheme = _ColorScheme != NULL;
00086     f.serial(hasColorScheme);
00087     if (hasColorScheme)
00088     {
00089         f.serialPolyPtr(_ColorScheme);
00090     }
00091     else
00092     {
00093         f.serial(_Color);
00094     }
00095     // Atten start
00096     bool hasAttenStartScheme = _AttenStartScheme != NULL;
00097     f.serial(hasAttenStartScheme);
00098     if (hasAttenStartScheme)
00099     {
00100         f.serialPolyPtr(_AttenStartScheme);
00101     }
00102     else
00103     {
00104         f.serial(_AttenStart);
00105     }
00106     // Atten end
00107     bool hasAttenEndScheme = _AttenEndScheme != NULL;
00108     f.serial(hasAttenEndScheme);
00109     if (hasAttenEndScheme)
00110     {
00111         f.serialPolyPtr(_AttenEndScheme);
00112     }
00113     else
00114     {
00115         f.serial(_AttenEnd);
00116     }
00117 
00118     // save # of lights
00119     if (ver == 0)
00120     {
00121         uint32 dummyNumLights; // from old buggy version
00122         f.serial(dummyNumLights);
00123     }
00124     if (f.isReading())
00125     {
00126         if (_Owner)
00127         {
00128             resize(_Owner->getMaxSize());
00129             for(uint k = 0; k < _Owner->getSize(); ++k)
00130             {
00131                 CPSEmitterInfo ei;
00132                 ei.setDefaults();
00133                 newElement(ei);
00134             }
00135         }
00136         else
00137         {
00138             resize(0);
00139         }
00140     }
00141 }
00142 
00143 //***************************************************************************************************************
00144 uint32 CPSLight::getType(void) const
00145 {
00146     NL_PS_FUNC(CPSLight_getType)
00147     return PSLight;
00148 }
00149 
00150 //***************************************************************************************************************
00151 void CPSLight::onShow(bool shown)
00152 {
00153     for(uint k = 0; k < _Lights.getSize(); ++k)
00154     {
00155         if (_Lights[k])
00156         {
00157             if (shown)
00158             {
00159                 _Lights[k]->show();
00160             }
00161             else
00162             {
00163                 _Lights[k]->hide();
00164             }
00165         }
00166     }
00167 }
00168 
00169 //***************************************************************************************************************
00170 void CPSLight::step(TPSProcessPass pass)
00171 {
00172     NL_PS_FUNC(CPSLight_step)
00173     if (pass != PSMotion)
00174     {
00175         if (pass == PSToolRender)
00176         {
00177             show();
00178         }
00179         return;
00180     }
00181     nlassert(_Owner);
00182     nlassert(_Owner->getOwner());
00183     CScene *scene = _Owner->getOwner()->getScene();
00184     const uint32 BATCH_SIZE = 512;
00185     uint32 numLeftLights = _Lights.getSize();
00186     // avoid ctor call for color array
00187     uint8          colorArray[BATCH_SIZE * sizeof(NLMISC::CRGBA)];
00188     NLMISC::CRGBA *colors = (NLMISC::CRGBA *) colorArray;
00189     float         attenStart[BATCH_SIZE];
00190     float         attenEnd[BATCH_SIZE];
00191     CPSAttrib<CPointLightModel *>::iterator lightIt = _Lights.begin();
00192     const CMatrix *convMat = &(getLocalToWorldMatrix());
00193     TPSAttribVector::const_iterator posIt = _Owner->getPos().begin();
00194     CRGBA globalColor = _Owner->getOwner()->getGlobalColor();
00195     while (numLeftLights)
00196     {
00197         uint32 toProcess = std::min(numLeftLights, BATCH_SIZE);
00198         // compute colors
00199         NLMISC::CRGBA *colPointer;
00200         uint   colStride;
00201         if (_ColorScheme)
00202         {
00203             colPointer = (CRGBA *) _ColorScheme->make(_Owner, _Lights.getSize() - numLeftLights, colors, sizeof(CRGBA), toProcess, true);
00204             colStride = 1;
00205         }
00206         else
00207         {
00208             colPointer = &_Color;
00209             colStride = 0;
00210         }
00211         // compute start attenuation
00212         float *attenStartPointer;
00213         uint   attenStartStride;
00214         if (_AttenStartScheme)
00215         {
00216             attenStartPointer = (float *) _AttenStartScheme->make(_Owner, _Lights.getSize() - numLeftLights, attenStart, sizeof(float), toProcess, true);
00217             attenStartStride = 1;
00218         }
00219         else
00220         {
00221             attenStartPointer = &_AttenStart;
00222             attenStartStride = 0;
00223         }
00224         // compute end attenuation
00225         float *attenEndPointer;
00226         uint   attenEndStride;
00227         if (_AttenEndScheme)
00228         {
00229             attenEndPointer = (float *) _AttenEndScheme->make(_Owner, _Lights.getSize() - numLeftLights, attenEnd, sizeof(float), toProcess, true);
00230             attenEndStride = 1;
00231         }
00232         else
00233         {
00234             attenEndPointer = &_AttenEnd;
00235             attenEndStride = 0;
00236         }
00237         numLeftLights -= toProcess;
00238         do
00239         {
00240             if (!*lightIt)
00241             {
00242                 // light not created, create it from scene
00243                 if (scene)
00244                 {
00245                     *lightIt = NLMISC::safe_cast<CPointLightModel *>(scene->createModel(PointLightModelId));
00246                     if (*lightIt)
00247                     {
00248                         (*lightIt)->setTransformMode(CTransform::RotEuler);
00249                     }
00250                 }
00251             }
00252             if (*lightIt)
00253             {
00254                 NLMISC::CVector pos = *convMat * *posIt;
00255                 CPointLightModel *plm = *lightIt;
00256                 if (pos != plm->getPos()) plm->setPos(pos);
00257 
00258 
00259                 if (CParticleSystem::OwnerModel)
00260                 {
00261                     // make sure the visibility is the same
00262                     if (CParticleSystem::OwnerModel->isHrcVisible())
00263                     {
00264                         plm->show();
00265                     }
00266                     else
00267                     {
00268                         plm->hide();
00269                     }
00270                     plm->setClusterSystem(CParticleSystem::OwnerModel->getClusterSystem());
00271                 }
00272 
00273                 CRGBA newCol = *colPointer;
00274                 newCol.modulateFromColor(newCol, globalColor);
00275                 if (newCol != plm->PointLight.getDiffuse())
00276                 {
00277                     plm->PointLight.setColor(newCol);
00278                 }
00279                 colPointer += colStride;
00280                 if (*attenStartPointer != plm->PointLight.getAttenuationBegin()
00281                     || *attenEndPointer != plm->PointLight.getAttenuationEnd()
00282                    )
00283                 {
00284                     plm->PointLight.setupAttenuation(*attenStartPointer, *attenEndPointer);
00285                 }
00286                 attenStartPointer += attenStartStride;
00287                 attenEndPointer += attenEndStride;
00288             }
00289             ++ lightIt;
00290             ++ posIt;
00291         }
00292         while(--toProcess);
00293     }
00294 }
00295 
00296 //***************************************************************************************************************
00297 void CPSLight::setColor(NLMISC::CRGBA color)
00298 {
00299     NL_PS_FUNC(CPSLight_setColor)
00300     delete _ColorScheme;
00301     _ColorScheme = NULL;
00302     _Color = color;
00303 }
00304 
00305 //***************************************************************************************************************
00306 void CPSLight::setColorScheme(CPSAttribMaker<NLMISC::CRGBA> *scheme)
00307 {
00308     NL_PS_FUNC(CPSLight_setColorScheme)
00309     delete _ColorScheme;
00310     _ColorScheme = scheme;
00311     if (_Owner)
00312     {
00313         if (_ColorScheme && _ColorScheme->hasMemory()) _ColorScheme->resize(_Owner->getMaxSize(), _Owner->getSize());
00314     }
00315 }
00316 
00317 //***************************************************************************************************************
00318 void CPSLight::setAttenStart(float radius)
00319 {
00320     NL_PS_FUNC(CPSLight_setAttenStart)
00321     nlassert(radius > 0.f);
00322     delete _AttenStartScheme;
00323     _AttenStartScheme = NULL;
00324     _AttenStart = radius;
00325 }
00326 
00327 //***************************************************************************************************************
00328 void CPSLight::setAttenStartScheme(CPSAttribMaker<float> *scheme)
00329 {
00330     NL_PS_FUNC(CPSLight_setAttenStartScheme)
00331     delete _AttenStartScheme;
00332     _AttenStartScheme = scheme;
00333     if (_Owner)
00334     {
00335         if (_AttenStartScheme && _AttenStartScheme->hasMemory()) _AttenStartScheme->resize(_Owner->getMaxSize(), _Owner->getSize());
00336     }
00337 }
00338 
00339 //***************************************************************************************************************
00340 void CPSLight::setAttenEnd(float radius)
00341 {
00342     NL_PS_FUNC(CPSLight_setAttenEnd)
00343     delete _AttenEndScheme;
00344     _AttenEndScheme = NULL;
00345     _AttenEnd = radius;
00346 }
00347 
00348 //***************************************************************************************************************
00349 void CPSLight::setAttenEndScheme(CPSAttribMaker<float> *scheme)
00350 {
00351     NL_PS_FUNC(CPSLight_setAttenEndScheme)
00352     delete _AttenEndScheme;
00353     _AttenEndScheme = scheme;
00354     if (_Owner)
00355     {
00356         if (_AttenEndScheme && _AttenEndScheme->hasMemory()) _AttenEndScheme->resize(_Owner->getMaxSize(), _Owner->getSize());
00357     }
00358 }
00359 
00360 //***************************************************************************************************************
00361 void CPSLight::newElement(const CPSEmitterInfo &info)
00362 {
00363     NL_PS_FUNC(CPSLight_newElement)
00364     if (_ColorScheme && _ColorScheme->hasMemory()) _ColorScheme->newElement(info);
00365     if (_AttenStartScheme && _AttenStartScheme->hasMemory()) _AttenStartScheme->newElement(info);
00366     if (_AttenEndScheme && _AttenEndScheme->hasMemory()) _AttenEndScheme->newElement(info);
00367     _Lights.insert(NULL); // instance is created during step()
00368 }
00369 
00370 //***************************************************************************************************************
00371 void CPSLight::deleteElement(uint32 index)
00372 {
00373     NL_PS_FUNC(CPSLight_deleteElement)
00374     if (_ColorScheme && _ColorScheme->hasMemory()) _ColorScheme->deleteElement(index);
00375     if (_AttenStartScheme && _AttenStartScheme->hasMemory()) _AttenStartScheme->deleteElement(index);
00376     if (_AttenEndScheme && _AttenEndScheme->hasMemory()) _AttenEndScheme->deleteElement(index);
00377     if (_Lights[index])
00378     {
00379         nlassert(_Owner && _Owner->getScene());
00380         _Owner->getScene()->deleteModel(_Lights[index]);
00381     }
00382     _Lights.remove(index);
00383 }
00384 
00385 //***************************************************************************************************************
00386 void CPSLight::resize(uint32 size)
00387 {
00388     NL_PS_FUNC(CPSLight_resize)
00389     nlassert(size < (1 << 16));
00390     if (_ColorScheme && _ColorScheme->hasMemory()) _ColorScheme->resize(size, getOwner() ? getOwner()->getSize() : 0);
00391     if (_AttenStartScheme && _AttenStartScheme->hasMemory()) _AttenStartScheme->resize(size, getOwner() ? getOwner()->getSize() : 0);
00392     if (_AttenEndScheme && _AttenEndScheme->hasMemory()) _AttenEndScheme->resize(size, getOwner() ? getOwner()->getSize() : 0);
00393     _Lights.resize(size);
00394 }
00395 
00396 //***************************************************************************************************************
00397 void CPSLight::releaseAllRef()
00398 {
00399     NL_PS_FUNC(CPSLight_releaseAllRef)
00400     CPSLocatedBindable::releaseAllRef();
00401     // delete all lights, because pointer to the scene is lost after detaching from a system.
00402     for(uint k = 0; k < _Lights.getSize(); ++k)
00403     {
00404         if (_Lights[k])
00405         {
00406             nlassert(_Owner && _Owner->getScene()); // if there's an instance there must be a scene from which it was created.
00407             _Owner->getScene()->deleteModel(_Lights[k]);
00408             _Lights[k] = NULL;
00409         }
00410     }
00411 }
00412 
00413 //***************************************************************************************************************
00414 void CPSLight::show()
00415 {
00416     NL_PS_FUNC(CPSLight_show)
00417     uint32 index;
00418     CPSLocated *loc;
00419     CPSLocatedBindable *lb;
00420     _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
00421 
00422     NLMISC::CMatrix xzMat;
00423     xzMat.setRot(CVector::I, CVector::K, CVector::Null);
00424     NLMISC::CMatrix xyMat;
00425     xyMat.setRot(CVector::I, CVector::J, CVector::Null);
00426     NLMISC::CMatrix yzMat;
00427     yzMat.setRot(CVector::J, CVector::K, CVector::Null);
00428 
00429 
00430     getDriver()->setupModelMatrix(NLMISC::CMatrix::Identity);
00431     const uint numSubdiv = 32;
00432     // for each element, see if it is the selected element, and if yes, display in red
00433     for (uint k = 0; k < _Lights.getSize(); ++k)
00434     {
00435         float radiusStart = _AttenStartScheme ? _AttenStartScheme->get(_Owner, k) : _AttenStart;
00436         float radiusEnd = _AttenEndScheme ? _AttenEndScheme->get(_Owner, k) : _AttenEnd;
00437         NLMISC::clamp(radiusStart, 0.f, radiusEnd);
00438         const NLMISC::CRGBA colStart = (((lb == NULL || this == lb) && loc == _Owner && index == k)  ? CRGBA::Blue : CRGBA(0, 0, 127));
00439         const NLMISC::CRGBA colEnd = (((lb == NULL || this == lb) && loc == _Owner && index == k)  ? CRGBA::Red : CRGBA(127, 0, 0));
00440         //
00441         CPSUtil::displayDisc(*getDriver(), radiusStart, getLocalToWorldMatrix() * _Owner->getPos()[k], xzMat, numSubdiv, colStart);
00442         CPSUtil::displayDisc(*getDriver(), radiusStart, getLocalToWorldMatrix() * _Owner->getPos()[k], xyMat, numSubdiv, colStart);
00443         CPSUtil::displayDisc(*getDriver(), radiusStart, getLocalToWorldMatrix() * _Owner->getPos()[k], yzMat, numSubdiv, colStart);
00444         //
00445         CPSUtil::displayDisc(*getDriver(), radiusEnd, getLocalToWorldMatrix() * _Owner->getPos()[k], xzMat, numSubdiv, colEnd);
00446         CPSUtil::displayDisc(*getDriver(), radiusEnd, getLocalToWorldMatrix() * _Owner->getPos()[k], xyMat, numSubdiv, colEnd);
00447         CPSUtil::displayDisc(*getDriver(), radiusEnd, getLocalToWorldMatrix() * _Owner->getPos()[k], yzMat, numSubdiv, colEnd);
00448         //
00449     }
00450 }
00451 
00452 } // namespace NL3D

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