/Irrlicht/CParticleSystemSceneNode.cpp

http://myjeh.googlecode.com/ · C++ · 704 lines · 515 code · 138 blank · 51 comment · 52 complexity · 9b6cce29be2926e980a7c7cbed350579 MD5 · raw file

  1. // Copyright (C) 2002-2010 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #include "CParticleSystemSceneNode.h"
  5. #include "os.h"
  6. #include "ISceneManager.h"
  7. #include "ICameraSceneNode.h"
  8. #include "IVideoDriver.h"
  9. #include "CParticleAnimatedMeshSceneNodeEmitter.h"
  10. #include "CParticleBoxEmitter.h"
  11. #include "CParticleCylinderEmitter.h"
  12. #include "CParticleMeshEmitter.h"
  13. #include "CParticlePointEmitter.h"
  14. #include "CParticleRingEmitter.h"
  15. #include "CParticleSphereEmitter.h"
  16. #include "CParticleAttractionAffector.h"
  17. #include "CParticleFadeOutAffector.h"
  18. #include "CParticleGravityAffector.h"
  19. #include "CParticleRotationAffector.h"
  20. #include "CParticleScaleAffector.h"
  21. #include "SViewFrustum.h"
  22. namespace irr
  23. {
  24. namespace scene
  25. {
  26. //! constructor
  27. CParticleSystemSceneNode::CParticleSystemSceneNode(bool createDefaultEmitter,
  28. ISceneNode* parent, ISceneManager* mgr, s32 id,
  29. const core::vector3df& position, const core::vector3df& rotation,
  30. const core::vector3df& scale)
  31. : IParticleSystemSceneNode(parent, mgr, id, position, rotation, scale),
  32. Emitter(0), ParticleSize(core::dimension2d<f32>(5.0f, 5.0f)), LastEmitTime(0),
  33. MaxParticles(0xffff), Buffer(0), ParticlesAreGlobal(true)
  34. {
  35. #ifdef _DEBUG
  36. setDebugName("CParticleSystemSceneNode");
  37. #endif
  38. Buffer = new SMeshBuffer();
  39. if (createDefaultEmitter)
  40. {
  41. IParticleEmitter* e = createBoxEmitter();
  42. setEmitter(e);
  43. e->drop();
  44. }
  45. }
  46. //! destructor
  47. CParticleSystemSceneNode::~CParticleSystemSceneNode()
  48. {
  49. if (Emitter)
  50. Emitter->drop();
  51. if (Buffer)
  52. Buffer->drop();
  53. removeAllAffectors();
  54. }
  55. //! Gets the particle emitter, which creates the particles.
  56. IParticleEmitter* CParticleSystemSceneNode::getEmitter()
  57. {
  58. return Emitter;
  59. }
  60. //! Sets the particle emitter, which creates the particles.
  61. void CParticleSystemSceneNode::setEmitter(IParticleEmitter* emitter)
  62. {
  63. if (emitter == Emitter)
  64. return;
  65. if (Emitter)
  66. Emitter->drop();
  67. Emitter = emitter;
  68. if (Emitter)
  69. Emitter->grab();
  70. }
  71. //! Adds new particle effector to the particle system.
  72. void CParticleSystemSceneNode::addAffector(IParticleAffector* affector)
  73. {
  74. affector->grab();
  75. AffectorList.push_back(affector);
  76. }
  77. //! Removes all particle affectors in the particle system.
  78. void CParticleSystemSceneNode::removeAllAffectors()
  79. {
  80. core::list<IParticleAffector*>::Iterator it = AffectorList.begin();
  81. while (it != AffectorList.end())
  82. {
  83. (*it)->drop();
  84. it = AffectorList.erase(it);
  85. }
  86. }
  87. //! Returns the material based on the zero based index i.
  88. video::SMaterial& CParticleSystemSceneNode::getMaterial(u32 i)
  89. {
  90. return Buffer->Material;
  91. }
  92. //! Returns amount of materials used by this scene node.
  93. u32 CParticleSystemSceneNode::getMaterialCount() const
  94. {
  95. return 1;
  96. }
  97. //! Creates a particle emitter for an animated mesh scene node
  98. IParticleAnimatedMeshSceneNodeEmitter*
  99. CParticleSystemSceneNode::createAnimatedMeshSceneNodeEmitter(
  100. scene::IAnimatedMeshSceneNode* node, bool useNormalDirection,
  101. const core::vector3df& direction, f32 normalDirectionModifier,
  102. s32 mbNumber, bool everyMeshVertex,
  103. u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
  104. const video::SColor& minStartColor, const video::SColor& maxStartColor,
  105. u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
  106. const core::dimension2df& minStartSize,
  107. const core::dimension2df& maxStartSize )
  108. {
  109. return new CParticleAnimatedMeshSceneNodeEmitter( node,
  110. useNormalDirection, direction, normalDirectionModifier,
  111. mbNumber, everyMeshVertex,
  112. minParticlesPerSecond, maxParticlesPerSecond,
  113. minStartColor, maxStartColor,
  114. lifeTimeMin, lifeTimeMax, maxAngleDegrees,
  115. minStartSize, maxStartSize );
  116. }
  117. //! Creates a box particle emitter.
  118. IParticleBoxEmitter* CParticleSystemSceneNode::createBoxEmitter(
  119. const core::aabbox3df& box, const core::vector3df& direction,
  120. u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
  121. const video::SColor& minStartColor, const video::SColor& maxStartColor,
  122. u32 lifeTimeMin, u32 lifeTimeMax,
  123. s32 maxAngleDegrees, const core::dimension2df& minStartSize,
  124. const core::dimension2df& maxStartSize )
  125. {
  126. return new CParticleBoxEmitter(box, direction, minParticlesPerSecond,
  127. maxParticlesPerSecond, minStartColor, maxStartColor,
  128. lifeTimeMin, lifeTimeMax, maxAngleDegrees,
  129. minStartSize, maxStartSize );
  130. }
  131. //! Creates a particle emitter for emitting from a cylinder
  132. IParticleCylinderEmitter* CParticleSystemSceneNode::createCylinderEmitter(
  133. const core::vector3df& center, f32 radius,
  134. const core::vector3df& normal, f32 length,
  135. bool outlineOnly, const core::vector3df& direction,
  136. u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
  137. const video::SColor& minStartColor, const video::SColor& maxStartColor,
  138. u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
  139. const core::dimension2df& minStartSize,
  140. const core::dimension2df& maxStartSize )
  141. {
  142. return new CParticleCylinderEmitter( center, radius, normal, length,
  143. outlineOnly, direction,
  144. minParticlesPerSecond, maxParticlesPerSecond,
  145. minStartColor, maxStartColor,
  146. lifeTimeMin, lifeTimeMax, maxAngleDegrees,
  147. minStartSize, maxStartSize );
  148. }
  149. //! Creates a mesh particle emitter.
  150. IParticleMeshEmitter* CParticleSystemSceneNode::createMeshEmitter(
  151. scene::IMesh* mesh, bool useNormalDirection,
  152. const core::vector3df& direction, f32 normalDirectionModifier,
  153. s32 mbNumber, bool everyMeshVertex,
  154. u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
  155. const video::SColor& minStartColor, const video::SColor& maxStartColor,
  156. u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
  157. const core::dimension2df& minStartSize,
  158. const core::dimension2df& maxStartSize)
  159. {
  160. return new CParticleMeshEmitter( mesh, useNormalDirection, direction,
  161. normalDirectionModifier, mbNumber, everyMeshVertex,
  162. minParticlesPerSecond, maxParticlesPerSecond,
  163. minStartColor, maxStartColor,
  164. lifeTimeMin, lifeTimeMax, maxAngleDegrees,
  165. minStartSize, maxStartSize );
  166. }
  167. //! Creates a point particle emitter.
  168. IParticlePointEmitter* CParticleSystemSceneNode::createPointEmitter(
  169. const core::vector3df& direction, u32 minParticlesPerSecond,
  170. u32 maxParticlesPerSecond, const video::SColor& minStartColor,
  171. const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax,
  172. s32 maxAngleDegrees, const core::dimension2df& minStartSize,
  173. const core::dimension2df& maxStartSize )
  174. {
  175. return new CParticlePointEmitter(direction, minParticlesPerSecond,
  176. maxParticlesPerSecond, minStartColor, maxStartColor,
  177. lifeTimeMin, lifeTimeMax, maxAngleDegrees,
  178. minStartSize, maxStartSize );
  179. }
  180. //! Creates a ring particle emitter.
  181. IParticleRingEmitter* CParticleSystemSceneNode::createRingEmitter(
  182. const core::vector3df& center, f32 radius, f32 ringThickness,
  183. const core::vector3df& direction,
  184. u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
  185. const video::SColor& minStartColor, const video::SColor& maxStartColor,
  186. u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
  187. const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize )
  188. {
  189. return new CParticleRingEmitter( center, radius, ringThickness, direction,
  190. minParticlesPerSecond, maxParticlesPerSecond, minStartColor,
  191. maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees,
  192. minStartSize, maxStartSize );
  193. }
  194. //! Creates a sphere particle emitter.
  195. IParticleSphereEmitter* CParticleSystemSceneNode::createSphereEmitter(
  196. const core::vector3df& center, f32 radius, const core::vector3df& direction,
  197. u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
  198. const video::SColor& minStartColor, const video::SColor& maxStartColor,
  199. u32 lifeTimeMin, u32 lifeTimeMax,
  200. s32 maxAngleDegrees, const core::dimension2df& minStartSize,
  201. const core::dimension2df& maxStartSize )
  202. {
  203. return new CParticleSphereEmitter(center, radius, direction,
  204. minParticlesPerSecond, maxParticlesPerSecond,
  205. minStartColor, maxStartColor,
  206. lifeTimeMin, lifeTimeMax, maxAngleDegrees,
  207. minStartSize, maxStartSize );
  208. }
  209. //! Creates a point attraction affector. This affector modifies the positions of the
  210. //! particles and attracts them to a specified point at a specified speed per second.
  211. IParticleAttractionAffector* CParticleSystemSceneNode::createAttractionAffector(
  212. const core::vector3df& point, f32 speed, bool attract,
  213. bool affectX, bool affectY, bool affectZ )
  214. {
  215. return new CParticleAttractionAffector( point, speed, attract, affectX, affectY, affectZ );
  216. }
  217. //! Creates a scale particle affector.
  218. IParticleAffector* CParticleSystemSceneNode::createScaleParticleAffector(const core::dimension2df& scaleTo)
  219. {
  220. return new CParticleScaleAffector(scaleTo);
  221. }
  222. //! Creates a fade out particle affector.
  223. IParticleFadeOutAffector* CParticleSystemSceneNode::createFadeOutParticleAffector(
  224. const video::SColor& targetColor, u32 timeNeededToFadeOut)
  225. {
  226. return new CParticleFadeOutAffector(targetColor, timeNeededToFadeOut);
  227. }
  228. //! Creates a gravity affector.
  229. IParticleGravityAffector* CParticleSystemSceneNode::createGravityAffector(
  230. const core::vector3df& gravity, u32 timeForceLost)
  231. {
  232. return new CParticleGravityAffector(gravity, timeForceLost);
  233. }
  234. //! Creates a rotation affector. This affector rotates the particles around a specified pivot
  235. //! point. The speed represents Degrees of rotation per second.
  236. IParticleRotationAffector* CParticleSystemSceneNode::createRotationAffector(
  237. const core::vector3df& speed, const core::vector3df& pivotPoint )
  238. {
  239. return new CParticleRotationAffector( speed, pivotPoint );
  240. }
  241. //! pre render event
  242. void CParticleSystemSceneNode::OnRegisterSceneNode()
  243. {
  244. doParticleSystem(os::Timer::getTime());
  245. if (IsVisible && (Particles.size() != 0))
  246. {
  247. SceneManager->registerNodeForRendering(this);
  248. ISceneNode::OnRegisterSceneNode();
  249. }
  250. }
  251. //! render
  252. void CParticleSystemSceneNode::render()
  253. {
  254. video::IVideoDriver* driver = SceneManager->getVideoDriver();
  255. ICameraSceneNode* camera = SceneManager->getActiveCamera();
  256. if (!camera || !driver)
  257. return;
  258. #if 0
  259. // calculate vectors for letting particles look to camera
  260. core::vector3df view(camera->getTarget() - camera->getAbsolutePosition());
  261. view.normalize();
  262. view *= -1.0f;
  263. #else
  264. const core::matrix4 &m = camera->getViewFrustum()->getTransform( video::ETS_VIEW );
  265. const core::vector3df view ( -m[2], -m[6] , -m[10] );
  266. #endif
  267. // reallocate arrays, if they are too small
  268. reallocateBuffers();
  269. // create particle vertex data
  270. s32 idx = 0;
  271. for (u32 i=0; i<Particles.size(); ++i)
  272. {
  273. const SParticle& particle = Particles[i];
  274. #if 0
  275. core::vector3df horizontal = camera->getUpVector().crossProduct(view);
  276. horizontal.normalize();
  277. horizontal *= 0.5f * particle.size.Width;
  278. core::vector3df vertical = horizontal.crossProduct(view);
  279. vertical.normalize();
  280. vertical *= 0.5f * particle.size.Height;
  281. #else
  282. f32 f;
  283. f = 0.5f * particle.size.Width;
  284. const core::vector3df horizontal ( m[0] * f, m[4] * f, m[8] * f );
  285. f = -0.5f * particle.size.Height;
  286. const core::vector3df vertical ( m[1] * f, m[5] * f, m[9] * f );
  287. #endif
  288. Buffer->Vertices[0+idx].Pos = particle.pos + horizontal + vertical;
  289. Buffer->Vertices[0+idx].Color = particle.color;
  290. Buffer->Vertices[0+idx].Normal = view;
  291. Buffer->Vertices[1+idx].Pos = particle.pos + horizontal - vertical;
  292. Buffer->Vertices[1+idx].Color = particle.color;
  293. Buffer->Vertices[1+idx].Normal = view;
  294. Buffer->Vertices[2+idx].Pos = particle.pos - horizontal - vertical;
  295. Buffer->Vertices[2+idx].Color = particle.color;
  296. Buffer->Vertices[2+idx].Normal = view;
  297. Buffer->Vertices[3+idx].Pos = particle.pos - horizontal + vertical;
  298. Buffer->Vertices[3+idx].Color = particle.color;
  299. Buffer->Vertices[3+idx].Normal = view;
  300. idx +=4;
  301. }
  302. // render all
  303. core::matrix4 mat;
  304. if (!ParticlesAreGlobal)
  305. mat.setTranslation(AbsoluteTransformation.getTranslation());
  306. driver->setTransform(video::ETS_WORLD, mat);
  307. driver->setMaterial(Buffer->Material);
  308. driver->drawVertexPrimitiveList(Buffer->getVertices(), Particles.size()*4,
  309. Buffer->getIndices(), Particles.size()*2, video::EVT_STANDARD, EPT_TRIANGLES,Buffer->getIndexType());
  310. // for debug purposes only:
  311. if ( DebugDataVisible & scene::EDS_BBOX )
  312. {
  313. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  314. video::SMaterial deb_m;
  315. deb_m.Lighting = false;
  316. driver->setMaterial(deb_m);
  317. driver->draw3DBox(Buffer->BoundingBox, video::SColor(0,255,255,255));
  318. }
  319. }
  320. //! returns the axis aligned bounding box of this node
  321. const core::aabbox3d<f32>& CParticleSystemSceneNode::getBoundingBox() const
  322. {
  323. return Buffer->getBoundingBox();
  324. }
  325. void CParticleSystemSceneNode::doParticleSystem(u32 time)
  326. {
  327. if (LastEmitTime==0)
  328. {
  329. LastEmitTime = time;
  330. return;
  331. }
  332. u32 now = time;
  333. u32 timediff = time - LastEmitTime;
  334. LastEmitTime = time;
  335. // run emitter
  336. if (Emitter && IsVisible)
  337. {
  338. SParticle* array = 0;
  339. s32 newParticles = Emitter->emitt(now, timediff, array);
  340. if (newParticles && array)
  341. {
  342. s32 j=Particles.size();
  343. if (newParticles > 16250-j)
  344. newParticles=16250-j;
  345. Particles.set_used(j+newParticles);
  346. for (s32 i=j; i<j+newParticles; ++i)
  347. {
  348. Particles[i]=array[i-j];
  349. AbsoluteTransformation.rotateVect(Particles[i].startVector);
  350. if (ParticlesAreGlobal)
  351. AbsoluteTransformation.transformVect(Particles[i].pos);
  352. }
  353. }
  354. }
  355. // run affectors
  356. core::list<IParticleAffector*>::Iterator ait = AffectorList.begin();
  357. for (; ait != AffectorList.end(); ++ait)
  358. (*ait)->affect(now, Particles.pointer(), Particles.size());
  359. if (ParticlesAreGlobal)
  360. Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation());
  361. else
  362. Buffer->BoundingBox.reset(core::vector3df(0,0,0));
  363. // animate all particles
  364. f32 scale = (f32)timediff;
  365. for (u32 i=0; i<Particles.size();)
  366. {
  367. // erase is pretty expensive!
  368. if (now > Particles[i].endTime)
  369. Particles.erase(i);
  370. else
  371. {
  372. Particles[i].pos += (Particles[i].vector * scale);
  373. Buffer->BoundingBox.addInternalPoint(Particles[i].pos);
  374. ++i;
  375. }
  376. }
  377. const f32 m = (ParticleSize.Width > ParticleSize.Height ? ParticleSize.Width : ParticleSize.Height) * 0.5f;
  378. Buffer->BoundingBox.MaxEdge.X += m;
  379. Buffer->BoundingBox.MaxEdge.Y += m;
  380. Buffer->BoundingBox.MaxEdge.Z += m;
  381. Buffer->BoundingBox.MinEdge.X -= m;
  382. Buffer->BoundingBox.MinEdge.Y -= m;
  383. Buffer->BoundingBox.MinEdge.Z -= m;
  384. if (ParticlesAreGlobal)
  385. {
  386. core::matrix4 absinv( AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE );
  387. absinv.transformBoxEx(Buffer->BoundingBox);
  388. }
  389. }
  390. //! Sets if the particles should be global. If it is, the particles are affected by
  391. //! the movement of the particle system scene node too, otherwise they completely
  392. //! ignore it. Default is true.
  393. void CParticleSystemSceneNode::setParticlesAreGlobal(bool global)
  394. {
  395. ParticlesAreGlobal = global;
  396. }
  397. //! Sets the size of all particles.
  398. void CParticleSystemSceneNode::setParticleSize(const core::dimension2d<f32> &size)
  399. {
  400. os::Printer::log("setParticleSize is deprecated, use setMinStartSize/setMaxStartSize in emitter.", irr::ELL_WARNING);
  401. //A bit of a hack, but better here than in the particle code
  402. if (Emitter)
  403. {
  404. Emitter->setMinStartSize(size);
  405. Emitter->setMaxStartSize(size);
  406. }
  407. ParticleSize = size;
  408. }
  409. void CParticleSystemSceneNode::reallocateBuffers()
  410. {
  411. if (Particles.size() * 4 > Buffer->getVertexCount() ||
  412. Particles.size() * 6 > Buffer->getIndexCount())
  413. {
  414. u32 oldSize = Buffer->getVertexCount();
  415. Buffer->Vertices.set_used(Particles.size() * 4);
  416. u32 i;
  417. // fill remaining vertices
  418. for (i=oldSize; i<Buffer->Vertices.size(); i+=4)
  419. {
  420. Buffer->Vertices[0+i].TCoords.set(0.0f, 0.0f);
  421. Buffer->Vertices[1+i].TCoords.set(0.0f, 1.0f);
  422. Buffer->Vertices[2+i].TCoords.set(1.0f, 1.0f);
  423. Buffer->Vertices[3+i].TCoords.set(1.0f, 0.0f);
  424. }
  425. // fill remaining indices
  426. u32 oldIdxSize = Buffer->getIndexCount();
  427. u32 oldvertices = oldSize;
  428. Buffer->Indices.set_used(Particles.size() * 6);
  429. for (i=oldIdxSize; i<Buffer->Indices.size(); i+=6)
  430. {
  431. Buffer->Indices[0+i] = (u16)0+oldvertices;
  432. Buffer->Indices[1+i] = (u16)2+oldvertices;
  433. Buffer->Indices[2+i] = (u16)1+oldvertices;
  434. Buffer->Indices[3+i] = (u16)0+oldvertices;
  435. Buffer->Indices[4+i] = (u16)3+oldvertices;
  436. Buffer->Indices[5+i] = (u16)2+oldvertices;
  437. oldvertices += 4;
  438. }
  439. }
  440. }
  441. //! Writes attributes of the scene node.
  442. void CParticleSystemSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
  443. {
  444. IParticleSystemSceneNode::serializeAttributes(out, options);
  445. out->addBool("GlobalParticles", ParticlesAreGlobal);
  446. out->addFloat("ParticleWidth", ParticleSize.Width);
  447. out->addFloat("ParticleHeight", ParticleSize.Height);
  448. // write emitter
  449. E_PARTICLE_EMITTER_TYPE type = EPET_COUNT;
  450. if (Emitter)
  451. type = Emitter->getType();
  452. out->addEnum("Emitter", (s32)type, ParticleEmitterTypeNames);
  453. if (Emitter)
  454. Emitter->serializeAttributes(out, options);
  455. // write affectors
  456. E_PARTICLE_AFFECTOR_TYPE atype = EPAT_NONE;
  457. for (core::list<IParticleAffector*>::ConstIterator it = AffectorList.begin();
  458. it != AffectorList.end(); ++it)
  459. {
  460. atype = (*it)->getType();
  461. out->addEnum("Affector", (s32)atype, ParticleAffectorTypeNames);
  462. (*it)->serializeAttributes(out);
  463. }
  464. // add empty affector to make it possible to add further affectors
  465. if (options && options->Flags & io::EARWF_FOR_EDITOR)
  466. out->addEnum("Affector", EPAT_NONE, ParticleAffectorTypeNames);
  467. }
  468. //! Reads attributes of the scene node.
  469. void CParticleSystemSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
  470. {
  471. IParticleSystemSceneNode::deserializeAttributes(in, options);
  472. ParticlesAreGlobal = in->getAttributeAsBool("GlobalParticles");
  473. ParticleSize.Width = in->getAttributeAsFloat("ParticleWidth");
  474. ParticleSize.Height = in->getAttributeAsFloat("ParticleHeight");
  475. // read emitter
  476. int emitterIdx = in->findAttribute("Emitter");
  477. if (emitterIdx == -1)
  478. return;
  479. if (Emitter)
  480. Emitter->drop();
  481. Emitter = 0;
  482. E_PARTICLE_EMITTER_TYPE type = (E_PARTICLE_EMITTER_TYPE)
  483. in->getAttributeAsEnumeration("Emitter", ParticleEmitterTypeNames);
  484. switch(type)
  485. {
  486. case EPET_POINT:
  487. Emitter = createPointEmitter();
  488. break;
  489. case EPET_ANIMATED_MESH:
  490. Emitter = createAnimatedMeshSceneNodeEmitter(NULL); // we can't set the node - the user will have to do this
  491. break;
  492. case EPET_BOX:
  493. Emitter = createBoxEmitter();
  494. break;
  495. case EPET_CYLINDER:
  496. Emitter = createCylinderEmitter(core::vector3df(0,0,0), 10.f, core::vector3df(0,1,0), 10.f); // (values here don't matter)
  497. break;
  498. case EPET_MESH:
  499. Emitter = createMeshEmitter(NULL); // we can't set the mesh - the user will have to do this
  500. break;
  501. case EPET_RING:
  502. Emitter = createRingEmitter(core::vector3df(0,0,0), 10.f, 10.f); // (values here don't matter)
  503. break;
  504. case EPET_SPHERE:
  505. Emitter = createSphereEmitter(core::vector3df(0,0,0), 10.f); // (values here don't matter)
  506. break;
  507. default:
  508. break;
  509. }
  510. u32 idx = 0;
  511. #if 0
  512. if (Emitter)
  513. idx = Emitter->deserializeAttributes(idx, in);
  514. ++idx;
  515. #else
  516. if (Emitter)
  517. Emitter->deserializeAttributes(in);
  518. #endif
  519. // read affectors
  520. removeAllAffectors();
  521. u32 cnt = in->getAttributeCount();
  522. while(idx < cnt)
  523. {
  524. const char* name = in->getAttributeName(idx);
  525. if (!name || strcmp("Affector", name))
  526. return;
  527. E_PARTICLE_AFFECTOR_TYPE atype =
  528. (E_PARTICLE_AFFECTOR_TYPE)in->getAttributeAsEnumeration(idx, ParticleAffectorTypeNames);
  529. IParticleAffector* aff = 0;
  530. switch(atype)
  531. {
  532. case EPAT_ATTRACT:
  533. aff = createAttractionAffector(core::vector3df(0,0,0));
  534. break;
  535. case EPAT_FADE_OUT:
  536. aff = createFadeOutParticleAffector();
  537. break;
  538. case EPAT_GRAVITY:
  539. aff = createGravityAffector();
  540. break;
  541. case EPAT_ROTATE:
  542. aff = createRotationAffector();
  543. break;
  544. case EPAT_SCALE:
  545. aff = createScaleParticleAffector();
  546. break;
  547. case EPAT_NONE:
  548. default:
  549. break;
  550. }
  551. ++idx;
  552. if (aff)
  553. {
  554. #if 0
  555. idx = aff->deserializeAttributes(idx, in, options);
  556. ++idx;
  557. #else
  558. aff->deserializeAttributes(in, options);
  559. #endif
  560. addAffector(aff);
  561. aff->drop();
  562. }
  563. }
  564. }
  565. } // end namespace scene
  566. } // end namespace irr