diff options
author | Jacques Lucke <mail@jlucke.com> | 2019-07-18 13:08:36 +0300 |
---|---|---|
committer | Jacques Lucke <mail@jlucke.com> | 2019-07-18 13:08:36 +0300 |
commit | 7aa22a24a7fea3766cab4e59f46bbca8064ded8d (patch) | |
tree | 06b302fda347a6dceba0a5df510340ae1ddea4bb | |
parent | 4672d7aa83c5e6b2847c92d6c1be20e251bfa33a (diff) |
initial forwarding listeners + particle trail node
Still looking for a better name instead of Forwarding Listeners
-rw-r--r-- | release/scripts/startup/nodes/bparticle_nodes/trails.py | 16 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/core.cpp | 32 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/core.hpp | 77 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/forces.cpp | 18 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/forces.hpp | 13 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/inserters.cpp | 22 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/inserters.hpp | 5 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/node_frontend.cpp | 15 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/simulate.cpp | 77 | ||||
-rw-r--r-- | source/blender/simulations/bparticles/step_description.hpp | 6 |
10 files changed, 267 insertions, 14 deletions
diff --git a/release/scripts/startup/nodes/bparticle_nodes/trails.py b/release/scripts/startup/nodes/bparticle_nodes/trails.py new file mode 100644 index 00000000000..125d9a046c0 --- /dev/null +++ b/release/scripts/startup/nodes/bparticle_nodes/trails.py @@ -0,0 +1,16 @@ +import bpy +from bpy.props import * +from .. base import BParticlesNode +from .. socket_builder import SocketBuilder + +class ParticleTrailsNode(bpy.types.Node, BParticlesNode): + bl_idname = "bp_ParticleTrailsNode" + bl_label = "Particle Trails" + + particle_type_name: StringProperty() + + def declaration(self, builder : SocketBuilder): + builder.particle_modifier_output("effect", "Effect") + + def draw(self, layout): + layout.prop(self, "particle_type_name", text="") diff --git a/source/blender/simulations/bparticles/core.cpp b/source/blender/simulations/bparticles/core.cpp index e04e0b1bf3b..de3626a44bd 100644 --- a/source/blender/simulations/bparticles/core.cpp +++ b/source/blender/simulations/bparticles/core.cpp @@ -14,10 +14,24 @@ Event::~Event() { } +ForwardingListener::~ForwardingListener() +{ +} + ParticleType::~ParticleType() { } +ArrayRef<ForwardingListener *> ParticleType::forwarding_listeners() +{ + return {}; +} + +ArrayRef<Event *> ParticleType::events() +{ + return {}; +} + StepDescription::~StepDescription() { } @@ -357,4 +371,22 @@ IntegratorInterface::IntegratorInterface(ParticlesBlock &block, { } +/* ForwardingListenerInterface + ****************************************************/ + +ForwardingListenerInterface::ForwardingListenerInterface(ParticleSet &particles, + ParticleAllocator &particle_allocator, + AttributeArrays offsets, + float step_end_time, + ArrayRef<float> durations, + ArrayRef<float> time_factors) + : m_particles(particles), + m_particle_allocator(particle_allocator), + m_offsets(offsets), + m_step_end_time(step_end_time), + m_durations(durations), + m_time_factors(time_factors) +{ +} + } // namespace BParticles diff --git a/source/blender/simulations/bparticles/core.hpp b/source/blender/simulations/bparticles/core.hpp index 70aefdc2ebb..0b12545b1b7 100644 --- a/source/blender/simulations/bparticles/core.hpp +++ b/source/blender/simulations/bparticles/core.hpp @@ -25,6 +25,7 @@ class EventFilterInterface; class EventExecuteInterface; class EmitterInterface; class IntegratorInterface; +class ForwardingListenerInterface; /* Main API for the particle simulation. These classes have to be subclassed to define how the * particles should behave. @@ -118,6 +119,13 @@ class Integrator { virtual void integrate(IntegratorInterface &interface) = 0; }; +class ForwardingListener { + public: + virtual ~ForwardingListener(); + + virtual void listen(ForwardingListenerInterface &interface) = 0; +}; + /** * Describes how one type of particle behaves and which attributes it has. */ @@ -130,10 +138,12 @@ class ParticleType { */ virtual Integrator &integrator() = 0; + virtual ArrayRef<ForwardingListener *> forwarding_listeners(); + /** * Return the events that particles of this type can trigger. */ - virtual ArrayRef<Event *> events() = 0; + virtual ArrayRef<Event *> events(); /** * Allows to define which attributes should exist for the type. @@ -574,6 +584,32 @@ class IntegratorInterface { AttributeArrays offset_targets(); }; +class ForwardingListenerInterface { + private: + ParticleSet m_particles; + ParticleAllocator &m_particle_allocator; + AttributeArrays m_offsets; + float m_step_end_time; + ArrayRef<float> m_durations; + ArrayRef<float> m_time_factors; + + public: + ForwardingListenerInterface(ParticleSet &particles, + ParticleAllocator &particle_allocator, + AttributeArrays offsets, + float step_end_time, + ArrayRef<float> durations, + ArrayRef<float> time_factors); + + ParticleSet &particles(); + ParticleAllocator &particle_allocator(); + AttributeArrays &offsets(); + ArrayRef<float> time_factors(); + float step_end_time(); + ArrayRef<float> durations(); + TimeSpan time_span(uint pindex); +}; + /* Event inline functions ********************************************/ @@ -862,4 +898,43 @@ inline AttributeArrays IntegratorInterface::offset_targets() return m_offsets; } +/* ForwardingListenerInterface inline functions + **********************************************/ + +inline ParticleSet &ForwardingListenerInterface::particles() +{ + return m_particles; +} + +inline ParticleAllocator &ForwardingListenerInterface::particle_allocator() +{ + return m_particle_allocator; +} + +inline AttributeArrays &ForwardingListenerInterface::offsets() +{ + return m_offsets; +} + +inline ArrayRef<float> ForwardingListenerInterface::time_factors() +{ + return m_time_factors; +} + +inline float ForwardingListenerInterface::step_end_time() +{ + return m_step_end_time; +} + +inline ArrayRef<float> ForwardingListenerInterface::durations() +{ + return m_durations; +} + +inline TimeSpan ForwardingListenerInterface::time_span(uint pindex) +{ + float duration = m_durations[pindex]; + return TimeSpan(m_step_end_time - duration, duration); +} + } // namespace BParticles diff --git a/source/blender/simulations/bparticles/forces.cpp b/source/blender/simulations/bparticles/forces.cpp index 28d00e9355d..7e39e512cd8 100644 --- a/source/blender/simulations/bparticles/forces.cpp +++ b/source/blender/simulations/bparticles/forces.cpp @@ -44,4 +44,22 @@ void TurbulenceForce::add_force(ParticlesBlock &block, ArrayRef<float3> r_force) } } +void TrailListener::listen(ForwardingListenerInterface &interface) +{ + ParticleSet particles = interface.particles(); + auto positions = particles.attributes().get_float3("Position"); + + SmallVector<float3> new_positions; + SmallVector<float> new_birth_times; + for (uint pindex : particles.pindices()) { + new_positions.append(positions[pindex]); + new_birth_times.append(interface.time_span(pindex).start()); + } + + auto new_particles = interface.particle_allocator().request(m_particle_type_name, + new_positions.size()); + new_particles.set_float3("Position", new_positions); + new_particles.set_float("Birth Time", new_birth_times); +} + } // namespace BParticles diff --git a/source/blender/simulations/bparticles/forces.hpp b/source/blender/simulations/bparticles/forces.hpp index 074bef42e71..f9c3b21ed5c 100644 --- a/source/blender/simulations/bparticles/forces.hpp +++ b/source/blender/simulations/bparticles/forces.hpp @@ -40,4 +40,17 @@ class TurbulenceForce : public Force { void add_force(ParticlesBlock &block, ArrayRef<float3> r_force) override; }; +class TrailListener : public ForwardingListener { + private: + std::string m_particle_type_name; + + public: + TrailListener(StringRef particle_type_name) + : m_particle_type_name(particle_type_name.to_std_string()) + { + } + + void listen(ForwardingListenerInterface &interface) override; +}; + } // namespace BParticles diff --git a/source/blender/simulations/bparticles/inserters.cpp b/source/blender/simulations/bparticles/inserters.cpp index 3b30e5c2283..7ca19b297f7 100644 --- a/source/blender/simulations/bparticles/inserters.cpp +++ b/source/blender/simulations/bparticles/inserters.cpp @@ -397,6 +397,21 @@ static std::unique_ptr<Emitter> BUILD_EMITTER_initial_grid(BuildContext &ctx, body->get_output<float>(fn_out, 4, "Size"))); } +static std::unique_ptr<ForwardingListener> BUILD_FORWARDING_LISTENER_trails(BuildContext &ctx, + bNode *bnode) +{ + PointerRNA rna = ctx.indexed_tree.get_rna(bnode); + char name[65]; + RNA_string_get(&rna, "particle_type_name", name); + + if (ctx.step_description.m_types.contains(name)) { + return std::unique_ptr<ForwardingListener>(new TrailListener(name)); + } + else { + return {}; + } +} + BLI_LAZY_INIT(StringMap<ForceFromNodeCallback>, get_force_builders) { StringMap<ForceFromNodeCallback> map; @@ -424,4 +439,11 @@ BLI_LAZY_INIT(StringMap<EmitterFromNodeCallback>, get_emitter_builders) return map; } +BLI_LAZY_INIT(StringMap<ForwardingListenerFromNodeCallback>, get_forwarding_listener_builders) +{ + StringMap<ForwardingListenerFromNodeCallback> map; + map.add_new("bp_ParticleTrailsNode", BUILD_FORWARDING_LISTENER_trails); + return map; +} + } // namespace BParticles diff --git a/source/blender/simulations/bparticles/inserters.hpp b/source/blender/simulations/bparticles/inserters.hpp index 4e300513f3e..845a5a961e7 100644 --- a/source/blender/simulations/bparticles/inserters.hpp +++ b/source/blender/simulations/bparticles/inserters.hpp @@ -40,4 +40,9 @@ using EmitterFromNodeCallback = std::function<std::unique_ptr<Emitter>( StringMap<EmitterFromNodeCallback> &get_emitter_builders(); +using ForwardingListenerFromNodeCallback = + std::function<std::unique_ptr<ForwardingListener>(BuildContext &ctx, bNode *bnode)>; + +StringMap<ForwardingListenerFromNodeCallback> &get_forwarding_listener_builders(); + } // namespace BParticles diff --git a/source/blender/simulations/bparticles/node_frontend.cpp b/source/blender/simulations/bparticles/node_frontend.cpp index 70aff0ce7a8..185c61cb535 100644 --- a/source/blender/simulations/bparticles/node_frontend.cpp +++ b/source/blender/simulations/bparticles/node_frontend.cpp @@ -60,6 +60,21 @@ std::unique_ptr<StepDescription> step_description_from_node_tree(IndexedNodeTree } } + for (auto item : get_forwarding_listener_builders().items()) { + for (bNode *bnode : indexed_tree.nodes_with_idname(item.key)) { + bNodeSocket *listener_output = bSocketList(bnode->outputs).get(0); + for (SocketWithNode linked : indexed_tree.linked(listener_output)) { + if (is_particle_type_node(linked.node)) { + auto listener = item.value(ctx, bnode); + if (listener) { + step_description->m_types.lookup_ref(linked.node->name) + ->m_forwarding_listeners.append(listener.release()); + } + } + } + } + } + for (auto item : get_event_builders().items()) { for (bNode *bnode : indexed_tree.nodes_with_idname(item.key)) { bNodeSocket *event_input = bSocketList(bnode->inputs).get(0); diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp index 771f97d3d47..960b6c2be09 100644 --- a/source/blender/simulations/bparticles/simulate.cpp +++ b/source/blender/simulations/bparticles/simulate.cpp @@ -68,10 +68,24 @@ BLI_NOINLINE static void find_next_event_per_particle(ParticleSet particles, } BLI_NOINLINE static void forward_particles_to_next_event_or_end( + ParticleType &particle_type, + ParticleAllocator &particle_allocator, ParticleSet particles, AttributeArrays attribute_offsets, + float step_end_time, + ArrayRef<float> remaining_durations, ArrayRef<float> time_factors_to_next_event) { + ForwardingListenerInterface interface(particles, + particle_allocator, + attribute_offsets, + step_end_time, + remaining_durations, + time_factors_to_next_event); + for (ForwardingListener *listener : particle_type.forwarding_listeners()) { + listener->listen(interface); + } + for (uint attribute_index : attribute_offsets.info().float3_attributes()) { StringRef name = attribute_offsets.info().name_of(attribute_index); @@ -187,12 +201,14 @@ BLI_NOINLINE static void execute_events(ParticleAllocator &particle_allocator, BLI_NOINLINE static void simulate_to_next_event(ArrayAllocator &array_allocator, ParticleAllocator &particle_allocator, ParticleSet particles, + ParticleType &particle_type, AttributeArrays attribute_offsets, ArrayRef<float> remaining_durations, float end_time, - ArrayRef<Event *> events, VectorAdaptor<uint> &r_unfinished_pindices) { + ArrayRef<Event *> events = particle_type.events(); + ArrayAllocator::Array<int> next_event_indices(array_allocator); ArrayAllocator::Array<float> time_factors_to_next_event(array_allocator); ArrayAllocator::Vector<uint> pindices_with_event(array_allocator); @@ -211,7 +227,13 @@ BLI_NOINLINE static void simulate_to_next_event(ArrayAllocator &array_allocator, time_factors_to_next_event, pindices_with_event); - forward_particles_to_next_event_or_end(particles, attribute_offsets, time_factors_to_next_event); + forward_particles_to_next_event_or_end(particle_type, + particle_allocator, + particles, + attribute_offsets, + end_time, + remaining_durations, + time_factors_to_next_event); update_remaining_attribute_offsets( pindices_with_event, time_factors_to_next_event, attribute_offsets); @@ -245,10 +267,10 @@ BLI_NOINLINE static void simulate_with_max_n_events(uint max_events, ArrayAllocator &array_allocator, ParticleAllocator &particle_allocator, ParticlesBlock &block, + ParticleType &particle_type, AttributeArrays attribute_offsets, ArrayRef<float> remaining_durations, float end_time, - ArrayRef<Event *> events, VectorAdaptor<uint> &r_unfinished_pindices) { BLI_assert(array_allocator.array_size() >= block.active_amount()); @@ -263,10 +285,10 @@ BLI_NOINLINE static void simulate_with_max_n_events(uint max_events, simulate_to_next_event(array_allocator, particle_allocator, ParticleSet(block, Range<uint>(0, amount_left).as_array_ref()), + particle_type, attribute_offsets, remaining_durations, end_time, - events, indices_output); amount_left = indices_output.size(); } @@ -278,10 +300,10 @@ BLI_NOINLINE static void simulate_with_max_n_events(uint max_events, simulate_to_next_event(array_allocator, particle_allocator, ParticleSet(block, indices_input), + particle_type, attribute_offsets, remaining_durations, end_time, - events, indices_output); amount_left = indices_output.size(); std::swap(indices_A, indices_B); @@ -320,9 +342,28 @@ BLI_NOINLINE static void add_float3_arrays(ArrayRef<float3> base, ArrayRef<float } } -BLI_NOINLINE static void apply_remaining_offsets(ParticleSet particles, - AttributeArrays attribute_offsets) +BLI_NOINLINE static void apply_remaining_offsets(ParticleType &particle_type, + ArrayAllocator &array_allocator, + ParticleAllocator &particle_allocator, + ParticleSet particles, + AttributeArrays attribute_offsets, + ArrayRef<float> durations, + float step_end_time) { + auto listeners = particle_type.forwarding_listeners(); + if (listeners.size() > 0) { + ArrayAllocator::Array<float> time_factors(array_allocator); + for (uint pindex : particles.pindices()) { + time_factors[pindex] = 1.0f; + } + + ForwardingListenerInterface interface( + particles, particle_allocator, attribute_offsets, step_end_time, durations, time_factors); + for (ForwardingListener *listener : particle_type.forwarding_listeners()) { + listener->listen(interface); + } + } + for (uint attribute_index : attribute_offsets.info().float3_attributes()) { StringRef name = attribute_offsets.info().name_of(attribute_index); @@ -359,11 +400,15 @@ BLI_NOINLINE static void simulate_block(ArrayAllocator &array_allocator, IntegratorInterface interface(block, remaining_durations, array_allocator, attribute_offsets); integrator.integrate(interface); - ArrayRef<Event *> events = particle_type.events(); - - if (events.size() == 0) { + if (particle_type.events().size() == 0) { ParticleSet all_particles_in_block(block, block.active_range().as_array_ref()); - apply_remaining_offsets(all_particles_in_block, attribute_offsets); + apply_remaining_offsets(particle_type, + array_allocator, + particle_allocator, + all_particles_in_block, + attribute_offsets, + remaining_durations, + end_time); } else { auto indices_array = array_allocator.allocate_scoped<uint>(); @@ -373,16 +418,22 @@ BLI_NOINLINE static void simulate_block(ArrayAllocator &array_allocator, array_allocator, particle_allocator, block, + particle_type, attribute_offsets, remaining_durations, end_time, - events, unfinished_pindices); /* Not sure yet, if this really should be done. */ if (unfinished_pindices.size() > 0) { ParticleSet remaining_particles(block, unfinished_pindices); - apply_remaining_offsets(remaining_particles, attribute_offsets); + apply_remaining_offsets(particle_type, + array_allocator, + particle_allocator, + remaining_particles, + attribute_offsets, + remaining_durations, + end_time); } } diff --git a/source/blender/simulations/bparticles/step_description.hpp b/source/blender/simulations/bparticles/step_description.hpp index c262f5a3044..4799bef7497 100644 --- a/source/blender/simulations/bparticles/step_description.hpp +++ b/source/blender/simulations/bparticles/step_description.hpp @@ -7,6 +7,7 @@ namespace BParticles { class ModifierParticleType : public ParticleType { public: SmallVector<Event *> m_events; + SmallVector<ForwardingListener *> m_forwarding_listeners; Integrator *m_integrator; ~ModifierParticleType() @@ -23,6 +24,11 @@ class ModifierParticleType : public ParticleType { return m_events; } + ArrayRef<ForwardingListener *> forwarding_listeners() override + { + return m_forwarding_listeners; + } + Integrator &integrator() override { return *m_integrator; |