ParticleEmitterResource.cpp 4.0 KB

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