diff options
Diffstat (limited to 'source/blender/blenkernel/intern/simulation.cc')
-rw-r--r-- | source/blender/blenkernel/intern/simulation.cc | 308 |
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; } |