ParticleEmitterResource.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/resource/ParticleEmitterResource.h>
  6. #include <anki/resource/ResourceManager.h>
  7. #include <anki/resource/Model.h>
  8. #include <anki/util/StringList.h>
  9. #include <anki/misc/Xml.h>
  10. #include <cstring>
  11. namespace anki
  12. {
  13. static ANKI_USE_RESULT Error xmlVec3(const XmlElement& el_, const CString& str, Vec3& out)
  14. {
  15. Error err = ErrorCode::NONE;
  16. XmlElement el;
  17. err = el_.getChildElementOptional(str, el);
  18. if(err || !el)
  19. {
  20. return err;
  21. }
  22. err = el.getVec3(out);
  23. return err;
  24. }
  25. static ANKI_USE_RESULT Error xmlF32(const XmlElement& el_, const CString& str, F32& out)
  26. {
  27. Error err = ErrorCode::NONE;
  28. XmlElement el;
  29. err = el_.getChildElementOptional(str, el);
  30. if(err || !el)
  31. {
  32. return err;
  33. }
  34. F64 tmp;
  35. err = el.getNumber(tmp);
  36. if(!err)
  37. {
  38. out = tmp;
  39. }
  40. return err;
  41. }
  42. static ANKI_USE_RESULT Error xmlU32(const XmlElement& el_, const CString& str, U32& out)
  43. {
  44. Error err = ErrorCode::NONE;
  45. XmlElement el;
  46. err = el_.getChildElementOptional(str, el);
  47. if(err || !el)
  48. {
  49. return err;
  50. }
  51. I64 tmp;
  52. err = el.getNumber(tmp);
  53. if(!err)
  54. {
  55. out = static_cast<U32>(tmp);
  56. }
  57. return err;
  58. }
  59. ParticleEmitterProperties& ParticleEmitterProperties::operator=(const ParticleEmitterProperties& b)
  60. {
  61. std::memcpy(this, &b, sizeof(ParticleEmitterProperties));
  62. return *this;
  63. }
  64. void ParticleEmitterProperties::updateFlags()
  65. {
  66. m_forceEnabled = !isZero(m_particle.m_forceDirection.getLengthSquared());
  67. m_forceEnabled = m_forceEnabled || !isZero(m_particle.m_forceDirectionDeviation.getLengthSquared());
  68. m_forceEnabled =
  69. m_forceEnabled && (m_particle.m_forceMagnitude != 0.0 || m_particle.m_forceMagnitudeDeviation != 0.0);
  70. m_wordGravityEnabled = isZero(m_particle.m_gravity.getLengthSquared());
  71. }
  72. ParticleEmitterResource::ParticleEmitterResource(ResourceManager* manager)
  73. : ResourceObject(manager)
  74. {
  75. }
  76. ParticleEmitterResource::~ParticleEmitterResource()
  77. {
  78. }
  79. Error ParticleEmitterResource::load(const ResourceFilename& filename, Bool async)
  80. {
  81. U32 tmp;
  82. XmlDocument doc;
  83. ANKI_CHECK(openFileParseXml(filename, doc));
  84. XmlElement rel; // Root element
  85. ANKI_CHECK(doc.getChildElement("particleEmitter", rel));
  86. // XML load
  87. //
  88. ANKI_CHECK(xmlF32(rel, "life", m_particle.m_life));
  89. ANKI_CHECK(xmlF32(rel, "lifeDeviation", m_particle.m_lifeDeviation));
  90. ANKI_CHECK(xmlF32(rel, "mass", m_particle.m_mass));
  91. ANKI_CHECK(xmlF32(rel, "massDeviation", m_particle.m_massDeviation));
  92. ANKI_CHECK(xmlF32(rel, "size", m_particle.m_size));
  93. ANKI_CHECK(xmlF32(rel, "sizeDeviation", m_particle.m_sizeDeviation));
  94. ANKI_CHECK(xmlF32(rel, "sizeAnimation", m_particle.m_sizeAnimation));
  95. ANKI_CHECK(xmlF32(rel, "alpha", m_particle.m_alpha));
  96. ANKI_CHECK(xmlF32(rel, "alphaDeviation", m_particle.m_alphaDeviation));
  97. tmp = m_particle.m_alphaAnimation;
  98. ANKI_CHECK(xmlU32(rel, "alphaAnimationEnabled", tmp));
  99. m_particle.m_alphaAnimation = tmp;
  100. ANKI_CHECK(xmlVec3(rel, "forceDirection", m_particle.m_forceDirection));
  101. ANKI_CHECK(xmlVec3(rel, "forceDirectionDeviation", m_particle.m_forceDirectionDeviation));
  102. ANKI_CHECK(xmlF32(rel, "forceMagnitude", m_particle.m_forceMagnitude));
  103. ANKI_CHECK(xmlF32(rel, "forceMagnitudeDeviation", m_particle.m_forceMagnitudeDeviation));
  104. ANKI_CHECK(xmlVec3(rel, "gravity", m_particle.m_gravity));
  105. ANKI_CHECK(xmlVec3(rel, "gravityDeviation", m_particle.m_gravityDeviation));
  106. ANKI_CHECK(xmlVec3(rel, "startingPosition", m_particle.m_startingPos));
  107. ANKI_CHECK(xmlVec3(rel, "startingPositionDeviation", m_particle.m_startingPosDeviation));
  108. ANKI_CHECK(xmlU32(rel, "maxNumberOfParticles", m_maxNumOfParticles));
  109. ANKI_CHECK(xmlF32(rel, "emissionPeriod", m_emissionPeriod));
  110. ANKI_CHECK(xmlU32(rel, "particlesPerEmittion", m_particlesPerEmittion));
  111. tmp = m_usePhysicsEngine;
  112. ANKI_CHECK(xmlU32(rel, "usePhysicsEngine", tmp));
  113. m_usePhysicsEngine = tmp;
  114. XmlElement el;
  115. CString cstr;
  116. ANKI_CHECK(rel.getChildElement("material", el));
  117. ANKI_CHECK(el.getText(cstr));
  118. ANKI_CHECK(getManager().loadResource(cstr, m_material, async));
  119. // sanity checks
  120. //
  121. static const char* ERROR = "Particle emmiter: Incorrect or missing value %s";
  122. if(m_particle.m_life <= 0.0)
  123. {
  124. ANKI_RESOURCE_LOGE(ERROR, "life");
  125. return ErrorCode::USER_DATA;
  126. }
  127. if(m_particle.m_life - m_particle.m_lifeDeviation <= 0.0)
  128. {
  129. ANKI_RESOURCE_LOGE(ERROR, "lifeDeviation");
  130. return ErrorCode::USER_DATA;
  131. }
  132. if(m_particle.m_size <= 0.0)
  133. {
  134. ANKI_RESOURCE_LOGE(ERROR, "size");
  135. return ErrorCode::USER_DATA;
  136. }
  137. if(m_maxNumOfParticles < 1)
  138. {
  139. ANKI_RESOURCE_LOGE(ERROR, "maxNumOfParticles");
  140. return ErrorCode::USER_DATA;
  141. }
  142. if(m_emissionPeriod <= 0.0)
  143. {
  144. ANKI_RESOURCE_LOGE(ERROR, "emissionPeriod");
  145. return ErrorCode::USER_DATA;
  146. }
  147. if(m_particlesPerEmittion < 1)
  148. {
  149. ANKI_RESOURCE_LOGE(ERROR, "particlesPerEmission");
  150. return ErrorCode::USER_DATA;
  151. }
  152. // Calc some stuff
  153. //
  154. updateFlags();
  155. return ErrorCode::NONE;
  156. }
  157. void ParticleEmitterResource::getRenderingInfo(U lod, ShaderProgramPtr& prog) const
  158. {
  159. lod = min<U>(lod, m_lodCount - 1);
  160. RenderingKey key(Pass::GB_FS, lod, 1);
  161. const MaterialVariant& variant = m_material->getOrCreateVariant(key);
  162. prog = variant.getShaderProgram();
  163. }
  164. } // end namespace anki