Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/simulation.cc')
-rw-r--r--source/blender/blenkernel/intern/simulation.cc308
1 files changed, 210 insertions, 98 deletions
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index 20a23ab8b38..c0fc8fcb464 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -31,6 +31,7 @@
#include "BLI_float3.hh"
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_rand.h"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -47,16 +48,36 @@
#include "BKE_pointcache.h"
#include "BKE_simulation.h"
+#include "NOD_node_tree_multi_function.hh"
#include "NOD_simulation.h"
+#include "BLI_map.hh"
#include "BLT_translation.h"
+#include "FN_attributes_ref.hh"
+#include "FN_multi_function_network_evaluation.hh"
+#include "FN_multi_function_network_optimization.hh"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-using blender::float3;
-using blender::MutableSpan;
-using blender::Span;
+#include "SIM_simulation_update.hh"
+
+using StateInitFunction = void (*)(SimulationState *state);
+using StateResetFunction = void (*)(SimulationState *state);
+using StateRemoveFunction = void (*)(SimulationState *state);
+using StateCopyFunction = void (*)(const SimulationState *src, SimulationState *dst);
+
+struct SimulationStateType {
+ const char *name;
+ int size;
+ StateInitFunction init;
+ StateResetFunction reset;
+ StateRemoveFunction remove;
+ StateCopyFunction copy;
+};
+
+static const SimulationStateType *try_get_state_type(blender::StringRefNull type_name);
static void simulation_init_data(ID *id)
{
@@ -67,20 +88,12 @@ static void simulation_init_data(ID *id)
bNodeTree *ntree = ntreeAddTree(nullptr, "Simulation Nodetree", ntreeType_Simulation->idname);
simulation->nodetree = ntree;
-
- /* Add a default particle simulation state for now. */
- ParticleSimulationState *state = (ParticleSimulationState *)MEM_callocN(
- sizeof(ParticleSimulationState), __func__);
- CustomData_reset(&state->attributes);
-
- state->point_cache = BKE_ptcache_add(&state->ptcaches);
- BLI_addtail(&simulation->states, state);
}
static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
{
Simulation *simulation_dst = (Simulation *)id_dst;
- Simulation *simulation_src = (Simulation *)id_src;
+ const Simulation *simulation_src = (const Simulation *)id_src;
/* We always need allocation of our private ID data. */
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
@@ -93,19 +106,14 @@ static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons
}
BLI_listbase_clear(&simulation_dst->states);
-
LISTBASE_FOREACH (const SimulationState *, state_src, &simulation_src->states) {
- switch ((eSimulationStateType)state_src->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state_dst = (ParticleSimulationState *)MEM_callocN(
- sizeof(ParticleSimulationState), __func__);
- CustomData_reset(&particle_state_dst->attributes);
-
- BLI_addtail(&simulation_dst->states, particle_state_dst);
- break;
- }
- }
+ SimulationState *state_dst = BKE_simulation_state_add(
+ simulation_dst, state_src->type, state_src->name);
+ BKE_simulation_state_copy_data(state_src, state_dst);
}
+
+ BLI_listbase_clear(&simulation_dst->dependencies);
+ BLI_duplicatelist(&simulation_dst->dependencies, &simulation_src->dependencies);
}
static void simulation_free_data(ID *id)
@@ -120,17 +128,9 @@ static void simulation_free_data(ID *id)
simulation->nodetree = nullptr;
}
- LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) {
- switch ((eSimulationStateType)state->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
- CustomData_free(&particle_state->attributes, particle_state->tot_particles);
- BKE_ptcache_free_list(&particle_state->ptcaches);
- break;
- }
- }
- MEM_freeN(state);
- }
+ BKE_simulation_state_remove_all(simulation);
+
+ BLI_freelistN(&simulation->dependencies);
}
static void simulation_foreach_id(ID *id, LibraryForeachIDData *data)
@@ -140,6 +140,9 @@ static void simulation_foreach_id(ID *id, LibraryForeachIDData *data)
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree);
}
+ LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) {
+ BKE_LIB_FOREACHID_PROCESS_ID(data, dependency->id, IDWALK_CB_USER);
+ }
}
IDTypeInfo IDType_ID_SIM = {
@@ -168,94 +171,203 @@ void *BKE_simulation_add(Main *bmain, const char *name)
return simulation;
}
-static MutableSpan<float3> get_particle_positions(ParticleSimulationState *state)
+SimulationState *BKE_simulation_state_add(Simulation *simulation,
+ const char *type,
+ const char *name)
{
- return MutableSpan<float3>(
- (float3 *)CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Position"),
- state->tot_particles);
+ BLI_assert(simulation != nullptr);
+ BLI_assert(name != nullptr);
+
+ const SimulationStateType *state_type = try_get_state_type(type);
+ BLI_assert(state_type != nullptr);
+
+ SimulationState *state = (SimulationState *)MEM_callocN(state_type->size, AT);
+ state->type = BLI_strdup(type);
+ state->name = BLI_strdup(name);
+
+ state_type->init(state);
+ BLI_addtail(&simulation->states, state);
+ return state;
}
-static void ensure_attributes_exist(ParticleSimulationState *state)
+void BKE_simulation_state_remove(Simulation *simulation, SimulationState *state)
{
- if (CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Position") == nullptr) {
- CustomData_add_layer_named(
- &state->attributes, CD_LOCATION, CD_CALLOC, nullptr, state->tot_particles, "Position");
- }
+ BLI_assert(simulation != nullptr);
+ BLI_assert(state != nullptr);
+ BLI_assert(BLI_findindex(&simulation->states, state) >= 0);
+
+ BLI_remlink(&simulation->states, state);
+ const SimulationStateType *state_type = try_get_state_type(state->type);
+ BLI_assert(state_type != nullptr);
+ state_type->remove(state);
+ MEM_freeN(state->name);
+ MEM_freeN(state->type);
+ MEM_freeN(state);
}
-static void copy_particle_state_to_cow(ParticleSimulationState *state_orig,
- ParticleSimulationState *state_cow)
+void BKE_simulation_state_remove_all(Simulation *simulation)
{
- ensure_attributes_exist(state_cow);
- CustomData_free(&state_cow->attributes, state_cow->tot_particles);
- CustomData_copy(&state_orig->attributes,
- &state_cow->attributes,
- CD_MASK_ALL,
- CD_DUPLICATE,
- state_orig->tot_particles);
- state_cow->current_frame = state_orig->current_frame;
- state_cow->tot_particles = state_orig->tot_particles;
+ BLI_assert(simulation != nullptr);
+
+ while (!BLI_listbase_is_empty(&simulation->states)) {
+ BKE_simulation_state_remove(simulation, (SimulationState *)simulation->states.first);
+ }
}
-void BKE_simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation)
+void BKE_simulation_state_reset(Simulation *UNUSED(simulation), SimulationState *state)
{
- int current_frame = scene->r.cfra;
+ BLI_assert(state != nullptr);
- ParticleSimulationState *state_cow = (ParticleSimulationState *)simulation->states.first;
- ParticleSimulationState *state_orig = (ParticleSimulationState *)state_cow->head.orig_state;
+ const SimulationStateType *state_type = try_get_state_type(state->type);
+ BLI_assert(state_type != nullptr);
+ state_type->reset(state);
+}
- if (current_frame == state_cow->current_frame) {
- return;
+void BKE_simulation_state_reset_all(Simulation *simulation)
+{
+ BLI_assert(simulation != nullptr);
+
+ LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ BKE_simulation_state_reset(simulation, state);
}
+}
- /* Number of particles should be stored in the cache, but for now assume it is constant. */
- state_cow->tot_particles = state_orig->tot_particles;
- CustomData_realloc(&state_cow->attributes, state_orig->tot_particles);
- ensure_attributes_exist(state_cow);
+void BKE_simulation_state_copy_data(const SimulationState *src_state, SimulationState *dst_state)
+{
+ BLI_assert(src_state != nullptr);
+ BLI_assert(dst_state != nullptr);
+ BLI_assert(STREQ(src_state->type, dst_state->type));
- PTCacheID pid_cow;
- BKE_ptcache_id_from_sim_particles(&pid_cow, state_cow);
- BKE_ptcache_id_time(&pid_cow, scene, current_frame, nullptr, nullptr, nullptr);
+ const SimulationStateType *state_type = try_get_state_type(src_state->type);
+ BLI_assert(state_type != nullptr);
+ state_type->copy(src_state, dst_state);
+}
- /* If successfull, this will read the state directly into the cow state. */
- int cache_result = BKE_ptcache_read(&pid_cow, current_frame, true);
- if (cache_result == PTCACHE_READ_EXACT) {
- state_cow->current_frame = current_frame;
- return;
+SimulationState *BKE_simulation_state_try_find_by_name(Simulation *simulation, const char *name)
+{
+ if (simulation == nullptr) {
+ return nullptr;
+ }
+ if (name == nullptr) {
+ return nullptr;
}
- /* Below we modify the original state/cache. Only the active depsgraph is allowed to do that. */
- if (!DEG_is_active(depsgraph)) {
- return;
+ LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ if (STREQ(state->name, name)) {
+ return state;
+ }
}
+ return nullptr;
+}
- PTCacheID pid_orig;
- BKE_ptcache_id_from_sim_particles(&pid_orig, state_orig);
- BKE_ptcache_id_time(&pid_orig, scene, current_frame, nullptr, nullptr, nullptr);
+SimulationState *BKE_simulation_state_try_find_by_name_and_type(Simulation *simulation,
+ const char *name,
+ const char *type)
+{
+ if (type == nullptr) {
+ return nullptr;
+ }
- if (current_frame == 1) {
- state_orig->tot_particles = 100;
- state_orig->current_frame = 1;
- CustomData_realloc(&state_orig->attributes, state_orig->tot_particles);
- ensure_attributes_exist(state_orig);
+ SimulationState *state = BKE_simulation_state_try_find_by_name(simulation, name);
+ if (state == nullptr) {
+ return nullptr;
+ }
+ if (STREQ(state->type, type)) {
+ return state;
+ }
+ return nullptr;
+}
- MutableSpan<float3> positions = get_particle_positions(state_orig);
- for (uint i : positions.index_range()) {
- positions[i] = {i / 10.0f, 0, 0};
- }
+void BKE_simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation)
+{
+ blender::sim::update_simulation_in_depsgraph(depsgraph, scene, simulation);
+}
- BKE_ptcache_write(&pid_orig, current_frame);
- copy_particle_state_to_cow(state_orig, state_cow);
+void BKE_simulation_update_dependencies(Simulation *simulation, Main *bmain)
+{
+ bool dependencies_changed = blender::sim::update_simulation_dependencies(simulation);
+ if (dependencies_changed) {
+ DEG_relations_tag_update(bmain);
}
- else if (current_frame == state_orig->current_frame + 1) {
- state_orig->current_frame = current_frame;
- ensure_attributes_exist(state_orig);
- MutableSpan<float3> positions = get_particle_positions(state_orig);
- for (float3 &position : positions) {
- position.z += 0.1f;
- }
+}
- BKE_ptcache_write(&pid_orig, current_frame);
- copy_particle_state_to_cow(state_orig, state_cow);
+using StateTypeMap = blender::Map<std::string, std::unique_ptr<SimulationStateType>>;
+
+template<typename T>
+static void add_state_type(StateTypeMap &map,
+ const char *name,
+ void (*init)(T *state),
+ void (*reset)(T *state),
+ void (*remove)(T *state),
+ void (*copy)(const T *src, T *dst))
+{
+ SimulationStateType state_type{
+ name,
+ (int)sizeof(T),
+ (StateInitFunction)init,
+ (StateResetFunction)reset,
+ (StateRemoveFunction)remove,
+ (StateCopyFunction)copy,
+ };
+ map.add_new(name, std::make_unique<SimulationStateType>(state_type));
+}
+
+static StateTypeMap init_state_types()
+{
+ StateTypeMap map;
+ add_state_type<ParticleSimulationState>(
+ map,
+ SIM_TYPE_NAME_PARTICLE_SIMULATION,
+ [](ParticleSimulationState *state) { CustomData_reset(&state->attributes); },
+ [](ParticleSimulationState *state) {
+ CustomData_free(&state->attributes, state->tot_particles);
+ state->tot_particles = 0;
+ state->next_particle_id = 0;
+ },
+ [](ParticleSimulationState *state) {
+ CustomData_free(&state->attributes, state->tot_particles);
+ },
+ [](const ParticleSimulationState *src, ParticleSimulationState *dst) {
+ CustomData_free(&dst->attributes, dst->tot_particles);
+ dst->tot_particles = src->tot_particles;
+ dst->next_particle_id = src->next_particle_id;
+ CustomData_copy(
+ &src->attributes, &dst->attributes, CD_MASK_ALL, CD_DUPLICATE, src->tot_particles);
+ });
+
+ add_state_type<ParticleMeshEmitterSimulationState>(
+ map,
+ SIM_TYPE_NAME_PARTICLE_MESH_EMITTER,
+ [](ParticleMeshEmitterSimulationState *UNUSED(state)) {},
+ [](ParticleMeshEmitterSimulationState *state) { state->last_birth_time = 0.0f; },
+ [](ParticleMeshEmitterSimulationState *UNUSED(state)) {},
+ [](const ParticleMeshEmitterSimulationState *src, ParticleMeshEmitterSimulationState *dst) {
+ dst->last_birth_time = src->last_birth_time;
+ });
+ return map;
+}
+
+static StateTypeMap &get_state_types()
+{
+ static StateTypeMap state_type_map = init_state_types();
+ return state_type_map;
+}
+
+static const SimulationStateType *try_get_state_type(blender::StringRefNull type_name)
+{
+ std::unique_ptr<SimulationStateType> *type = get_state_types().lookup_ptr_as(type_name);
+ if (type == nullptr) {
+ return nullptr;
}
+ return type->get();
+}
+
+template<> const char *BKE_simulation_get_state_type_name<ParticleSimulationState>()
+{
+ return SIM_TYPE_NAME_PARTICLE_SIMULATION;
+}
+
+template<> const char *BKE_simulation_get_state_type_name<ParticleMeshEmitterSimulationState>()
+{
+ return SIM_TYPE_NAME_PARTICLE_MESH_EMITTER;
}