00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/particle_system.h"
00029 #include "3d/particle_system_shape.h"
00030 #include "3d/particle_system_model.h"
00031 #include "3d/scene.h"
00032 #include "3d/driver.h"
00033 #include "nel/misc/file.h"
00034 #include "nel/misc/mem_stream.h"
00035
00036
00037
00038 namespace NL3D {
00039
00040 using NLMISC::IStream;
00041 using NLMISC::CIFile;
00042
00043
00044
00045
00046
00047 #if defined(NL_DEBUG) && defined(NL_OS_WINDOWS)
00048 #include <crtdbg.h>
00049
00050 #define PARTICLES_CHECK_MEM
00051 #else
00052 #define PARTICLES_CHECK_MEM
00053 #endif
00054
00056 CParticleSystemShape::CParticleSystemShape() : _MaxViewDist(100.f),
00057 _DestroyWhenOutOfFrustum(false),
00058 _DestroyModelWhenOutOfRange(false),
00059 _UsePrecomputedBBox(false),
00060 _Sharing(false)
00061 {
00062 for (uint k = 0; k < 4; ++k)
00063 {
00064 _UserParamDefaultTrack[k].setValue(0);
00065 }
00066 _DefaultPos.setValue(CVector::Null);
00067 _DefaultScale.setValue( CVector(1, 1, 1) );
00068 _DefaultRotQuat.setValue(CQuat());
00069 _DefaultTriggerTrack.setValue(true);
00070
00071 }
00072
00074 void CParticleSystemShape::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00075 {
00076 sint ver = f.serialVersion(6);
00078 NLMISC::CVector8 &buf = _ParticleSystemProto.bufferAsVector();
00079 f.serialCont(buf);
00080 if (ver > 1)
00081 {
00082
00083 for (uint k = 0; k < 4; ++k)
00084 {
00085 f.serial(_UserParamDefaultTrack[k]);
00086 }
00087 }
00088 if ( ver > 2)
00089 {
00090 f.serial (_DefaultPos);
00091 f.serial (_DefaultScale);
00092 f.serial (_DefaultRotQuat);
00093 }
00094 if ( ver > 3)
00095 {
00096 f.serial(_MaxViewDist);
00097 f.serial(_DestroyWhenOutOfFrustum);
00098 f.serial(_DestroyModelWhenOutOfRange);
00099 }
00100 if ( ver > 4)
00101 {
00102 f.serial(_UsePrecomputedBBox);
00103 if (_UsePrecomputedBBox)
00104 {
00105 f.serial(_PrecomputedBBox);
00106 }
00107 }
00108 if ( ver > 5)
00109 {
00110 f.serial(_Sharing);
00111 }
00112 }
00113
00115 void CParticleSystemShape::buildFromPS(const CParticleSystem &ps)
00116 {
00117
00118 if (_ParticleSystemProto.isReading())
00119 {
00120 _ParticleSystemProto.invert();
00121 }
00122
00123
00124 CParticleSystem *myPs = const_cast<CParticleSystem *>(&ps);
00125 nlassert(myPs);
00126
00127 _ParticleSystemProto.serialPtr(myPs);
00128
00129
00130 _MaxViewDist = myPs->getMaxViewDist();
00131 _DestroyWhenOutOfFrustum = myPs->doesDestroyWhenOutOfFrustum();
00132 _DestroyModelWhenOutOfRange = myPs->getDestroyModelWhenOutOfRange();
00133 if (!myPs->getAutoComputeBBox())
00134 {
00135 _UsePrecomputedBBox = true;
00136 myPs->computeBBox(_PrecomputedBBox);
00137 }
00138 else
00139 {
00140 _UsePrecomputedBBox = false;
00141 }
00142 _Sharing = myPs->isSharingEnabled();
00143 }
00144
00146 void CParticleSystemShape::getAABBox(NLMISC::CAABBox &bbox) const
00147 {
00148 if (!_UsePrecomputedBBox)
00149 {
00150 bbox.setCenter(NLMISC::CVector::Null);
00151 bbox.setHalfSize(NLMISC::CVector(1, 1, 1));
00152 }
00153 else
00154 {
00155 bbox = _PrecomputedBBox;
00156 }
00157 }
00158
00160 CParticleSystem *CParticleSystemShape::instanciatePS(CScene &scene)
00161 {
00162 if (_Sharing && _SharedSystem != NULL)
00163 {
00164 return _SharedSystem;
00165 }
00166
00167
00168 CParticleSystem *myInstance = NULL;
00169
00170
00171 if (!_ParticleSystemProto.isReading())
00172 {
00173 _ParticleSystemProto.invert();
00174 }
00175
00176 _ParticleSystemProto.resetPtrTable();
00177 _ParticleSystemProto.seek(0, IStream::begin);
00178 _ParticleSystemProto.serialPtr(myInstance);
00179
00180
00181 myInstance->setScene(&scene);
00182
00183 if (_Sharing)
00184 {
00185 _SharedSystem = myInstance;
00186 }
00187
00188 return myInstance;
00189 }
00190
00192 CTransformShape *CParticleSystemShape::createInstance(CScene &scene)
00193 {
00194 CParticleSystemModel *psm = NLMISC::safe_cast<CParticleSystemModel *>(scene.createModel(NL3D::ParticleSystemModelId) );
00195 psm->Shape = this;
00196 psm->_Scene = &scene;
00197
00198
00199
00200
00201 psm->ITransformable::setPos( ((CAnimatedValueVector&)_DefaultPos.getValue()).Value );
00202 psm->ITransformable::setRotQuat( ((CAnimatedValueQuat&)_DefaultRotQuat.getValue()).Value );
00203 psm->ITransformable::setScale( ((CAnimatedValueVector&)_DefaultScale.getValue()).Value );
00204
00205
00206 psm->setLoadBalancingGroup("Global");
00207
00208 return psm;
00209 }
00210
00212 void CParticleSystemShape::render(IDriver *drv, CTransformShape *trans, bool passOpaque)
00213 {
00214 nlassert(dynamic_cast<CParticleSystemModel *>(trans));
00215 nlassert(drv);
00216 CParticleSystemModel *psm = (CParticleSystemModel *) trans;
00217 if (psm->_Invalidated) return;
00218 CParticleSystem *ps = psm->getPS();
00220 if (!ps) return;
00221
00222 TAnimationTime delay = psm->getEllapsedTime();
00223 nlassert(ps->getScene());
00224
00226
00228
00230
00231 {
00232 ps->setSysMat(trans->getWorldMatrix());
00233 }
00234
00235
00237
00238 ps->setDriver(drv);
00239
00240 PARTICLES_CHECK_MEM;
00241 if (passOpaque)
00242 {
00243 ps->step(CParticleSystem::SolidRender, delay);
00244 }
00245 else
00246 {
00247 ps->step(CParticleSystem::BlendRender, delay);
00248 }
00249 PARTICLES_CHECK_MEM;
00250 if (psm->isToolDisplayEnabled())
00251 {
00252 ps->step(CParticleSystem::ToolRender, delay);
00253 PARTICLES_CHECK_MEM;
00254 }
00255 }
00256
00257 }