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:
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h5
-rw-r--r--source/blender/blenkernel/BKE_simulation.h15
-rw-r--r--source/blender/blenkernel/intern/pointcache.c87
-rw-r--r--source/blender/blenkernel/intern/simulation.cc277
-rw-r--r--source/blender/blenloader/intern/readfile.c12
-rw-r--r--source/blender/blenloader/intern/writefile.c48
-rw-r--r--source/blender/makesdna/DNA_simulation_types.h23
-rw-r--r--source/blender/modifiers/intern/MOD_simulation.cc16
-rw-r--r--source/blender/simulation/intern/simulation_collect_influences.cc51
-rw-r--r--source/blender/simulation/intern/simulation_collect_influences.hh35
-rw-r--r--source/blender/simulation/intern/simulation_solver.cc15
-rw-r--r--source/blender/simulation/intern/simulation_solver.hh57
-rw-r--r--source/blender/simulation/intern/simulation_update.cc85
13 files changed, 426 insertions, 300 deletions
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index a9abe2d0f6d..dc99ec7f56f 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -86,12 +86,10 @@ struct ListBase;
struct Main;
struct Object;
struct ParticleKey;
-struct ParticleSimulationState;
struct ParticleSystem;
struct PointCache;
struct RigidBodyWorld;
struct Scene;
-struct Simulation;
struct SoftBody;
struct ViewLayer;
@@ -296,9 +294,6 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid,
struct Object *ob,
struct DynamicPaintSurface *surface);
void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw);
-void BKE_ptcache_id_from_sim_particles(PTCacheID *pid,
- struct ParticleSimulationState *state_orig,
- struct ParticleSimulationState *state_cow);
PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache);
void BKE_ptcache_ids_from_object(struct ListBase *lb,
diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h
index 36f4122f4dc..5aa71b6381d 100644
--- a/source/blender/blenkernel/BKE_simulation.h
+++ b/source/blender/blenkernel/BKE_simulation.h
@@ -34,13 +34,26 @@ void BKE_simulation_data_update(struct Depsgraph *depsgraph,
struct Simulation *simulation);
SimulationState *BKE_simulation_state_add(Simulation *simulation,
- eSimulationStateType type,
+ const char *type,
const char *name);
void BKE_simulation_state_remove(Simulation *simulation, SimulationState *state);
void BKE_simulation_state_remove_all(Simulation *simulation);
+void BKE_simulation_state_reset(Simulation *simulation, SimulationState *state);
+void BKE_simulation_state_reset_all(Simulation *simulation);
+SimulationState *BKE_simulation_state_try_find_by_name(Simulation *simulation, const char *name);
+SimulationState *BKE_simulation_state_try_find_by_name_and_type(Simulation *simulation,
+ const char *name,
+ const char *type);
+void BKE_simulation_state_copy_data(const SimulationState *src_state, SimulationState *dst_state);
#ifdef __cplusplus
}
#endif
+#ifdef __cplusplus
+
+template<typename StateType> const char *BKE_simulation_get_state_type_name();
+
+#endif
+
#endif /* __BKE_SIMULATION_H__ */
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index aa93c6cb854..4b09f7542c7 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1885,81 +1885,6 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->file_type = PTCACHE_FILE_PTCACHE;
}
-static int ptcache_sim_particle_totpoint(void *state_v, int UNUSED(cfra))
-{
- ParticleSimulationState *state = (ParticleSimulationState *)state_v;
- return state->tot_particles;
-}
-
-static void ptcache_sim_particle_error(void *UNUSED(state_v), const char *UNUSED(message))
-{
-}
-
-static int ptcache_sim_particle_write(int index, void *state_v, void **data, int UNUSED(cfra))
-{
- ParticleSimulationState *state = (ParticleSimulationState *)state_v;
-
- const float *positions = (const float *)CustomData_get_layer_named(
- &state->attributes, CD_PROP_FLOAT3, "Position");
-
- PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, positions + (index * 3));
-
- return 1;
-}
-static void ptcache_sim_particle_read(
- int index, void *state_v, void **data, float UNUSED(cfra), const float *UNUSED(old_data))
-{
- ParticleSimulationState *state = (ParticleSimulationState *)state_v;
-
- BLI_assert(index < state->tot_particles);
- float *positions = (float *)CustomData_get_layer_named(
- &state->attributes, CD_PROP_FLOAT3, "Position");
-
- PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, positions + (index * 3));
-}
-
-void BKE_ptcache_id_from_sim_particles(PTCacheID *pid,
- ParticleSimulationState *state_orig,
- ParticleSimulationState *state_cow)
-{
- memset(pid, 0, sizeof(PTCacheID));
-
- pid->calldata = state_cow;
- pid->type = PTCACHE_TYPE_SIM_PARTICLES;
- pid->cache = state_orig->point_cache;
- pid->cache_ptr = &state_orig->point_cache;
- pid->ptcaches = &state_orig->ptcaches;
- pid->totpoint = ptcache_sim_particle_totpoint;
- pid->totwrite = ptcache_sim_particle_totpoint;
- pid->error = ptcache_sim_particle_error;
-
- pid->write_point = ptcache_sim_particle_write;
- pid->read_point = ptcache_sim_particle_read;
- pid->interpolate_point = NULL;
-
- pid->write_stream = NULL;
- pid->read_stream = NULL;
-
- pid->write_openvdb_stream = NULL;
- pid->read_openvdb_stream = NULL;
-
- pid->write_extra_data = NULL;
- pid->read_extra_data = NULL;
- pid->interpolate_extra_data = NULL;
-
- pid->write_header = NULL;
- pid->read_header = NULL;
-
- pid->data_types = 1 << BPHYS_DATA_LOCATION;
- pid->info_types = 0;
-
- pid->stack_index = 0;
-
- pid->default_step = 1;
- pid->max_step = 1;
- pid->file_type = PTCACHE_FILE_PTCACHE;
-}
-
/**
* \param ob: Optional, may be NULL.
* \param scene: Optional may be NULL.
@@ -2059,17 +1984,7 @@ static bool foreach_object_modifier_ptcache(Object *object,
}
}
else if (md->type == eModifierType_Simulation) {
- SimulationModifierData *smd = (SimulationModifierData *)md;
- if (smd->simulation) {
- LISTBASE_FOREACH (SimulationState *, state, &smd->simulation->states) {
- switch ((eSimulationStateType)state->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- /* TODO(jacques) */
- break;
- }
- }
- }
- }
+ /* TODO(jacques) */
}
}
return true;
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index 1f11869e21c..95340e4e29c 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -51,6 +51,7 @@
#include "NOD_node_tree_multi_function.hh"
#include "NOD_simulation.h"
+#include "BLI_map.hh"
#include "BLT_translation.h"
#include "FN_attributes_ref.hh"
@@ -62,6 +63,22 @@
#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)
{
Simulation *simulation = (Simulation *)id;
@@ -76,7 +93,7 @@ static void simulation_init_data(ID *id)
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;
@@ -89,76 +106,16 @@ 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) {
+ 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_duplicatelist(&simulation_dst->persistent_data_handles,
&simulation_src->persistent_data_handles);
}
-static void free_simulation_state_head(SimulationState *state)
-{
- MEM_freeN(state->name);
-}
-
-static void free_particle_simulation_state(ParticleSimulationState *state)
-{
- free_simulation_state_head(&state->head);
- CustomData_free(&state->attributes, state->tot_particles);
- BKE_ptcache_free_list(&state->ptcaches);
- MEM_freeN(state);
-}
-
-SimulationState *BKE_simulation_state_add(Simulation *simulation,
- eSimulationStateType type,
- const char *name)
-{
- BLI_assert(simulation != nullptr);
- BLI_assert(name != nullptr);
-
- bool is_cow_simulation = DEG_is_evaluated_id(&simulation->id);
-
- switch (type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *state = (ParticleSimulationState *)MEM_callocN(sizeof(*state), AT);
- state->head.type = SIM_STATE_TYPE_PARTICLES;
- state->head.name = BLI_strdup(name);
- CustomData_reset(&state->attributes);
-
- if (!is_cow_simulation) {
- state->point_cache = BKE_ptcache_add(&state->ptcaches);
- }
-
- BLI_addtail(&simulation->states, state);
- return &state->head;
- }
- }
-
- BLI_assert(false);
- return nullptr;
-}
-
-void BKE_simulation_state_remove(Simulation *simulation, SimulationState *state)
-{
- BLI_assert(simulation != nullptr);
- BLI_assert(state != nullptr);
- BLI_assert(BLI_findindex(&simulation->states, state) >= 0);
-
- BLI_remlink(&simulation->states, state);
- switch ((eSimulationStateType)state->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- free_particle_simulation_state((ParticleSimulationState *)state);
- break;
- }
- }
-}
-
-void BKE_simulation_state_remove_all(Simulation *simulation)
-{
- BLI_assert(simulation != nullptr);
- while (!BLI_listbase_is_empty(&simulation->states)) {
- BKE_simulation_state_remove(simulation, (SimulationState *)simulation->states.first);
- }
-}
-
static void simulation_free_data(ID *id)
{
Simulation *simulation = (Simulation *)id;
@@ -215,7 +172,195 @@ void *BKE_simulation_add(Main *bmain, const char *name)
return simulation;
}
+SimulationState *BKE_simulation_state_add(Simulation *simulation,
+ const char *type,
+ const char *name)
+{
+ 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;
+}
+
+void BKE_simulation_state_remove(Simulation *simulation, SimulationState *state)
+{
+ 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);
+}
+
+void BKE_simulation_state_remove_all(Simulation *simulation)
+{
+ BLI_assert(simulation != nullptr);
+
+ while (!BLI_listbase_is_empty(&simulation->states)) {
+ BKE_simulation_state_remove(simulation, (SimulationState *)simulation->states.first);
+ }
+}
+
+void BKE_simulation_state_reset(Simulation *UNUSED(simulation), SimulationState *state)
+{
+ BLI_assert(state != nullptr);
+
+ const SimulationStateType *state_type = try_get_state_type(state->type);
+ BLI_assert(state_type != nullptr);
+ state_type->reset(state);
+}
+
+void BKE_simulation_state_reset_all(Simulation *simulation)
+{
+ BLI_assert(simulation != nullptr);
+
+ LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ BKE_simulation_state_reset(simulation, state);
+ }
+}
+
+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));
+
+ const SimulationStateType *state_type = try_get_state_type(src_state->type);
+ BLI_assert(state_type != nullptr);
+ state_type->copy(src_state, dst_state);
+}
+
+SimulationState *BKE_simulation_state_try_find_by_name(Simulation *simulation, const char *name)
+{
+ if (simulation == nullptr) {
+ return nullptr;
+ }
+ if (name == nullptr) {
+ return nullptr;
+ }
+
+ LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ if (STREQ(state->name, name)) {
+ return state;
+ }
+ }
+ return nullptr;
+}
+
+SimulationState *BKE_simulation_state_try_find_by_name_and_type(Simulation *simulation,
+ const char *name,
+ const char *type)
+{
+ if (type == nullptr) {
+ return nullptr;
+ }
+
+ 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;
+}
+
void BKE_simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation)
{
blender::sim::update_simulation_in_depsgraph(depsgraph, scene, simulation);
}
+
+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;
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index f443859e62c..9320187f2a0 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8691,14 +8691,10 @@ static void direct_link_simulation(BlendDataReader *reader, Simulation *simulati
BLO_read_list(reader, &simulation->states);
LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
BLO_read_data_address(reader, &state->name);
- switch ((eSimulationStateType)state->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
- direct_link_customdata(reader, &particle_state->attributes, particle_state->tot_particles);
- direct_link_pointcache_list(
- reader, &particle_state->ptcaches, &particle_state->point_cache, 0);
- break;
- };
+ BLO_read_data_address(reader, &state->type);
+ if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) {
+ ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
+ direct_link_customdata(reader, &particle_state->attributes, particle_state->tot_particles);
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index d33d8032ed1..46ac6b43c92 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -3833,31 +3833,33 @@ static void write_simulation(BlendWriter *writer, Simulation *simulation, const
LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
BLO_write_string(writer, state->name);
- switch ((eSimulationStateType)state->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
- BLO_write_struct(writer, ParticleSimulationState, particle_state);
-
- CustomDataLayer *layers = NULL;
- CustomDataLayer layers_buff[CD_TEMP_CHUNK_SIZE];
- CustomData_file_write_prepare(
- &particle_state->attributes, &layers, layers_buff, ARRAY_SIZE(layers_buff));
-
- write_customdata(writer,
- &simulation->id,
- particle_state->tot_particles,
- &particle_state->attributes,
- layers,
- CD_MASK_ALL);
-
- if (layers != NULL && layers != layers_buff) {
- MEM_freeN(layers);
- }
-
- write_pointcaches(writer, &particle_state->ptcaches);
- break;
+ BLO_write_string(writer, state->type);
+ /* TODO: Decentralize this part. */
+ if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) {
+ ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
+ BLO_write_struct(writer, ParticleSimulationState, particle_state);
+
+ CustomDataLayer *layers = NULL;
+ CustomDataLayer layers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomData_file_write_prepare(
+ &particle_state->attributes, &layers, layers_buff, ARRAY_SIZE(layers_buff));
+
+ write_customdata(writer,
+ &simulation->id,
+ particle_state->tot_particles,
+ &particle_state->attributes,
+ layers,
+ CD_MASK_ALL);
+
+ if (layers != NULL && layers != layers_buff) {
+ MEM_freeN(layers);
}
}
+ else if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER)) {
+ ParticleMeshEmitterSimulationState *emitter_state = (ParticleMeshEmitterSimulationState *)
+ state;
+ BLO_write_struct(writer, ParticleMeshEmitterSimulationState, emitter_state);
+ }
}
BLO_write_struct_list(writer, PersistentDataHandleItem, &simulation->persistent_data_handles);
diff --git a/source/blender/makesdna/DNA_simulation_types.h b/source/blender/makesdna/DNA_simulation_types.h
index f7a7f94da53..5bb0e50e089 100644
--- a/source/blender/makesdna/DNA_simulation_types.h
+++ b/source/blender/makesdna/DNA_simulation_types.h
@@ -46,10 +46,7 @@ typedef struct SimulationState {
struct SimulationState *next;
struct SimulationState *prev;
- /** eSimulationStateType */
- int type;
- int _pad;
-
+ char *type;
char *name;
} SimulationState;
@@ -60,13 +57,15 @@ typedef struct ParticleSimulationState {
int tot_particles;
int next_particle_id;
struct CustomData attributes;
-
- /** Caches the state of the particles over time. The cache only exists on the original data
- * block, not on cow copies. */
- struct PointCache *point_cache;
- struct ListBase ptcaches;
} ParticleSimulationState;
+typedef struct ParticleMeshEmitterSimulationState {
+ SimulationState head;
+
+ float last_birth_time;
+ char _pad[4];
+} ParticleMeshEmitterSimulationState;
+
/** Stores a mapping between an integer handle and a corresponding ID data block. */
typedef struct PersistentDataHandleItem {
struct PersistentDataHandleItem *next;
@@ -81,9 +80,7 @@ enum {
SIM_DS_EXPAND = (1 << 0),
};
-/* SimulationCache.type */
-typedef enum eSimulationStateType {
- SIM_STATE_TYPE_PARTICLES = 0,
-} eSimulationStateType;
+#define SIM_TYPE_NAME_PARTICLE_SIMULATION "Particle Simulation"
+#define SIM_TYPE_NAME_PARTICLE_MESH_EMITTER "Particle Mesh Emitter"
#endif /* __DNA_SIMULATION_TYPES_H__ */
diff --git a/source/blender/modifiers/intern/MOD_simulation.cc b/source/blender/modifiers/intern/MOD_simulation.cc
index 819ed320255..d9cc9840e08 100644
--- a/source/blender/modifiers/intern/MOD_simulation.cc
+++ b/source/blender/modifiers/intern/MOD_simulation.cc
@@ -93,20 +93,8 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
static const ParticleSimulationState *find_particle_state(SimulationModifierData *smd)
{
- if (smd->simulation == nullptr) {
- return nullptr;
- }
- if (smd->data_path == nullptr) {
- return nullptr;
- }
- LISTBASE_FOREACH (const SimulationState *, state, &smd->simulation->states) {
- if (STREQ(smd->data_path, state->name)) {
- if (state->type == SIM_STATE_TYPE_PARTICLES) {
- return (ParticleSimulationState *)state;
- }
- }
- }
- return nullptr;
+ return (const ParticleSimulationState *)BKE_simulation_state_try_find_by_name_and_type(
+ smd->simulation, smd->data_path, SIM_TYPE_NAME_PARTICLE_SIMULATION);
}
static PointCloud *modifyPointCloud(ModifierData *md,
diff --git a/source/blender/simulation/intern/simulation_collect_influences.cc b/source/blender/simulation/intern/simulation_collect_influences.cc
index 4760063daca..764e587d157 100644
--- a/source/blender/simulation/intern/simulation_collect_influences.cc
+++ b/source/blender/simulation/intern/simulation_collect_influences.cc
@@ -280,17 +280,30 @@ static void collect_forces(nodes::MFNetworkTreeMap &network_map,
class MyBasicEmitter : public ParticleEmitter {
private:
Array<std::string> names_;
+ std::string my_state_;
const fn::MultiFunction &inputs_fn_;
uint32_t seed_;
public:
- MyBasicEmitter(Array<std::string> names, const fn::MultiFunction &inputs_fn, uint32_t seed)
- : names_(std::move(names)), inputs_fn_(inputs_fn), seed_(seed)
+ MyBasicEmitter(Array<std::string> names,
+ std::string my_state,
+ const fn::MultiFunction &inputs_fn,
+ uint32_t seed)
+ : names_(std::move(names)),
+ my_state_(std::move(my_state)),
+ inputs_fn_(inputs_fn),
+ seed_(seed)
{
}
void emit(ParticleEmitterContext &context) const override
{
+ auto *state = context.solve_context().state_map().lookup<ParticleMeshEmitterSimulationState>(
+ my_state_);
+ if (state == nullptr) {
+ return;
+ }
+
fn::MFContextBuilder mf_context;
mf_context.add_global_context("PersistentDataHandleMap",
&context.solve_context().handle_map());
@@ -311,15 +324,17 @@ class MyBasicEmitter : public ParticleEmitter {
Vector<float3> new_velocities;
Vector<float> new_birth_times;
- float start_time = context.simulation_time_interval().start();
+ TimeInterval time_interval = context.simulation_time_interval();
+ float start_time = time_interval.start();
RandomNumberGenerator rng{(*(uint32_t *)&start_time) ^ seed_};
- int amount = rate * 10;
- for (int i : IndexRange(amount)) {
- UNUSED_VARS(i);
+ const float time_between_particles = 1.0f / rate;
+ while (state->last_birth_time + time_between_particles < time_interval.end()) {
new_positions.append(rng.get_unit_float3() * 0.3 + float3(object->loc));
new_velocities.append(rng.get_unit_float3());
- new_birth_times.append(context.simulation_time_interval().start());
+ const float birth_time = state->last_birth_time + time_between_particles;
+ new_birth_times.append(birth_time);
+ state->last_birth_time = birth_time;
}
for (StringRef name : names_) {
@@ -328,6 +343,7 @@ class MyBasicEmitter : public ParticleEmitter {
return;
}
+ int amount = new_positions.size();
fn::MutableAttributesRef attributes = allocator->allocate(amount);
initialized_copy_n(new_positions.data(), amount, attributes.get<float3>("Position").data());
@@ -352,7 +368,8 @@ static Vector<const nodes::DNode *> find_linked_particle_simulations(
static ParticleEmitter *create_particle_emitter(const nodes::DNode &dnode,
ResourceCollector &resources,
- nodes::MFNetworkTreeMap &network_map)
+ nodes::MFNetworkTreeMap &network_map,
+ RequiredStates &r_required_states)
{
Vector<const nodes::DNode *> simulation_dnodes = find_linked_particle_simulations(
dnode.output(0));
@@ -377,19 +394,23 @@ static ParticleEmitter *create_particle_emitter(const nodes::DNode &dnode,
fn::MultiFunction &inputs_fn = resources.construct<fn::MFNetworkEvaluator>(
AT, Span<const fn::MFOutputSocket *>(), input_sockets.as_span());
- uint32_t seed = DefaultHash<std::string>{}(dnode_to_path(dnode));
+ std::string my_state_name = dnode_to_path(dnode);
+ r_required_states.add(my_state_name, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER);
+ uint32_t seed = DefaultHash<std::string>{}(my_state_name);
ParticleEmitter &emitter = resources.construct<MyBasicEmitter>(
- AT, std::move(names), inputs_fn, seed);
+ AT, std::move(names), std::move(my_state_name), inputs_fn, seed);
return &emitter;
}
static void collect_emitters(nodes::MFNetworkTreeMap &network_map,
ResourceCollector &resources,
- SimulationInfluences &r_influences)
+ SimulationInfluences &r_influences,
+ RequiredStates &r_required_states)
{
for (const nodes::DNode *dnode :
network_map.tree().nodes_by_type("SimulationNodeParticleMeshEmitter")) {
- ParticleEmitter *emitter = create_particle_emitter(*dnode, resources, network_map);
+ ParticleEmitter *emitter = create_particle_emitter(
+ *dnode, resources, network_map, r_required_states);
if (emitter != nullptr) {
r_influences.particle_emitters.append(emitter);
}
@@ -433,7 +454,7 @@ static void find_used_data_blocks(const nodes::DerivedNodeTree &tree,
void collect_simulation_influences(Simulation &simulation,
ResourceCollector &resources,
SimulationInfluences &r_influences,
- SimulationStatesInfo &r_states_info)
+ RequiredStates &r_required_states)
{
nodes::NodeTreeRefMap tree_refs;
const nodes::DerivedNodeTree tree{simulation.nodetree, tree_refs};
@@ -452,10 +473,10 @@ void collect_simulation_influences(Simulation &simulation,
// WM_clipboard_text_set(network.to_dot().c_str(), false);
collect_forces(network_map, resources, data_sources, r_influences);
- collect_emitters(network_map, resources, r_influences);
+ collect_emitters(network_map, resources, r_influences, r_required_states);
for (const nodes::DNode *dnode : get_particle_simulation_nodes(tree)) {
- r_states_info.particle_simulation_names.add(dnode_to_path(*dnode));
+ r_required_states.add(dnode_to_path(*dnode), SIM_TYPE_NAME_PARTICLE_SIMULATION);
}
find_used_data_blocks(tree, r_influences);
diff --git a/source/blender/simulation/intern/simulation_collect_influences.hh b/source/blender/simulation/intern/simulation_collect_influences.hh
index cca396ffa66..42cbea6977e 100644
--- a/source/blender/simulation/intern/simulation_collect_influences.hh
+++ b/source/blender/simulation/intern/simulation_collect_influences.hh
@@ -25,14 +25,43 @@
namespace blender::sim {
-struct SimulationStatesInfo {
- VectorSet<std::string> particle_simulation_names;
+class RequiredStates {
+ private:
+ Map<std::string, const char *> state_type_by_state_name_;
+
+ public:
+ void add(std::string state_name, const char *state_type)
+ {
+ BLI_assert(state_type != nullptr);
+ const char *type_name = state_type_by_state_name_.lookup_default(state_name, nullptr);
+ if (type_name != nullptr) {
+ if (!STREQ(state_type, type_name)) {
+ std::cout << "Warning: Tried to have two different states with the same name.\n";
+ std::cout << " Name: " << state_name << "\n";
+ std::cout << " Type 1: " << state_type << "\n";
+ std::cout << " Type 2: " << type_name << "\n";
+ }
+ return;
+ }
+
+ state_type_by_state_name_.add(std::move(state_name), state_type);
+ }
+
+ const Map<std::string, const char *> &states() const
+ {
+ return state_type_by_state_name_;
+ }
+
+ bool is_required(StringRef state_name, StringRef state_type) const
+ {
+ return state_type_by_state_name_.lookup_default_as(state_name, "") == state_type;
+ }
};
void collect_simulation_influences(Simulation &simulation,
ResourceCollector &resources,
SimulationInfluences &r_influences,
- SimulationStatesInfo &r_states_info);
+ RequiredStates &r_required_states);
} // namespace blender::sim
diff --git a/source/blender/simulation/intern/simulation_solver.cc b/source/blender/simulation/intern/simulation_solver.cc
index 158c50957df..ee7a8d40035 100644
--- a/source/blender/simulation/intern/simulation_solver.cc
+++ b/source/blender/simulation/intern/simulation_solver.cc
@@ -312,20 +312,21 @@ void solve_simulation_time_step(Simulation &simulation,
handle_map.add(handle->handle, *handle->id);
}
+ SimulationStateMap state_map;
+ LISTBASE_FOREACH (SimulationState *, state, &simulation.states) {
+ state_map.add(state);
+ }
+
SimulationSolveContext solve_context{simulation,
depsgraph,
influences,
TimeInterval(simulation.current_simulation_time, time_step),
+ state_map,
handle_map};
TimeInterval simulation_time_interval{simulation.current_simulation_time, time_step};
- Vector<SimulationState *> simulation_states{simulation.states};
- Vector<ParticleSimulationState *> particle_simulation_states;
- for (SimulationState *state : simulation_states) {
- if (state->type == SIM_STATE_TYPE_PARTICLES) {
- particle_simulation_states.append((ParticleSimulationState *)state);
- }
- }
+ Span<ParticleSimulationState *> particle_simulation_states =
+ state_map.lookup<ParticleSimulationState>();
Map<std::string, std::unique_ptr<fn::AttributesInfo>> attribute_infos;
Map<std::string, std::unique_ptr<ParticleAllocator>> particle_allocators_map;
diff --git a/source/blender/simulation/intern/simulation_solver.hh b/source/blender/simulation/intern/simulation_solver.hh
index 1d1b9935661..2dc0921ad9e 100644
--- a/source/blender/simulation/intern/simulation_solver.hh
+++ b/source/blender/simulation/intern/simulation_solver.hh
@@ -25,6 +25,7 @@
#include "FN_attributes_ref.hh"
#include "BKE_persistent_data_handle.hh"
+#include "BKE_simulation.h"
#include "particle_allocator.hh"
#include "time_interval.hh"
@@ -55,12 +56,61 @@ struct SimulationInfluences {
VectorSet<ID *> used_data_blocks;
};
+class SimulationStateMap {
+ private:
+ Map<StringRefNull, SimulationState *> states_by_name_;
+ Map<StringRefNull, Vector<SimulationState *>> states_by_type_;
+
+ public:
+ void add(SimulationState *state)
+ {
+ states_by_name_.add_new(state->name, state);
+ states_by_type_.lookup_or_add_default(state->type).append(state);
+ }
+
+ template<typename StateType> StateType *lookup(StringRef name) const
+ {
+ const char *type = BKE_simulation_get_state_type_name<StateType>();
+ return (StateType *)this->lookup_name_type(name, type);
+ }
+
+ template<typename StateType> Span<StateType *> lookup() const
+ {
+ const char *type = BKE_simulation_get_state_type_name<StateType>();
+ return this->lookup_type(type).cast<StateType *>();
+ }
+
+ SimulationState *lookup_name_type(StringRef name, StringRef type) const
+ {
+ SimulationState *state = states_by_name_.lookup_default_as(name, nullptr);
+ if (state == nullptr) {
+ return nullptr;
+ }
+ if (state->type == type) {
+ return state;
+ }
+ return nullptr;
+ }
+
+ Span<SimulationState *> lookup_type(StringRef type) const
+ {
+ const Vector<SimulationState *> *states = states_by_type_.lookup_ptr_as(type);
+ if (states == nullptr) {
+ return {};
+ }
+ else {
+ return states->as_span();
+ }
+ }
+};
+
class SimulationSolveContext {
private:
Simulation &simulation_;
Depsgraph &depsgraph_;
const SimulationInfluences &influences_;
TimeInterval solve_interval_;
+ const SimulationStateMap &state_map_;
const bke::PersistentDataHandleMap &id_handle_map_;
public:
@@ -68,11 +118,13 @@ class SimulationSolveContext {
Depsgraph &depsgraph,
const SimulationInfluences &influences,
TimeInterval solve_interval,
+ const SimulationStateMap &state_map,
const bke::PersistentDataHandleMap &handle_map)
: simulation_(simulation),
depsgraph_(depsgraph),
influences_(influences),
solve_interval_(solve_interval),
+ state_map_(state_map),
id_handle_map_(handle_map)
{
}
@@ -91,6 +143,11 @@ class SimulationSolveContext {
{
return id_handle_map_;
}
+
+ const SimulationStateMap &state_map() const
+ {
+ return state_map_;
+ }
};
class ParticleAllocators {
diff --git a/source/blender/simulation/intern/simulation_update.cc b/source/blender/simulation/intern/simulation_update.cc
index 5328304863b..09219e0238f 100644
--- a/source/blender/simulation/intern/simulation_update.cc
+++ b/source/blender/simulation/intern/simulation_update.cc
@@ -37,88 +37,55 @@
namespace blender::sim {
-static void copy_states_to_cow(Simulation *simulation_orig, Simulation *simulation_cow)
+static void copy_states_to_cow(const Simulation *simulation_orig, Simulation *simulation_cow)
{
BKE_simulation_state_remove_all(simulation_cow);
simulation_cow->current_frame = simulation_orig->current_frame;
- LISTBASE_FOREACH (SimulationState *, state_orig, &simulation_orig->states) {
- switch ((eSimulationStateType)state_orig->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state_orig = (ParticleSimulationState *)state_orig;
- ParticleSimulationState *particle_state_cow = (ParticleSimulationState *)
- BKE_simulation_state_add(simulation_cow, SIM_STATE_TYPE_PARTICLES, state_orig->name);
- particle_state_cow->tot_particles = particle_state_orig->tot_particles;
- CustomData_copy(&particle_state_orig->attributes,
- &particle_state_cow->attributes,
- CD_MASK_ALL,
- CD_DUPLICATE,
- particle_state_orig->tot_particles);
- break;
- }
- }
+ LISTBASE_FOREACH (const SimulationState *, state_orig, &simulation_orig->states) {
+ SimulationState *state_cow = BKE_simulation_state_add(
+ simulation_cow, state_orig->type, state_orig->name);
+ BKE_simulation_state_copy_data(state_orig, state_cow);
}
}
-static void remove_unused_states(Simulation *simulation, const VectorSet<std::string> &state_names)
+static void remove_unused_states(Simulation *simulation, const RequiredStates &required_states)
{
LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) {
- if (!state_names.contains(state->name)) {
+ if (!required_states.is_required(state->name, state->type)) {
BKE_simulation_state_remove(simulation, state);
}
}
}
-static void reset_states(Simulation *simulation)
+static void add_missing_states(Simulation *simulation, const RequiredStates &required_states)
{
- LISTBASE_FOREACH (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);
- particle_state->tot_particles = 0;
- break;
- }
- }
- }
-}
+ for (auto &&item : required_states.states().items()) {
+ const char *name = item.key.c_str();
+ const char *type = item.value;
-static SimulationState *try_find_state_by_name(Simulation *simulation, StringRef name)
-{
- LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
- if (state->name == name) {
- return state;
- }
- }
- return nullptr;
-}
+ SimulationState *state = BKE_simulation_state_try_find_by_name_and_type(
+ simulation, name, type);
-static void add_missing_particle_states(Simulation *simulation, Span<std::string> state_names)
-{
- for (StringRefNull name : state_names) {
- SimulationState *state = try_find_state_by_name(simulation, name);
- if (state != nullptr) {
- BLI_assert(state->type == SIM_STATE_TYPE_PARTICLES);
- continue;
+ if (state == nullptr) {
+ BKE_simulation_state_add(simulation, type, name);
}
-
- BKE_simulation_state_add(simulation, SIM_STATE_TYPE_PARTICLES, name.c_str());
}
}
static void reinitialize_empty_simulation_states(Simulation *simulation,
- const SimulationStatesInfo &states_info)
+ const RequiredStates &required_states)
{
- remove_unused_states(simulation, states_info.particle_simulation_names);
- reset_states(simulation);
- add_missing_particle_states(simulation, states_info.particle_simulation_names);
+ remove_unused_states(simulation, required_states);
+ BKE_simulation_state_reset_all(simulation);
+ add_missing_states(simulation, required_states);
}
static void update_simulation_state_list(Simulation *simulation,
- const SimulationStatesInfo &states_info)
+ const RequiredStates &required_states)
{
- remove_unused_states(simulation, states_info.particle_simulation_names);
- add_missing_particle_states(simulation, states_info.particle_simulation_names);
+ remove_unused_states(simulation, required_states);
+ add_missing_states(simulation, required_states);
}
void update_simulation_in_depsgraph(Depsgraph *depsgraph,
@@ -139,13 +106,13 @@ void update_simulation_in_depsgraph(Depsgraph *depsgraph,
ResourceCollector resources;
SimulationInfluences influences;
- SimulationStatesInfo states_info;
+ RequiredStates required_states;
/* TODO: Use simulation_cow, but need to add depsgraph relations before that. */
- collect_simulation_influences(*simulation_orig, resources, influences, states_info);
+ collect_simulation_influences(*simulation_orig, resources, influences, required_states);
if (current_frame == 1) {
- reinitialize_empty_simulation_states(simulation_orig, states_info);
+ reinitialize_empty_simulation_states(simulation_orig, required_states);
initialize_simulation_states(*simulation_orig, *depsgraph, influences);
simulation_orig->current_frame = 1;
@@ -153,7 +120,7 @@ void update_simulation_in_depsgraph(Depsgraph *depsgraph,
copy_states_to_cow(simulation_orig, simulation_cow);
}
else if (current_frame == simulation_orig->current_frame + 1) {
- update_simulation_state_list(simulation_orig, states_info);
+ update_simulation_state_list(simulation_orig, required_states);
float time_step = 1.0f / 24.0f;
solve_simulation_time_step(*simulation_orig, *depsgraph, influences, time_step);