00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
00065 for(uint k = 0; k < _Lights.getSize(); ++k)
00066 {
00067 nlassert(_Lights[k] == NULL);
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
00082
00083 sint ver = f.serialVersion(1);
00084
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
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
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
00119 if (ver == 0)
00120 {
00121 uint32 dummyNumLights;
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
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
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
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
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
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
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);
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
00402 for(uint k = 0; k < _Lights.getSize(); ++k)
00403 {
00404 if (_Lights[k])
00405 {
00406 nlassert(_Owner && _Owner->getScene());
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
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 }