ParticleEmitterResource.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright (C) 2009-2021, 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/ModelResource.h>
  8. #include <AnKi/Util/StringList.h>
  9. #include <AnKi/Util/Xml.h>
  10. #include <cstring>
  11. namespace anki
  12. {
  13. template<typename T>
  14. static ANKI_USE_RESULT Error getXmlVal(const XmlElement& el, const CString& tag, T& out, Bool& found)
  15. {
  16. return el.getAttributeNumberOptional(tag, out, found);
  17. }
  18. template<>
  19. ANKI_USE_RESULT Error getXmlVal(const XmlElement& el, const CString& tag, Vec3& out, Bool& found)
  20. {
  21. return el.getAttributeNumbersOptional(tag, out, found);
  22. }
  23. ParticleEmitterResource::ParticleEmitterResource(ResourceManager* manager)
  24. : ResourceObject(manager)
  25. {
  26. }
  27. ParticleEmitterResource::~ParticleEmitterResource()
  28. {
  29. }
  30. Error ParticleEmitterResource::load(const ResourceFilename& filename, Bool async)
  31. {
  32. XmlDocument doc;
  33. ANKI_CHECK(openFileParseXml(filename, doc));
  34. XmlElement rootEl; // Root element
  35. ANKI_CHECK(doc.getChildElement("particleEmitter", rootEl));
  36. #define ANKI_XML(varName, VarName) \
  37. ANKI_CHECK( \
  38. readVar(rootEl, #varName, m_particle.m_min##VarName, m_particle.m_max##VarName, &m_particle.m_min##VarName))
  39. ANKI_XML(life, Life);
  40. ANKI_XML(mass, Mass);
  41. ANKI_XML(initialSize, InitialSize);
  42. ANKI_XML(finalSize, FinalSize);
  43. ANKI_XML(initialAlpha, InitialAlpha);
  44. ANKI_XML(finalAlpha, FinalAlpha);
  45. ANKI_XML(forceDirection, ForceDirection);
  46. ANKI_XML(forceMagnitude, ForceMagnitude);
  47. ANKI_XML(gravity, Gravity);
  48. ANKI_XML(startingPosition, StartingPosition);
  49. #undef ANKI_XML
  50. XmlElement el;
  51. ANKI_CHECK(rootEl.getChildElement("maxNumberOfParticles", el));
  52. ANKI_CHECK(el.getAttributeNumber("value", m_maxNumOfParticles));
  53. ANKI_CHECK(rootEl.getChildElement("emissionPeriod", el));
  54. ANKI_CHECK(el.getAttributeNumber("value", m_emissionPeriod));
  55. ANKI_CHECK(rootEl.getChildElement("particlesPerEmission", el));
  56. ANKI_CHECK(el.getAttributeNumber("value", m_particlesPerEmission));
  57. ANKI_CHECK(rootEl.getChildElementOptional("usePhysicsEngine", el));
  58. if(el)
  59. {
  60. ANKI_CHECK(el.getAttributeNumber("value", m_usePhysicsEngine));
  61. }
  62. ANKI_CHECK(rootEl.getChildElementOptional("emitterBoundingVolume", el));
  63. if(el)
  64. {
  65. ANKI_CHECK(el.getAttributeNumbers("min", m_emitterBoundingVolumeMin));
  66. ANKI_CHECK(el.getAttributeNumbers("max", m_emitterBoundingVolumeMax));
  67. }
  68. CString cstr;
  69. ANKI_CHECK(rootEl.getChildElement("material", el));
  70. ANKI_CHECK(el.getAttributeText("value", cstr));
  71. ANKI_CHECK(getManager().loadResource(cstr, m_material, async));
  72. return Error::NONE;
  73. }
  74. template<typename T>
  75. Error ParticleEmitterResource::readVar(const XmlElement& rootEl, CString varName, T& minVal, T& maxVal,
  76. const T* defaultVal)
  77. {
  78. XmlElement el;
  79. // <varName>
  80. ANKI_CHECK(rootEl.getChildElementOptional(varName, el));
  81. if(!el && !defaultVal)
  82. {
  83. ANKI_RESOURCE_LOGE("<%s> is missing", varName.cstr());
  84. return Error::USER_DATA;
  85. }
  86. if(!el)
  87. {
  88. maxVal = minVal = *defaultVal;
  89. return Error::NONE;
  90. }
  91. // value tag
  92. Bool found;
  93. ANKI_CHECK(getXmlVal(el, "value", minVal, found));
  94. if(found)
  95. {
  96. maxVal = minVal;
  97. return Error::NONE;
  98. }
  99. // min & max value tags
  100. ANKI_CHECK(getXmlVal(el, "min", minVal, found));
  101. if(!found)
  102. {
  103. ANKI_RESOURCE_LOGE("tag min is missing for <%s>", varName.cstr());
  104. return Error::USER_DATA;
  105. }
  106. ANKI_CHECK(getXmlVal(el, "max", maxVal, found));
  107. if(!found)
  108. {
  109. ANKI_RESOURCE_LOGE("tag max is missing for <%s>", varName.cstr());
  110. return Error::USER_DATA;
  111. }
  112. if(minVal > maxVal)
  113. {
  114. ANKI_RESOURCE_LOGE("min tag should have less value than max for <%s>", varName.cstr());
  115. return Error::USER_DATA;
  116. }
  117. return Error::NONE;
  118. }
  119. void ParticleEmitterResource::getRenderingInfo(const RenderingKey& key_, ShaderProgramPtr& prog) const
  120. {
  121. RenderingKey key = key_;
  122. key.setLod(min<U32>(key.getLod(), m_lodCount - 1));
  123. const MaterialVariant& variant = m_material->getOrCreateVariant(key);
  124. prog = variant.getShaderProgram();
  125. }
  126. } // end namespace anki