ParticleEmitter.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. // Copyright (C) 2014, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include "anki/scene/ParticleEmitter.h"
  6. #include "anki/scene/SceneGraph.h"
  7. #include "anki/scene/InstanceNode.h"
  8. #include "anki/scene/Misc.h"
  9. #include "anki/resource/Model.h"
  10. #include "anki/util/Functions.h"
  11. #include "anki/physics/PhysicsWorld.h"
  12. #include "anki/Gl.h"
  13. namespace anki {
  14. //==============================================================================
  15. // Misc =
  16. //==============================================================================
  17. const U COMPONENTS = 3 + 1 + 1; // 3 position, 1 size, 1 alpha
  18. const PtrSize VERT_SIZE = COMPONENTS * sizeof(F32);
  19. //==============================================================================
  20. static F32 getRandom(F32 initial, F32 deviation)
  21. {
  22. return (deviation == 0.0)
  23. ? initial
  24. : initial + randFloat(deviation) * 2.0 - deviation;
  25. }
  26. //==============================================================================
  27. static Vec3 getRandom(const Vec3& initial, const Vec3& deviation)
  28. {
  29. if(deviation == Vec3(0.0))
  30. {
  31. return initial;
  32. }
  33. else
  34. {
  35. Vec3 out;
  36. for(U i = 0; i < 3; i++)
  37. {
  38. out[i] = getRandom(initial[i], deviation[i]);
  39. }
  40. return out;
  41. }
  42. }
  43. //==============================================================================
  44. // ParticleBase =
  45. //==============================================================================
  46. //==============================================================================
  47. void ParticleBase::revive(const ParticleEmitter& pe,
  48. F32 /*prevUpdateTime*/, F32 crntTime)
  49. {
  50. ANKI_ASSERT(isDead());
  51. const ParticleEmitterProperties& props = pe;
  52. // life
  53. m_timeOfDeath = getRandom(crntTime + props.m_particle.m_life,
  54. props.m_particle.m_lifeDeviation);
  55. m_timeOfBirth = crntTime;
  56. }
  57. //==============================================================================
  58. // ParticleSimple =
  59. //==============================================================================
  60. //==============================================================================
  61. void ParticleSimple::simulate(const ParticleEmitter& pe,
  62. F32 prevUpdateTime, F32 crntTime)
  63. {
  64. F32 dt = crntTime - prevUpdateTime;
  65. ANKI_ASSERT(
  66. static_cast<const ParticleEmitterProperties&>(pe).
  67. m_particle.m_gravity.getLength() > 0.0);
  68. Vec4 xp = m_position;
  69. Vec4 xc = m_acceleration * (dt * dt) + m_velocity * dt + xp;
  70. m_position = xc;
  71. m_velocity += m_acceleration * dt;
  72. }
  73. //==============================================================================
  74. void ParticleSimple::revive(const ParticleEmitter& pe,
  75. F32 prevUpdateTime, F32 crntTime)
  76. {
  77. ParticleBase::revive(pe, prevUpdateTime, crntTime);
  78. m_velocity = Vec4(0.0);
  79. const ParticleEmitterProperties& props = pe;
  80. m_acceleration = getRandom(props.m_particle.m_gravity,
  81. props.m_particle.m_gravityDeviation).xyz0();
  82. // Set the initial position
  83. m_position = getRandom(props.m_particle.m_startingPos,
  84. props.m_particle.m_startingPosDeviation).xyz0();
  85. m_position += pe.getWorldTransform().getOrigin();
  86. }
  87. //==============================================================================
  88. // Particle =
  89. //==============================================================================
  90. #if 0
  91. //==============================================================================
  92. Particle::Particle(
  93. const char* name, SceneGraph* scene, // SceneNode
  94. // RigidBody
  95. PhysicsWorld* masterContainer, const RigidBody::Initializer& init_)
  96. : ParticleBase(name, scene, PT_PHYSICS)
  97. {
  98. RigidBody::Initializer init = init_;
  99. getSceneGraph().getPhysics().newPhysicsObject<RigidBody>(body, init);
  100. sceneNodeProtected.rigidBodyC = body;
  101. }
  102. //==============================================================================
  103. Particle::~Particle()
  104. {
  105. getSceneGraph().getPhysics().deletePhysicsObject(body);
  106. }
  107. //==============================================================================
  108. void Particle::revive(const ParticleEmitter& pe,
  109. F32 prevUpdateTime, F32 crntTime)
  110. {
  111. ParticleBase::revive(pe, prevUpdateTime, crntTime);
  112. const ParticleEmitterProperties& props = pe;
  113. // pre calculate
  114. Bool forceFlag = props.forceEnabled;
  115. Bool worldGravFlag = props.wordGravityEnabled;
  116. // activate it (Bullet stuff)
  117. body->forceActivationState(ACTIVE_TAG);
  118. body->activate();
  119. body->clearForces();
  120. body->setLinearVelocity(btVector3(0.0, 0.0, 0.0));
  121. body->setAngularVelocity(btVector3(0.0, 0.0, 0.0));
  122. // force
  123. if(forceFlag)
  124. {
  125. Vec3 forceDir = getRandom(props.particle.forceDirection,
  126. props.particle.forceDirectionDeviation);
  127. forceDir.normalize();
  128. if(!pe.identityRotation)
  129. {
  130. // the forceDir depends on the particle emitter rotation
  131. forceDir = pe.getWorldTransform().getRotation() * forceDir;
  132. }
  133. F32 forceMag = getRandom(props.particle.forceMagnitude,
  134. props.particle.forceMagnitudeDeviation);
  135. body->applyCentralForce(toBt(forceDir * forceMag));
  136. }
  137. // gravity
  138. if(!worldGravFlag)
  139. {
  140. body->setGravity(toBt(getRandom(props.particle.gravity,
  141. props.particle.gravityDeviation)));
  142. }
  143. // Starting pos. In local space
  144. Vec3 pos = getRandom(props.particle.startingPos,
  145. props.particle.startingPosDeviation);
  146. if(pe.identityRotation)
  147. {
  148. pos += pe.getWorldTransform().getOrigin();
  149. }
  150. else
  151. {
  152. pos.transform(pe.getWorldTransform());
  153. }
  154. btTransform trf(
  155. toBt(Transform(pos, pe.getWorldTransform().getRotation(), 1.0)));
  156. body->setWorldTransform(trf);
  157. }
  158. #endif
  159. //==============================================================================
  160. // ParticleEmitter =
  161. //==============================================================================
  162. //==============================================================================
  163. ParticleEmitter::ParticleEmitter(
  164. const CString& name, SceneGraph* scene,
  165. const CString& filename)
  166. : SceneNode(name, scene),
  167. SpatialComponent(this),
  168. MoveComponent(this),
  169. RenderComponent(this),
  170. m_particles(getSceneAllocator()),
  171. m_transforms(getSceneAllocator())
  172. {
  173. addComponent(static_cast<MoveComponent*>(this));
  174. addComponent(static_cast<SpatialComponent*>(this));
  175. addComponent(static_cast<RenderComponent*>(this));
  176. m_obb.setCenter(Vec4(0.0));
  177. m_obb.setExtend(Vec4(1.0, 1.0, 1.0, 0.0));
  178. m_obb.setRotation(Mat3x4::getIdentity());
  179. // Load resource
  180. m_particleEmitterResource.load(filename, &getResourceManager());
  181. // copy the resource to me
  182. ParticleEmitterProperties& me = *this;
  183. const ParticleEmitterProperties& other =
  184. m_particleEmitterResource->getProperties();
  185. me = other;
  186. if(m_usePhysicsEngine)
  187. {
  188. createParticlesSimulation(scene);
  189. m_simulationType = SimulationType::PHYSICS_ENGINE;
  190. }
  191. else
  192. {
  193. createParticlesSimpleSimulation(scene);
  194. m_simulationType = SimulationType::SIMPLE;
  195. }
  196. m_timeLeftForNextEmission = 0.0;
  197. RenderComponent::init();
  198. // Create the vertex buffer and object
  199. //
  200. PtrSize buffSize = m_maxNumOfParticles * VERT_SIZE * 3;
  201. GlDevice& gl = getSceneGraph()._getGlDevice();
  202. GlCommandBufferHandle cmd;
  203. cmd.create(&gl);
  204. m_vertBuff.create(cmd, GL_ARRAY_BUFFER, buffSize,
  205. GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
  206. // TODO Optimize that to avoid serialization
  207. cmd.finish();
  208. m_vertBuffMapping = (U8*)m_vertBuff.getPersistentMappingAddress();
  209. }
  210. //==============================================================================
  211. ParticleEmitter::~ParticleEmitter()
  212. {
  213. // Delete simple particles
  214. if(m_simulationType == SimulationType::SIMPLE)
  215. {
  216. for(ParticleBase* part : m_particles)
  217. {
  218. getSceneAllocator().deleteInstance(part);
  219. }
  220. }
  221. }
  222. //==============================================================================
  223. void ParticleEmitter::buildRendering(RenderingBuildData& data)
  224. {
  225. ANKI_ASSERT(data.m_subMeshIndicesCount <= m_transforms.size() + 1);
  226. if(m_aliveParticlesCount == 0)
  227. {
  228. return;
  229. }
  230. RenderingKey key = data.m_key;
  231. key.m_lod = 0;
  232. GlProgramPipelineHandle ppline;
  233. m_particleEmitterResource->getMaterial().getProgramPipeline(key, ppline);
  234. ppline.bind(data.m_jobs);
  235. PtrSize offset = (getGlobTimestamp() % 3) * (m_vertBuff.getSize() / 3);
  236. // Position
  237. m_vertBuff.bindVertexBuffer(data.m_jobs,
  238. 3, GL_FLOAT, false, VERT_SIZE, offset + 0, 0);
  239. // Scale
  240. m_vertBuff.bindVertexBuffer(data.m_jobs,
  241. 1, GL_FLOAT, false, VERT_SIZE, offset + sizeof(F32) * 3, 6);
  242. // Alpha
  243. m_vertBuff.bindVertexBuffer(data.m_jobs,
  244. 1, GL_FLOAT, false, VERT_SIZE, offset + sizeof(F32) * 4, 7);
  245. data.m_jobs.drawArrays(GL_POINTS,
  246. m_aliveParticlesCount,
  247. data.m_subMeshIndicesCount);
  248. }
  249. //==============================================================================
  250. const Material& ParticleEmitter::getMaterial()
  251. {
  252. return m_particleEmitterResource->getMaterial();
  253. }
  254. //==============================================================================
  255. void ParticleEmitter::onMoveComponentUpdate(
  256. SceneNode& node, F32 prevTime, F32 crntTime)
  257. {
  258. m_identityRotation =
  259. getWorldTransform().getRotation() == Mat3x4::getIdentity();
  260. }
  261. //==============================================================================
  262. void ParticleEmitter::createParticlesSimulation(SceneGraph* scene)
  263. {
  264. #if 0
  265. collShape = getSceneAllocator().newInstance<btSphereShape>(particle.size);
  266. RigidBody::Initializer binit;
  267. binit.shape = collShape;
  268. binit.group = PhysicsWorld::CG_PARTICLE;
  269. binit.mask = PhysicsWorld::CG_MAP;
  270. particles.reserve(maxNumOfParticles);
  271. for(U i = 0; i < maxNumOfParticles; i++)
  272. {
  273. binit.mass = getRandom(particle.mass, particle.massDeviation);
  274. Particle* part = getSceneGraph().newSceneNode<Particle>(
  275. nullptr, &scene->getPhysics(), binit);
  276. part->size = getRandom(particle.size, particle.sizeDeviation);
  277. part->alpha = getRandom(particle.alpha, particle.alphaDeviation);
  278. part->getRigidBody()->forceActivationState(DISABLE_SIMULATION);
  279. particles.push_back(part);
  280. }
  281. #endif
  282. }
  283. //==============================================================================
  284. void ParticleEmitter::createParticlesSimpleSimulation(SceneGraph* scene)
  285. {
  286. m_particles.resize(m_maxNumOfParticles);
  287. for(U i = 0; i < m_maxNumOfParticles; i++)
  288. {
  289. ParticleSimple* part =
  290. getSceneAllocator().newInstance<ParticleSimple>();
  291. part->m_size = getRandom(m_particle.m_size, m_particle.m_sizeDeviation);
  292. part->m_alpha =
  293. getRandom(m_particle.m_alpha, m_particle.m_alphaDeviation);
  294. m_particles[i] = part;
  295. }
  296. }
  297. //==============================================================================
  298. void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime)
  299. {
  300. // - Deactivate the dead particles
  301. // - Calc the AABB
  302. // - Calc the instancing stuff
  303. //
  304. Vec4 aabbmin(MAX_F32, MAX_F32, MAX_F32, 0.0);
  305. Vec4 aabbmax(MIN_F32, MIN_F32, MIN_F32, 0.0);
  306. m_aliveParticlesCount = 0;
  307. F32* verts = (F32*)(m_vertBuffMapping
  308. + (getGlobTimestamp() % 3) * (m_vertBuff.getSize() / 3));
  309. F32* verts_base = verts;
  310. (void)verts_base;
  311. for(ParticleBase* p : m_particles)
  312. {
  313. if(p->isDead())
  314. {
  315. // if its already dead so dont deactivate it again
  316. continue;
  317. }
  318. if(p->getTimeOfDeath() < crntTime)
  319. {
  320. // Just died
  321. p->kill();
  322. }
  323. else
  324. {
  325. // It's alive
  326. // Do checks
  327. ANKI_ASSERT(((PtrSize)verts + VERT_SIZE
  328. - (PtrSize)m_vertBuffMapping) <= m_vertBuff.getSize());
  329. // This will calculate a new world transformation
  330. p->simulate(*this, prevUpdateTime, crntTime);
  331. const Vec4& origin = p->getPosition();
  332. for(U i = 0; i < 3; i++)
  333. {
  334. aabbmin[i] = std::min(aabbmin[i], origin[i]);
  335. aabbmax[i] = std::max(aabbmax[i], origin[i]);
  336. }
  337. F32 lifePercent = (crntTime - p->getTimeOfBirth())
  338. / (p->getTimeOfDeath() - p->getTimeOfBirth());
  339. verts[0] = origin.x();
  340. verts[1] = origin.y();
  341. verts[2] = origin.z();
  342. // XXX set a flag for scale
  343. verts[3] = p->m_size + (lifePercent * m_particle.m_sizeAnimation);
  344. // Set alpha
  345. if(m_particle.m_alphaAnimation)
  346. {
  347. verts[4] = sin((lifePercent) * getPi<F32>()) * p->m_alpha;
  348. }
  349. else
  350. {
  351. verts[4] = p->m_alpha;
  352. }
  353. ++m_aliveParticlesCount;
  354. verts += 5;
  355. }
  356. }
  357. if(m_aliveParticlesCount != 0)
  358. {
  359. Vec4 min = aabbmin - m_particle.m_size;
  360. Vec4 max = aabbmax + m_particle.m_size;
  361. Vec4 center = (min + max) / 2.0;
  362. m_obb = Obb(center, Mat3x4::getIdentity(), max - center);
  363. }
  364. else
  365. {
  366. m_obb = Obb(Vec4(0.0), Mat3x4::getIdentity(), Vec4(0.001));
  367. }
  368. SpatialComponent::markForUpdate();
  369. //
  370. // Emit new particles
  371. //
  372. if(m_timeLeftForNextEmission <= 0.0)
  373. {
  374. U particlesCount = 0; // How many particles I am allowed to emmit
  375. for(ParticleBase* pp : m_particles)
  376. {
  377. ParticleBase& p = *pp;
  378. if(!p.isDead())
  379. {
  380. // its alive so skip it
  381. continue;
  382. }
  383. p.revive(*this, prevUpdateTime, crntTime);
  384. // do the rest
  385. ++particlesCount;
  386. if(particlesCount >= m_particlesPerEmittion)
  387. {
  388. break;
  389. }
  390. } // end for all particles
  391. m_timeLeftForNextEmission = m_emissionPeriod;
  392. } // end if can emit
  393. else
  394. {
  395. m_timeLeftForNextEmission -= crntTime - prevUpdateTime;
  396. }
  397. // Do something more
  398. doInstancingCalcs();
  399. }
  400. //==============================================================================
  401. void ParticleEmitter::doInstancingCalcs()
  402. {
  403. // Gather the move components of the instances
  404. SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
  405. Timestamp instancesTimestamp = 0;
  406. SceneObject::visitChildren([&](SceneObject& obj)
  407. {
  408. if(obj.getType() == SceneObject::Type::SCENE_NODE)
  409. {
  410. SceneNode& sn = obj.downCast<SceneNode>();
  411. if(sn.tryGetComponent<InstanceComponent>())
  412. {
  413. MoveComponent& move = sn.getComponent<MoveComponent>();
  414. instanceMoves.push_back(&move);
  415. instancesTimestamp =
  416. std::max(instancesTimestamp, move.getTimestamp());
  417. }
  418. }
  419. });
  420. // If instancing
  421. if(instanceMoves.size() != 0)
  422. {
  423. Bool transformsNeedUpdate = false;
  424. // Check if an instance was added or removed and reset the spatials and
  425. // the transforms
  426. if(instanceMoves.size() != m_transforms.size())
  427. {
  428. transformsNeedUpdate = true;
  429. // Check if instances added or removed
  430. if(m_transforms.size() < instanceMoves.size())
  431. {
  432. // Instances added
  433. U diff = instanceMoves.size() - m_transforms.size();
  434. while(diff-- != 0)
  435. {
  436. ObbSpatialComponent* newSpatial = getSceneAllocator().
  437. newInstance<ObbSpatialComponent>(this);
  438. addComponent(newSpatial);
  439. }
  440. }
  441. else
  442. {
  443. // Instances removed
  444. // TODO
  445. ANKI_ASSERT(0 && "TODO");
  446. }
  447. m_transforms.resize(instanceMoves.size());
  448. }
  449. if(transformsNeedUpdate || m_transformsTimestamp < instancesTimestamp)
  450. {
  451. m_transformsTimestamp = instancesTimestamp;
  452. // Update the transforms
  453. for(U i = 0; i < instanceMoves.size(); i++)
  454. {
  455. m_transforms[i] = instanceMoves[i]->getWorldTransform();
  456. }
  457. }
  458. // Update the spatials anyway
  459. U count = 0;
  460. iterateComponentsOfType<SpatialComponent>([&](SpatialComponent& sp)
  461. {
  462. // Skip the first
  463. if(count != 0)
  464. {
  465. ObbSpatialComponent* msp =
  466. staticCastPtr<ObbSpatialComponent*>(&sp);
  467. Obb aobb = m_obb;
  468. aobb.setCenter(Vec4(0.0));
  469. msp->m_obb = aobb.getTransformed(m_transforms[count - 1]);
  470. msp->markForUpdate();
  471. }
  472. ++count;
  473. });
  474. ANKI_ASSERT(count - 1 == m_transforms.size());
  475. } // end if instancing
  476. }
  477. //==============================================================================
  478. Bool ParticleEmitter::getHasWorldTransforms()
  479. {
  480. return true;
  481. }
  482. //==============================================================================
  483. void ParticleEmitter::getRenderWorldTransform(U index, Transform& trf)
  484. {
  485. ANKI_ASSERT(m_transforms.size() > 0);
  486. if(index == 0)
  487. {
  488. // Don't transform the particle positions. They are already in world
  489. // space
  490. trf = Transform::getIdentity();
  491. }
  492. else
  493. {
  494. --index;
  495. ANKI_ASSERT(index < m_transforms.size());
  496. // The particle positions are already in word space. Move them back to
  497. // local space
  498. Transform invTrf = getWorldTransform().getInverse();
  499. trf = m_transforms[index].combineTransformations(invTrf);
  500. }
  501. }
  502. } // end namespace anki