[Bf-blender-cvs] [766edbdf1f8] master: Particles: improve mesh emitter
Jacques Lucke
noreply at git.blender.org
Thu Jul 23 17:57:42 CEST 2020
Commit: 766edbdf1f82389d89dc708b1e0d36efeaba0888
Author: Jacques Lucke
Date: Thu Jul 23 17:57:11 2020 +0200
Branches: master
https://developer.blender.org/rB766edbdf1f82389d89dc708b1e0d36efeaba0888
Particles: improve mesh emitter
Particles are now emitted from vertices of the mesh.
===================================================================
M source/blender/blenlib/BLI_vector.hh
M source/blender/functions/FN_multi_function_params.hh
M source/blender/simulation/CMakeLists.txt
A source/blender/simulation/intern/particle_mesh_emitter.cc
A source/blender/simulation/intern/particle_mesh_emitter.hh
M source/blender/simulation/intern/simulation_collect_influences.cc
M source/blender/simulation/intern/simulation_collect_influences.hh
M source/blender/simulation/intern/simulation_solver.cc
M source/blender/simulation/intern/simulation_solver.hh
A source/blender/simulation/intern/simulation_solver_influences.hh
M source/blender/simulation/intern/time_interval.hh
===================================================================
diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh
index 1bb674093bb..7eac511bf4a 100644
--- a/source/blender/blenlib/BLI_vector.hh
+++ b/source/blender/blenlib/BLI_vector.hh
@@ -561,7 +561,7 @@ class Vector {
/**
* Return a reference to the last element in the vector.
- * This will assert when the vector is empty.
+ * This invokes undefined behavior when the vector is empty.
*/
const T &last() const
{
diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh
index 93d7b47af83..ac4dca33cf0 100644
--- a/source/blender/functions/FN_multi_function_params.hh
+++ b/source/blender/functions/FN_multi_function_params.hh
@@ -50,52 +50,56 @@ class MFParamsBuilder {
MFParamsBuilder(const class MultiFunction &fn, int64_t min_array_size);
- template<typename T> void add_readonly_single_input(const T *value)
+ template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "")
{
- this->add_readonly_single_input(GVSpan::FromSingle(CPPType::get<T>(), value, min_array_size_));
+ this->add_readonly_single_input(GVSpan::FromSingle(CPPType::get<T>(), value, min_array_size_),
+ expected_name);
}
- void add_readonly_single_input(GVSpan ref)
+ void add_readonly_single_input(GVSpan ref, StringRef expected_name = "")
{
- this->assert_current_param_type(MFParamType::ForSingleInput(ref.type()));
+ this->assert_current_param_type(MFParamType::ForSingleInput(ref.type()), expected_name);
BLI_assert(ref.size() >= min_array_size_);
virtual_spans_.append(ref);
}
- void add_readonly_vector_input(GVArraySpan ref)
+ void add_readonly_vector_input(GVArraySpan ref, StringRef expected_name = "")
{
- this->assert_current_param_type(MFParamType::ForVectorInput(ref.type()));
+ this->assert_current_param_type(MFParamType::ForVectorInput(ref.type()), expected_name);
BLI_assert(ref.size() >= min_array_size_);
virtual_array_spans_.append(ref);
}
- template<typename T> void add_uninitialized_single_output(T *value)
+ template<typename T> void add_uninitialized_single_output(T *value, StringRef expected_name = "")
{
- this->add_uninitialized_single_output(GMutableSpan(CPPType::get<T>(), value, 1));
+ this->add_uninitialized_single_output(GMutableSpan(CPPType::get<T>(), value, 1),
+ expected_name);
}
- void add_uninitialized_single_output(GMutableSpan ref)
+ void add_uninitialized_single_output(GMutableSpan ref, StringRef expected_name = "")
{
- this->assert_current_param_type(MFParamType::ForSingleOutput(ref.type()));
+ this->assert_current_param_type(MFParamType::ForSingleOutput(ref.type()), expected_name);
BLI_assert(ref.size() >= min_array_size_);
mutable_spans_.append(ref);
}
- void add_vector_output(GVectorArray &vector_array)
+ void add_vector_output(GVectorArray &vector_array, StringRef expected_name = "")
{
- this->assert_current_param_type(MFParamType::ForVectorOutput(vector_array.type()));
+ this->assert_current_param_type(MFParamType::ForVectorOutput(vector_array.type()),
+ expected_name);
BLI_assert(vector_array.size() >= min_array_size_);
vector_arrays_.append(&vector_array);
}
- void add_single_mutable(GMutableSpan ref)
+ void add_single_mutable(GMutableSpan ref, StringRef expected_name = "")
{
- this->assert_current_param_type(MFParamType::ForMutableSingle(ref.type()));
+ this->assert_current_param_type(MFParamType::ForMutableSingle(ref.type()), expected_name);
BLI_assert(ref.size() >= min_array_size_);
mutable_spans_.append(ref);
}
- void add_vector_mutable(GVectorArray &vector_array)
+ void add_vector_mutable(GVectorArray &vector_array, StringRef expected_name = "")
{
- this->assert_current_param_type(MFParamType::ForMutableVector(vector_array.type()));
+ this->assert_current_param_type(MFParamType::ForMutableVector(vector_array.type()),
+ expected_name);
BLI_assert(vector_array.size() >= min_array_size_);
vector_arrays_.append(&vector_array);
}
@@ -119,11 +123,17 @@ class MFParamsBuilder {
}
private:
- void assert_current_param_type(MFParamType param_type)
+ void assert_current_param_type(MFParamType param_type, StringRef expected_name = "")
{
- UNUSED_VARS_NDEBUG(param_type);
+ UNUSED_VARS_NDEBUG(param_type, expected_name);
#ifdef DEBUG
int param_index = this->current_param_index();
+
+ if (expected_name != "") {
+ StringRef actual_name = signature_->param_names[param_index];
+ BLI_assert(actual_name == expected_name);
+ }
+
MFParamType expected_type = signature_->param_types[param_index];
BLI_assert(expected_type == param_type);
#endif
diff --git a/source/blender/simulation/CMakeLists.txt b/source/blender/simulation/CMakeLists.txt
index 243b056db74..6466a6e67d4 100644
--- a/source/blender/simulation/CMakeLists.txt
+++ b/source/blender/simulation/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC
intern/implicit_eigen.cpp
intern/particle_allocator.cc
intern/particle_function.cc
+ intern/particle_mesh_emitter.cc
intern/simulation_collect_influences.cc
intern/simulation_solver.cc
intern/simulation_update.cc
@@ -52,7 +53,9 @@ set(SRC
intern/implicit.h
intern/particle_allocator.hh
intern/particle_function.hh
+ intern/particle_mesh_emitter.hh
intern/simulation_collect_influences.hh
+ intern/simulation_solver_influences.hh
intern/simulation_solver.hh
intern/time_interval.hh
diff --git a/source/blender/simulation/intern/particle_mesh_emitter.cc b/source/blender/simulation/intern/particle_mesh_emitter.cc
new file mode 100644
index 00000000000..ab2ee0c81ed
--- /dev/null
+++ b/source/blender/simulation/intern/particle_mesh_emitter.cc
@@ -0,0 +1,147 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "particle_mesh_emitter.hh"
+
+#include "BLI_float4x4.hh"
+#include "BLI_rand.hh"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+namespace blender::sim {
+
+struct EmitterSettings {
+ const Object *object;
+ float rate;
+};
+
+static void compute_birth_times(float rate,
+ TimeInterval emit_interval,
+ ParticleMeshEmitterSimulationState &state,
+ Vector<float> &r_birth_times)
+{
+ const float time_between_particles = 1.0f / rate;
+ int counter = 0;
+ while (true) {
+ counter++;
+ const float time_offset = counter * time_between_particles;
+ const float birth_time = state.last_birth_time + time_offset;
+ if (birth_time > emit_interval.end()) {
+ break;
+ }
+ if (birth_time <= emit_interval.start()) {
+ continue;
+ }
+ r_birth_times.append(birth_time);
+ }
+}
+
+static void compute_new_particle_attributes(EmitterSettings &settings,
+ TimeInterval emit_interval,
+ ParticleMeshEmitterSimulationState &state,
+ Vector<float3> &r_positions,
+ Vector<float3> &r_velocities,
+ Vector<float> &r_birth_times)
+{
+ if (settings.object == nullptr) {
+ return;
+ }
+ if (settings.rate <= 0.000001f) {
+ return;
+ }
+ if (settings.object->type != OB_MESH) {
+ return;
+ }
+ const Mesh &mesh = *(Mesh *)settings.object->data;
+ if (mesh.totvert == 0) {
+ return;
+ }
+
+ float4x4 local_to_world = settings.object->obmat;
+
+ const float start_time = emit_interval.start();
+ const uint32_t seed = DefaultHash<StringRef>{}(state.head.name);
+ RandomNumberGenerator rng{(*(uint32_t *)&start_time) ^ seed};
+
+ compute_birth_times(settings.rate, emit_interval, state, r_birth_times);
+ if (r_birth_times.is_empty()) {
+ return;
+ }
+
+ state.last_birth_time = r_birth_times.last();
+
+ for (int i : r_birth_times.index_range()) {
+ UNUSED_VARS(i);
+ const int vertex_index = rng.get_int32() % mesh.totvert;
+ float3 vertex_position = mesh.mvert[vertex_index].co;
+ r_positions.append(local_to_world * vertex_position);
+ r_velocities.append(rng.get_unit_float3());
+ }
+}
+
+static EmitterSettings compute_settings(const fn::MultiFunction &inputs_fn,
+ ParticleEmitterContext &context)
+{
+ EmitterSettings parameters;
+
+ fn::MFContextBuilder mf_context;
+ mf_context.add_global_context("PersistentDataHandleMap", &context.solve_context().handle_map());
+
+ fn::MFParamsBuilder mf_params{inputs_fn, 1};
+ bke::PersistentObjectHandle object_handle;
+ mf_params.add_uninitialized_single_output(&object_handle, "Object");
+ mf_params.add_uninitialized_single_output(¶meters.rate, "Rate");
+
+ inputs_fn.call(IndexRange(1), mf_params, mf_context);
+
+ parameters.object = context.solve_context().handle_map().lookup(object_handle);
+ return parameters;
+}
+
+void ParticleMeshEmitter::emit(ParticleEmitterContext &context) const
+{
+ auto *state = context.lookup_state<ParticleMeshEmitterSimulationState>(own_state_name_);
+ if (state == nullptr) {
+ return;
+ }
+
+ EmitterSettings settings = compute_settings(inputs_fn_, context);
+
+ Vector<float3> new_positions;
+ Vector<float3> new_velocities;
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list