/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #ifndef __NEMITTER__ #define __NEMITTER__ #include "core/item.h" #include "core/renderable.h" #include "geometry/curve.h" #include "sort/sort.h" namespace GS { namespace Core { /*! @short Particle class. @author Emmanuel Julien (ejulien@gsworks.fr) */ struct Particle { Time time; Vector4 position, velocity; float size; float angle; Color color; /*! @name Parameter scaler. @{ */ float opacity_scale, size_scale; /// @} /// Is the particle alive. bool IsAlive() const { return time.toSec() < 0 ? false : true; } Particle() { opacity_scale = 1; } }; /* @short Particle model. Models the particle attributes over its lifetime. @author Emmanuel Julien (ejulien@gsworks.fr) */ struct ParticleModel : public SharedObject { struct RenderData { Render::sMaterial material; }; String name; String material; Time time_to_live; ///< Time to live. float damping; ///< Particle velocity damping. Vector4 gravity; ///< Particle gravity. Curve angle_curve, size_curve; Curve red_curve, green_curve, blue_curve, opacity_curve; AutoPtr render_data; /// Setup render data. void RenderSetup(ResourceFactories * = 0); /*! @short Set template color. This function does not clear the color and opacity curves. It only set their default value member, curves with keys will animate as usual. */ void SetColor(const Color &); /// Add color curve point. void AddColorPoint(const Time &t, const Color &); /*! @name Serialization. @{ */ bool FromMetaTag(NML::Tag &); NML::Tag *AsMetaTag() const; /// @} ParticleModel(); }; typedef SharedPtr sParticleModel; /*! @short Emitter class. Note: Emitters emit particle along the Z axis. @author Emmanuel Julien (ejulien@gsworks.fr) */ class Emitter : public Item, public Renderable { public: struct RenderData { sParticleModel particle_model; }; enum Model { Model_Spray = 0 }; /*! @name Emitter model. @{ */ protected: Model model; public: /*! @name Renderable interface. @{ */ /// Compute the renderable minmax. virtual void ComputeRenderableMinMax(MinMax &mm) { ComputeMinMax(mm); } /// Get the renderable primitive list for this renderable. virtual uint GetRenderablePrimitiveList(const Camera &view, const Camera &default_view, Stack &list, Renderable::Context context = Renderable::Context_Default, bool cull = true); /// @} uint pool_size; ///< Particle pool size. float birth_rate; ///< Rate in particle/second. float birth_speed_min, birth_speed_max; ///< Speed in m.s. float spray_angle; /*! @name Model scale. @{ */ float birth_rate_scale, birth_opacity_scale, birth_speed_scale, birth_size_scale; /// @} String particle_model; /// Model particle. void ModelParticle(Particle &, const Item &, const Time &emitter_time); /// Get emitter model. Model GetModel() const { return model; } /// Set as spray emitter. void SetSprayModel(float angle = Units::Deg(45.f)); /// @} AutoPtr render_data; protected: Array particle_pool; uint alive_count; bool is_seen; Time time; Time birth_time; Array ::Entry> sort_array; public: void RenderSetup(ResourceFactories * = 0); bool Setup(); void Update(const Time &dt); void Free(); void ComputeMinMax(MinMax &) const; /// Sort emitter particles against a given view matrix. void Sort(const Matrix4 &view_matrix); /*! @short Get alive particle count. @note The emitter must have been sorted beforehand. @see Sort(). */ uint GetParticleCount() const { return alive_count; } /* @short Get alive particle. @note Particles are returned back to front. */ Particle *GetParticle(uint n) const { return n < particle_pool.GetCount() ? &particle_pool[sort_array[alive_count - 1 - n].o] : 0; } /*! @name Serialization. @{ */ bool FromMetaTag(NML::Tag &); NML::Tag *AsMetaTag() const; /// @} Emitter(); }; } // Core } // GS #endif // __NEMITTER__