CParticleMeshEmitter.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright (C) 2002-2012 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 "IrrCompileConfig.h"
  5. #include "CParticleMeshEmitter.h"
  6. #include "os.h"
  7. namespace irr
  8. {
  9. namespace scene
  10. {
  11. //! constructor
  12. CParticleMeshEmitter::CParticleMeshEmitter(
  13. IMesh* mesh, bool useNormalDirection,
  14. const core::vector3df& direction, f32 normalDirectionModifier,
  15. s32 mbNumber, bool everyMeshVertex,
  16. u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
  17. const video::SColor& minStartColor, const video::SColor& maxStartColor,
  18. u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
  19. const core::dimension2df& minStartSize,
  20. const core::dimension2df& maxStartSize )
  21. : Mesh(0), TotalVertices(0), MBCount(0), MBNumber(mbNumber),
  22. NormalDirectionModifier(normalDirectionModifier), Direction(direction),
  23. MaxStartSize(maxStartSize), MinStartSize(minStartSize),
  24. MinParticlesPerSecond(minParticlesPerSecond), MaxParticlesPerSecond(maxParticlesPerSecond),
  25. MinStartColor(minStartColor), MaxStartColor(maxStartColor),
  26. MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax),
  27. Time(0), MaxAngleDegrees(maxAngleDegrees),
  28. EveryMeshVertex(everyMeshVertex), UseNormalDirection(useNormalDirection)
  29. {
  30. #ifdef _DEBUG
  31. setDebugName("CParticleMeshEmitter");
  32. #endif
  33. setMesh(mesh);
  34. }
  35. //! Prepares an array with new particles to emitt into the system
  36. //! and returns how much new particles there are.
  37. s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray)
  38. {
  39. Time += timeSinceLastCall;
  40. const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
  41. const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
  42. const f32 everyWhatMillisecond = 1000.0f / perSecond;
  43. if(Time > everyWhatMillisecond)
  44. {
  45. Particles.set_used(0);
  46. u32 amount = (u32)((Time / everyWhatMillisecond) + 0.5f);
  47. Time = 0;
  48. SParticle p;
  49. if(amount > MaxParticlesPerSecond * 2)
  50. amount = MaxParticlesPerSecond * 2;
  51. for(u32 i=0; i<amount; ++i)
  52. {
  53. if( EveryMeshVertex )
  54. {
  55. for( u32 j=0; j<Mesh->getMeshBufferCount(); ++j )
  56. {
  57. for( u32 k=0; k<Mesh->getMeshBuffer(j)->getVertexCount(); ++k )
  58. {
  59. p.pos = Mesh->getMeshBuffer(j)->getPosition(k);
  60. if( UseNormalDirection )
  61. p.vector = Mesh->getMeshBuffer(j)->getNormal(k) /
  62. NormalDirectionModifier;
  63. else
  64. p.vector = Direction;
  65. p.startTime = now;
  66. if( MaxAngleDegrees )
  67. {
  68. core::vector3df tgt = p.vector;
  69. tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
  70. tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
  71. tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
  72. p.vector = tgt;
  73. }
  74. p.endTime = now + MinLifeTime;
  75. if (MaxLifeTime != MinLifeTime)
  76. p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
  77. if (MinStartColor==MaxStartColor)
  78. p.color=MinStartColor;
  79. else
  80. p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
  81. p.startColor = p.color;
  82. p.startVector = p.vector;
  83. if (MinStartSize==MaxStartSize)
  84. p.startSize = MinStartSize;
  85. else
  86. p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
  87. p.size = p.startSize;
  88. Particles.push_back(p);
  89. }
  90. }
  91. }
  92. else
  93. {
  94. const s32 randomMB = (MBNumber < 0) ? (os::Randomizer::rand() % MBCount) : MBNumber;
  95. u32 vertexNumber = Mesh->getMeshBuffer(randomMB)->getVertexCount();
  96. if (!vertexNumber)
  97. continue;
  98. vertexNumber = os::Randomizer::rand() % vertexNumber;
  99. p.pos = Mesh->getMeshBuffer(randomMB)->getPosition(vertexNumber);
  100. if( UseNormalDirection )
  101. p.vector = Mesh->getMeshBuffer(randomMB)->getNormal(vertexNumber) /
  102. NormalDirectionModifier;
  103. else
  104. p.vector = Direction;
  105. p.startTime = now;
  106. if( MaxAngleDegrees )
  107. {
  108. core::vector3df tgt = Direction;
  109. tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
  110. tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
  111. tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
  112. p.vector = tgt;
  113. }
  114. p.endTime = now + MinLifeTime;
  115. if (MaxLifeTime != MinLifeTime)
  116. p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
  117. if (MinStartColor==MaxStartColor)
  118. p.color=MinStartColor;
  119. else
  120. p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
  121. p.startColor = p.color;
  122. p.startVector = p.vector;
  123. if (MinStartSize==MaxStartSize)
  124. p.startSize = MinStartSize;
  125. else
  126. p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
  127. p.size = p.startSize;
  128. Particles.push_back(p);
  129. }
  130. }
  131. outArray = Particles.pointer();
  132. return Particles.size();
  133. }
  134. return 0;
  135. }
  136. //! Set Mesh to emit particles from
  137. void CParticleMeshEmitter::setMesh(IMesh* mesh)
  138. {
  139. Mesh = mesh;
  140. TotalVertices = 0;
  141. MBCount = 0;
  142. VertexPerMeshBufferList.clear();
  143. if ( !Mesh )
  144. return;
  145. MBCount = Mesh->getMeshBufferCount();
  146. VertexPerMeshBufferList.reallocate(MBCount);
  147. for( u32 i = 0; i < MBCount; ++i )
  148. {
  149. VertexPerMeshBufferList.push_back( Mesh->getMeshBuffer(i)->getVertexCount() );
  150. TotalVertices += Mesh->getMeshBuffer(i)->getVertexCount();
  151. }
  152. }
  153. } // end namespace scene
  154. } // end namespace irr