#include "anki/resource/ParticleEmitterResource.h" #include "anki/resource/Model.h" #include "anki/util/Exception.h" #include "anki/util/StringList.h" #include "anki/misc/Xml.h" #include namespace anki { //============================================================================== // Misc = //============================================================================== //============================================================================== static const char* errMsg = "Incorrect or missing value "; #define PE_EXCEPTION(x) ANKI_EXCEPTION("Particle emmiter: " + x) //============================================================================== static void xmlReadVec3(const XmlElement& el_, const char* str, Vec3& out) { XmlElement el = el_.getChildElementOptional(str); if(!el) { return; } StringList list; list = StringList::splitString(el.getText(), ' '); if(list.size() != 3) { throw ANKI_EXCEPTION("Expecting 3 floats for Vec3"); } for(U i = 0; i < 3; i++) { out[i] = std::stof(list[i]); } } //============================================================================== static void xmlReadFloat(const XmlElement& el_, const char* str, F32& out) { XmlElement el = el_.getChildElementOptional(str); if(!el) { return; } out = std::stof(el.getText()); } //============================================================================== static void xmlReadU(const XmlElement& el_, const char* str, U32& out) { XmlElement el = el_.getChildElementOptional(str); if(!el) { return; } out = (U32)std::stoi(el.getText()); } //============================================================================== // ParticleEmitterProperties = //============================================================================== //============================================================================== ParticleEmitterProperties& ParticleEmitterProperties::operator=( const ParticleEmitterProperties& b) { memcpy(this, &b, sizeof(ParticleEmitterProperties)); return *this; } //============================================================================== void ParticleEmitterProperties::updateFlags() { forceEnabled = !isZero(particle.forceDirection.getLengthSquared()); forceEnabled = forceEnabled || !isZero(particle.forceDirectionDeviation.getLengthSquared()); forceEnabled = forceEnabled && (particle.forceMagnitude != 0.0 || particle.forceMagnitudeDeviation != 0.0); wordGravityEnabled = isZero(particle.gravity.getLengthSquared()); } //============================================================================== // ParticleEmitterResource = //============================================================================== //============================================================================== ParticleEmitterResource::ParticleEmitterResource() {} //============================================================================== ParticleEmitterResource::~ParticleEmitterResource() {} //============================================================================== void ParticleEmitterResource::load(const char* filename) { try { XmlDocument doc; doc.loadFile(filename); loadInternal(doc.getChildElement("particleEmitter")); } catch(std::exception& e) { throw ANKI_EXCEPTION("Failed to load file: " + filename) << e; } } //============================================================================== void ParticleEmitterResource::loadInternal(const XmlElement& rootel) { // XML load // xmlReadFloat(rootel, "life", particle.life); xmlReadFloat(rootel, "lifeDeviation", particle.lifeDeviation); xmlReadFloat(rootel, "mass", particle.mass); xmlReadFloat(rootel, "massDeviation", particle.massDeviation); xmlReadFloat(rootel, "size", particle.size); xmlReadFloat(rootel, "sizeDeviation", particle.sizeDeviation); xmlReadFloat(rootel, "sizeAnimation", particle.sizeAnimation); xmlReadFloat(rootel, "alpha", particle.alpha); xmlReadFloat(rootel, "alphaDeviation", particle.alphaDeviation); xmlReadVec3(rootel, "forceDirection", particle.forceDirection); xmlReadVec3(rootel, "forceDirectionDeviation", particle.forceDirectionDeviation); xmlReadFloat(rootel, "forceMagnitude", particle.forceMagnitude); xmlReadFloat(rootel, "forceMagnitudeDeviation", particle.forceMagnitudeDeviation); xmlReadVec3(rootel, "gravity", particle.gravity); xmlReadVec3(rootel, "gravityDeviation", particle.gravityDeviation); xmlReadVec3(rootel, "startingPosition", particle.startingPos); xmlReadVec3(rootel, "startingPositionDeviation", particle.startingPosDeviation); xmlReadU(rootel, "maxNumberOfParticles", maxNumOfParticles); xmlReadFloat(rootel, "emissionPeriod", emissionPeriod); xmlReadU(rootel, "particlesPerEmittion", particlesPerEmittion); U32 u = usePhysicsEngine; xmlReadU(rootel, "usePhysicsEngine", u); usePhysicsEngine = u; XmlElement el = rootel.getChildElement("model"); model.load(el.getText()); // sanity checks // if(particle.life <= 0.0) { throw PE_EXCEPTION(errMsg + "life"); } if(particle.life - particle.lifeDeviation <= 0.0) { throw PE_EXCEPTION(errMsg + "lifeDeviation"); } if(particle.size <= 0.0) { throw PE_EXCEPTION(errMsg + "size"); } if(maxNumOfParticles < 1) { throw PE_EXCEPTION(errMsg + "maxNumOfParticles"); } if(emissionPeriod <= 0.0) { throw PE_EXCEPTION(errMsg + "emissionPeriod"); } if(particlesPerEmittion < 1) { throw PE_EXCEPTION(errMsg + "particlesPerEmission"); } // Calc some stuff // updateFlags(); } } // end namespace anki