// Copyright (c) 2011 The Foundry Visionmongers Ltd. All Rights Reserved. #include "DDImage/Knob.h" #include "DDImage/Knobs.h" #include "DDImage/ParticleOp.h" #include "DDImage/ParallelFor.h" #include using namespace DD::Image; static const char* const CLASS = "ParticleGravity"; static const char* const HELP = "Apply gravity to the particles. \n" "- can be applied on each or all of the x,y,z axis in both directions.\n" "- is actually more of a directional acceleration node than gravity (it " "can go in directions other than \"down\")."; class ParticleGravity : public ParticleBehaviour { public: ParticleGravity(Node* node) : ParticleBehaviour(node) { _forceAxis = {{ Vector3(0, 0, 0), Vector3(0, -0.1, 0) }}; } void knobs( Knob_Callback f ) override { ParticleBehaviour::knobs(f); PositionVector_knob(f, reinterpret_cast(_forceAxis.data()), "strength"); Tooltip(f, "The acceleration to be applied to all particles, expressed in units/frame/frame. " "The direction and magnitude of the vector are applied. The position of the vector " "has no effect.\n" "Gravity affects all particles equally irrespective of mass. For more details " "see Galileo. "); addConditionsKnobs( f ); addDomainKnobs( f ); if (!isLicensed()) set_unlicensed(); } bool applyBehaviour( const ParticleContext& context, ParticleSystem* ps ) override { Vector3 strength = _forceAxis[1] - _forceAxis[0]; const auto particleStartTime = ps->particleStartTime(); auto particleVelocity = ps->particleVelocity(); ParallelFor(ps->numParticles(), [&](int i) { if ( conditionsApply( ps, i ) ) applyAcceleration(context, strength, particleVelocity[i], particleStartTime[i]); } ); return true; } static const Description description; const char* Class() const override { return CLASS; } const char* node_help() const override { return HELP; } private: std::array _forceAxis; }; static Op* build(Node* node) { return new ParticleGravity(node); } const Op::Description ParticleGravity::description(CLASS, build);