diff options
51 files changed, 24 insertions, 4651 deletions
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index 8ac1262645b..0f4eb8a8507 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -573,63 +573,9 @@ class QuickLiquid(Operator): return {'FINISHED'} - -class QuickParticles(Operator): - """Use active object as particle emitter""" - bl_idname = "object.quick_particles" - bl_label = "Quick Particles" - - @classmethod - def poll(cls, context): - if not context.preferences.experimental.use_new_particle_system: - return False - if context.mode != 'OBJECT': - return False - if context.active_object is None: - return False - if context.active_object.type != 'MESH': - return False - return True - - def execute(self, context): - pointcloud = bpy.data.pointclouds.new("Particles") - pointcloud_object = bpy.data.objects.new("Particles", pointcloud) - modifier = pointcloud_object.modifiers.new("Simulation", 'SIMULATION') - simulation = bpy.data.simulations.new("Particle Simulation") - tree = simulation.node_tree - - default_name = "Particles" - particle_simulation_node = tree.nodes.new('SimulationNodeParticleSimulation') - particle_simulation_node.name = default_name - emitter_node = tree.nodes.new('SimulationNodeParticleMeshEmitter') - emitter_node.location.x -= 200 - emitter_node.location.y += 50 - emitter_node.inputs["Object"].default_value = context.active_object - force_node = tree.nodes.new('SimulationNodeForce') - force_node.location.x -= 200 - force_node.location.y -= 100 - force_node.inputs["Force"].default_value = (0, 0, -1) - - tree.links.new(particle_simulation_node.inputs["Emitters"], emitter_node.outputs["Emitter"]) - tree.links.new(particle_simulation_node.inputs["Forces"], force_node.outputs["Force"]) - - modifier.simulation = simulation - modifier.data_path = default_name - - for obj in context.selected_objects: - obj.select_set(False) - - context.collection.objects.link(pointcloud_object) - pointcloud_object.select_set(True) - context.view_layer.objects.active = pointcloud_object - pointcloud_object.show_bounds = True - return {'FINISHED'} - - classes = ( QuickExplode, QuickFur, QuickSmoke, QuickLiquid, - QuickParticles, ) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 38f2c67f501..b5ce8be3b6a 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2691,8 +2691,6 @@ class VIEW3D_MT_object_quick_effects(Menu): layout.operator("object.quick_explode") layout.operator("object.quick_smoke") layout.operator("object.quick_liquid") - if context.preferences.experimental.use_new_particle_system: - layout.operator("object.quick_particles") class VIEW3D_MT_object_showhide(Menu): diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 027f4068dc4..8d2b6198fd5 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -485,64 +485,6 @@ def not_implemented_node(idname): simulation_node_categories = [ # Simulation Nodes - SimulationNodeCategory("SIM_OUTPUT", "Output", items=[ - NodeItem("SimulationNodeParticleSimulation"), - ]), - SimulationNodeCategory("SIM_INPUTS", "Input", items=[ - NodeItem("SimulationNodeTime"), - NodeItem("SimulationNodeParticleAttribute"), - NodeItem("FunctionNodeGroupInstanceID"), - NodeItem("ShaderNodeValue"), - NodeItem("FunctionNodeObjectTransforms"), - ]), - SimulationNodeCategory("SIM_EMITTERS", "Emitters", items=[ - NodeItem("SimulationNodeParticleMeshEmitter"), - not_implemented_node("SimulationNodeEmitParticles"), - ]), - SimulationNodeCategory("SIM_EVENTS", "Events", items=[ - NodeItem("SimulationNodeParticleBirthEvent"), - NodeItem("SimulationNodeParticleTimeStepEvent"), - NodeItem("SimulationNodeAgeReachedEvent"), - not_implemented_node("SimulationNodeParticleMeshCollisionEvent"), - ]), - SimulationNodeCategory("SIM_FORCES", "Forces", items=[ - NodeItem("SimulationNodeForce"), - ]), - SimulationNodeCategory("SIM_EXECUTE", "Execute", items=[ - NodeItem("SimulationNodeSetParticleAttribute"), - NodeItem("SimulationNodeExecuteCondition"), - NodeItem("SimulationNodeKillParticle"), - not_implemented_node("SimulationNodeMultiExecute"), - ]), - SimulationNodeCategory("SIM_NOISE", "Noise", items=[ - not_implemented_node("ShaderNodeTexNoise"), - not_implemented_node("ShaderNodeTexWhiteNoise"), - ]), - SimulationNodeCategory("SIM_COLOR", "Color", items=[ - not_implemented_node("ShaderNodeMixRGB"), - not_implemented_node("ShaderNodeInvert"), - not_implemented_node("ShaderNodeHueSaturation"), - not_implemented_node("ShaderNodeGamma"), - not_implemented_node("ShaderNodeBrightContrast"), - ]), - SimulationNodeCategory("SIM_CONVERTER", "Converter", items=[ - NodeItem("ShaderNodeMapRange"), - NodeItem("ShaderNodeClamp"), - NodeItem("ShaderNodeMath"), - NodeItem("ShaderNodeValToRGB"), - NodeItem("ShaderNodeVectorMath"), - NodeItem("ShaderNodeSeparateRGB"), - NodeItem("ShaderNodeCombineRGB"), - NodeItem("ShaderNodeSeparateXYZ"), - NodeItem("ShaderNodeCombineXYZ"), - not_implemented_node("ShaderNodeSeparateHSV"), - not_implemented_node("ShaderNodeCombineHSV"), - NodeItem("FunctionNodeBooleanMath"), - NodeItem("FunctionNodeFloatCompare"), - not_implemented_node("FunctionNodeSwitch"), - NodeItem("FunctionNodeCombineStrings"), - NodeItem("FunctionNodeRandomFloat"), - ]), SimulationNodeCategory("SIM_GROUP", "Group", items=node_group_items), SimulationNodeCategory("SIM_LAYOUT", "Layout", items=[ NodeItem("NodeFrame"), diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 5200a1b03fe..38045e22def 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1324,27 +1324,6 @@ int ntreeTexExecTree(struct bNodeTree *ntree, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Simulation Nodes - * \{ */ - -#define SIM_NODE_PARTICLE_SIMULATION 1000 -#define SIM_NODE_FORCE 1001 -#define SIM_NODE_SET_PARTICLE_ATTRIBUTE 1002 -#define SIM_NODE_PARTICLE_BIRTH_EVENT 1003 -#define SIM_NODE_PARTICLE_TIME_STEP_EVENT 1004 -#define SIM_NODE_EXECUTE_CONDITION 1005 -#define SIM_NODE_MULTI_EXECUTE 1006 -#define SIM_NODE_PARTICLE_MESH_EMITTER 1007 -#define SIM_NODE_PARTICLE_MESH_COLLISION_EVENT 1008 -#define SIM_NODE_EMIT_PARTICLES 1009 -#define SIM_NODE_TIME 1010 -#define SIM_NODE_PARTICLE_ATTRIBUTE 1011 -#define SIM_NODE_AGE_REACHED_EVENT 1012 -#define SIM_NODE_KILL_PARTICLE 1013 - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Function Nodes * \{ */ diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h index 2c436f2bff8..23735990079 100644 --- a/source/blender/blenkernel/BKE_simulation.h +++ b/source/blender/blenkernel/BKE_simulation.h @@ -31,27 +31,7 @@ void *BKE_simulation_add(struct Main *bmain, const char *name); void BKE_simulation_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Simulation *simulation); -void BKE_simulation_update_dependencies(struct Simulation *simulation, struct Main *bmain); - -SimulationState *BKE_simulation_state_add(Simulation *simulation, - 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 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index cf31b5338cb..80a553ff525 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -281,10 +281,6 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: - case SOCK_EMITTERS: - case SOCK_EVENTS: - case SOCK_FORCES: - case SOCK_CONTROL_FLOW: break; } } @@ -377,10 +373,6 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: - case SOCK_EMITTERS: - case SOCK_EVENTS: - case SOCK_FORCES: - case SOCK_CONTROL_FLOW: BLI_assert(false); break; } @@ -723,10 +715,6 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: - case SOCK_EMITTERS: - case SOCK_EVENTS: - case SOCK_FORCES: - case SOCK_CONTROL_FLOW: break; } } @@ -805,10 +793,6 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock) case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: - case SOCK_EMITTERS: - case SOCK_EVENTS: - case SOCK_FORCES: - case SOCK_CONTROL_FLOW: break; } } @@ -1361,10 +1345,6 @@ static void socket_id_user_increment(bNodeSocket *sock) case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: - case SOCK_EMITTERS: - case SOCK_EVENTS: - case SOCK_FORCES: - case SOCK_CONTROL_FLOW: break; } } @@ -1391,10 +1371,6 @@ static void socket_id_user_decrement(bNodeSocket *sock) case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: - case SOCK_EMITTERS: - case SOCK_EVENTS: - case SOCK_FORCES: - case SOCK_CONTROL_FLOW: break; } } @@ -1522,14 +1498,6 @@ const char *nodeStaticSocketType(int type, int subtype) return "NodeSocketObject"; case SOCK_IMAGE: return "NodeSocketImage"; - case SOCK_EMITTERS: - return "NodeSocketEmitters"; - case SOCK_EVENTS: - return "NodeSocketEvents"; - case SOCK_FORCES: - return "NodeSocketForces"; - case SOCK_CONTROL_FLOW: - return "NodeSocketControlFlow"; } return NULL; } @@ -1595,14 +1563,6 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype) return "NodeSocketInterfaceObject"; case SOCK_IMAGE: return "NodeSocketInterfaceImage"; - case SOCK_EMITTERS: - return "NodeSocketInterfaceEmitters"; - case SOCK_EVENTS: - return "NodeSocketInterfaceEvents"; - case SOCK_FORCES: - return "NodeSocketInterfaceForces"; - case SOCK_CONTROL_FLOW: - return "NodeSocketInterfaceControlFlow"; } return NULL; } @@ -4008,16 +3968,6 @@ void ntreeUpdateAllUsers(Main *main, ID *ngroup) FOREACH_NODETREE_END; } -static void ntreeUpdateSimulationDependencies(Main *main, bNodeTree *simulation_ntree) -{ - FOREACH_NODETREE_BEGIN (main, ntree, owner_id) { - if (GS(owner_id->name) == ID_SIM && ntree == simulation_ntree) { - BKE_simulation_update_dependencies((Simulation *)owner_id, main); - } - } - FOREACH_NODETREE_END; -} - void ntreeUpdateTree(Main *bmain, bNodeTree *ntree) { if (!ntree) { @@ -4073,11 +4023,6 @@ void ntreeUpdateTree(Main *bmain, bNodeTree *ntree) ntree_validate_links(ntree); } - if (bmain != NULL && ntree->typeinfo == ntreeType_Simulation && - (ntree->id.flag & LIB_EMBEDDED_DATA)) { - ntreeUpdateSimulationDependencies(bmain, ntree); - } - /* clear update flags */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { node->update = 0; @@ -4704,21 +4649,6 @@ static void registerTextureNodes(void) static void registerSimulationNodes(void) { register_node_type_sim_group(); - - register_node_type_sim_particle_simulation(); - register_node_type_sim_force(); - register_node_type_sim_set_particle_attribute(); - register_node_type_sim_particle_birth_event(); - register_node_type_sim_particle_time_step_event(); - register_node_type_sim_execute_condition(); - register_node_type_sim_multi_execute(); - register_node_type_sim_particle_mesh_emitter(); - register_node_type_sim_particle_mesh_collision_event(); - register_node_type_sim_emit_particles(); - register_node_type_sim_time(); - register_node_type_sim_particle_attribute(); - register_node_type_sim_age_reached_event(); - register_node_type_sim_kill_particle(); } static void registerFunctionNodes(void) diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index d7314831b18..2e1f8bd581e 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -61,26 +61,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" -#include "SIM_simulation_update.hh" - #include "BLO_read_write.h" -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; @@ -106,16 +88,6 @@ static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons (ID **)&simulation_dst->nodetree, flag_private_id_data); } - - 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_listbase_clear(&simulation_dst->dependencies); - BLI_duplicatelist(&simulation_dst->dependencies, &simulation_src->dependencies); } static void simulation_free_data(ID *id) @@ -129,10 +101,6 @@ static void simulation_free_data(ID *id) MEM_freeN(simulation->nodetree); simulation->nodetree = nullptr; } - - BKE_simulation_state_remove_all(simulation); - - BLI_freelistN(&simulation->dependencies); } static void simulation_foreach_id(ID *id, LibraryForeachIDData *data) @@ -142,9 +110,6 @@ 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); - } } static void simulation_blend_write(BlendWriter *writer, ID *id, const void *id_address) @@ -163,41 +128,6 @@ static void simulation_blend_write(BlendWriter *writer, ID *id, const void *id_a BLO_write_struct(writer, bNodeTree, simulation->nodetree); ntreeBlendWrite(writer, simulation->nodetree); } - - LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { - BLO_write_string(writer, state->name); - BLO_write_string(writer, state->type); - /* TODO: Decentralize this part. */ - if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { - ParticleSimulationState *particle_state = (ParticleSimulationState *)state; - - CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE]; - CustomData attributes_shallow_copy = particle_state->attributes; - CustomData_blend_write_prepare( - &attributes_shallow_copy, &players, players_buff, ARRAY_SIZE(players_buff)); - - BLO_write_struct(writer, ParticleSimulationState, particle_state); - - CustomData_blend_write(writer, - &attributes_shallow_copy, - players, - particle_state->tot_particles, - CD_MASK_ALL, - &simulation->id); - - /* Remove temporary data. */ - if (players && players != players_buff) { - MEM_freeN(players); - } - } - 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, SimulationDependency, &simulation->dependencies); } } @@ -206,34 +136,18 @@ static void simulation_blend_read_data(BlendDataReader *reader, ID *id) Simulation *simulation = (Simulation *)id; BLO_read_data_address(reader, &simulation->adt); BKE_animdata_blend_read_data(reader, simulation->adt); - - BLO_read_list(reader, &simulation->states); - LISTBASE_FOREACH (SimulationState *, state, &simulation->states) { - BLO_read_data_address(reader, &state->name); - BLO_read_data_address(reader, &state->type); - if (STREQ(state->type, SIM_TYPE_NAME_PARTICLE_SIMULATION)) { - ParticleSimulationState *particle_state = (ParticleSimulationState *)state; - CustomData_blend_read(reader, &particle_state->attributes, particle_state->tot_particles); - } - } - - BLO_read_list(reader, &simulation->dependencies); } static void simulation_blend_read_lib(BlendLibReader *reader, ID *id) { Simulation *simulation = (Simulation *)id; - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { - BLO_read_id_address(reader, simulation->id.lib, &dependency->id); - } + UNUSED_VARS(simulation, reader); } static void simulation_blend_read_expand(BlendExpander *expander, ID *id) { Simulation *simulation = (Simulation *)id; - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { - BLO_expand(expander, dependency->id); - } + UNUSED_VARS(simulation, expander); } IDTypeInfo IDType_ID_SIM = { @@ -262,204 +176,11 @@ IDTypeInfo IDType_ID_SIM = { void *BKE_simulation_add(Main *bmain, const char *name) { Simulation *simulation = (Simulation *)BKE_id_new(bmain, ID_SIM, 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); -} - -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); - } -} - -using StateTypeMap = blender::Map<std::string, std::unique_ptr<SimulationStateType>>; - -template<typename T> -static void add_state_type(StateTypeMap &map, - void (*init)(T *state), - void (*reset)(T *state), - void (*remove)(T *state), - void (*copy)(const T *src, T *dst)) -{ - SimulationStateType state_type{ - BKE_simulation_get_state_type_name<T>(), - static_cast<int>(sizeof(T)), - (StateInitFunction)init, - (StateResetFunction)reset, - (StateRemoveFunction)remove, - (StateCopyFunction)copy, - }; - map.add_new(state_type.name, std::make_unique<SimulationStateType>(state_type)); -} - -static StateTypeMap init_state_types() -{ - StateTypeMap map; - add_state_type<ParticleSimulationState>( - map, - [](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, - [](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>() +void BKE_simulation_data_update(Depsgraph *UNUSED(depsgraph), + Scene *UNUSED(scene), + Simulation *UNUSED(simulation)) { - return SIM_TYPE_NAME_PARTICLE_MESH_EMITTER; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 5d3dc1c859e..86a365a4901 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -2660,24 +2660,6 @@ void DepsgraphRelationBuilder::build_simulation(Simulation *simulation) OperationKey nodetree_key( &simulation->nodetree->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT); add_relation(nodetree_key, simulation_eval_key, "NodeTree -> Simulation", 0); - - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { - if (dependency->id == nullptr) { - continue; - } - build_id(dependency->id); - if (GS(dependency->id->name) == ID_OB) { - Object *object = (Object *)dependency->id; - if (dependency->flag & SIM_DEPENDS_ON_TRANSFORM) { - ComponentKey object_transform_key(&object->id, NodeType::TRANSFORM); - add_relation(object_transform_key, simulation_eval_key, "Object Transform -> Simulation"); - } - if (dependency->flag & SIM_DEPENDS_ON_GEOMETRY) { - ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY); - add_relation(object_geometry_key, simulation_eval_key, "Object Geometry -> Simulation"); - } - } - } } void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 10aa53abb01..66da2887427 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3140,58 +3140,8 @@ static void node_texture_set_butfunc(bNodeType *ntype) /* ****************** BUTTON CALLBACKS FOR SIMULATION NODES ***************** */ -static void node_simulation_buts_particle_simulation(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) +static void node_simulation_set_butfunc(bNodeType *UNUSED(ntype)) { - uiItemR(layout, ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_simulation_buts_particle_time_step_event(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_simulation_buts_particle_attribute(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_simulation_buts_set_particle_attribute(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_simulation_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_simulation_set_butfunc(bNodeType *ntype) -{ - switch (ntype->type) { - case SIM_NODE_PARTICLE_SIMULATION: - ntype->draw_buttons = node_simulation_buts_particle_simulation; - break; - case SIM_NODE_PARTICLE_TIME_STEP_EVENT: - ntype->draw_buttons = node_simulation_buts_particle_time_step_event; - break; - case SIM_NODE_PARTICLE_ATTRIBUTE: - ntype->draw_buttons = node_simulation_buts_particle_attribute; - break; - case SIM_NODE_SET_PARTICLE_ATTRIBUTE: - ntype->draw_buttons = node_simulation_buts_set_particle_attribute; - break; - case SIM_NODE_TIME: - ntype->draw_buttons = node_simulation_buts_time; - break; - } } /* ****************** BUTTON CALLBACKS FOR FUNCTION NODES ***************** */ @@ -3379,10 +3329,6 @@ static const float std_node_socket_colors[][4] = { {0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */ {0.40, 0.10, 0.10, 1.0}, /* SOCK_OBJECT */ {0.10, 0.40, 0.10, 1.0}, /* SOCK_IMAGE */ - {0.80, 0.80, 0.20, 1.0}, /* SOCK_EMITTERS */ - {0.80, 0.20, 0.80, 1.0}, /* SOCK_EVENTS */ - {0.20, 0.80, 0.80, 1.0}, /* SOCK_FORCES */ - {0.30, 0.30, 0.30, 1.0}, /* SOCK_CONTROL_FLOW */ }; /* common color callbacks for standard types */ diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 2668b3eb6ca..6aec3c39b29 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -446,7 +446,7 @@ typedef enum ID_Type { ID_HA = MAKE_ID2('H', 'A'), /* Hair */ ID_PT = MAKE_ID2('P', 'T'), /* PointCloud */ ID_VO = MAKE_ID2('V', 'O'), /* Volume */ - ID_SIM = MAKE_ID2('S', 'I'), /* Simulation */ + ID_SIM = MAKE_ID2('S', 'I'), /* Simulation (currently unused) */ } ID_Type; /* Only used as 'placeholder' in .blend files for directly linked data-blocks. */ diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index 3aca558cdbe..44b4e9b855e 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -576,8 +576,6 @@ #define _DNA_DEFAULT_SimulationModifierData \ { \ - .simulation = NULL, \ - .data_path = NULL, \ } #define _DNA_DEFAULT_SkinModifierData \ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 34d2c80dc5d..29bcc5fe903 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -2219,9 +2219,6 @@ enum { typedef struct SimulationModifierData { ModifierData modifier; - - struct Simulation *simulation; - char *data_path; } SimulationModifierData; typedef struct MeshToVolumeModifierData { diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 33856dc2622..cba93bbadfc 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -155,10 +155,6 @@ typedef enum eNodeSocketDatatype { SOCK_STRING = 7, SOCK_OBJECT = 8, SOCK_IMAGE = 9, - SOCK_EMITTERS = 10, - SOCK_EVENTS = 11, - SOCK_FORCES = 12, - SOCK_CONTROL_FLOW = 13, } eNodeSocketDatatype; /* socket shape */ diff --git a/source/blender/makesdna/DNA_simulation_types.h b/source/blender/makesdna/DNA_simulation_types.h index 8cc2db99332..4ff694b29cc 100644 --- a/source/blender/makesdna/DNA_simulation_types.h +++ b/source/blender/makesdna/DNA_simulation_types.h @@ -27,69 +27,14 @@ typedef struct Simulation { ID id; struct AnimData *adt; /* animation data (must be immediately after id) */ + /* This nodetree is embedded into the data block. */ struct bNodeTree *nodetree; uint32_t flag; - - /** This is the frame in scene time, that the states correspond to. */ - float current_frame; - - /** Time since the start of the simulation in simulation time (which might differ from scene - * time). */ - float current_simulation_time; char _pad[4]; - - /** List containing SimulationState objects. */ - struct ListBase states; - - /** List containing SimulationDependency objects. */ - struct ListBase dependencies; } Simulation; -typedef struct SimulationState { - struct SimulationState *next; - struct SimulationState *prev; - - char *type; - char *name; -} SimulationState; - -typedef struct ParticleSimulationState { - SimulationState head; - - /** Contains the state of the particles at time Simulation->current_frame. */ - int32_t tot_particles; - int32_t next_particle_id; - struct CustomData attributes; -} ParticleSimulationState; - -typedef struct ParticleMeshEmitterSimulationState { - SimulationState head; - - float last_birth_time; - char _pad[4]; -} ParticleMeshEmitterSimulationState; - -/** Stores a reference to data that the simulation depends on. This is partially derived from the - * simulation node tree. */ -typedef struct SimulationDependency { - struct SimulationDependency *next; - struct SimulationDependency *prev; - struct ID *id; - int32_t handle; - uint32_t flag; -} SimulationDependency; - /* Simulation.flag */ enum { SIM_DS_EXPAND = (1 << 0), }; - -/* SimulationDependency.flag */ -enum { - SIM_DEPENDS_ON_TRANSFORM = (1 << 0), - SIM_DEPENDS_ON_GEOMETRY = (1 << 1), -}; - -#define SIM_TYPE_NAME_PARTICLE_SIMULATION "Particle Simulation" -#define SIM_TYPE_NAME_PARTICLE_MESH_EMITTER "Particle Mesh Emitter" diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 9e0597f000b..e42dfb83885 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1531,51 +1531,6 @@ static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr, CLAMP_MIN(psmd->psys, 1); } -# ifdef WITH_PARTICLE_NODES -static void rna_SimulationModifier_simulation_update(Main *bmain, Scene *scene, PointerRNA *ptr) -{ - SimulationModifierData *smd = ptr->data; - if (smd->simulation != NULL) { - DEG_id_tag_update(&smd->simulation->id, ID_RECALC_ALL); - } - rna_Modifier_dependency_update(bmain, scene, ptr); -} - -static void rna_SimulationModifier_data_path_get(PointerRNA *ptr, char *value) -{ - SimulationModifierData *smd = ptr->data; - - if (smd->data_path) { - strcpy(value, smd->data_path); - } - else { - value[0] = '\0'; - } -} - -static int rna_SimulationModifier_data_path_length(PointerRNA *ptr) -{ - SimulationModifierData *smd = ptr->data; - return smd->data_path ? strlen(smd->data_path) : 0; -} - -static void rna_SimulationModifier_data_path_set(PointerRNA *ptr, const char *value) -{ - SimulationModifierData *smd = ptr->data; - - if (smd->data_path) { - MEM_freeN(smd->data_path); - } - - if (value[0]) { - smd->data_path = BLI_strdup(value); - } - else { - smd->data_path = NULL; - } -} -# endif - /** * Special set callback that just changes the first bit of the expansion flag. * This way the expansion state of all the sub-panels is not changed by RNA. @@ -6968,7 +6923,6 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna) static void rna_def_modifier_simulation(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop; srna = RNA_def_struct(brna, "SimulationModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Simulation Modifier", ""); @@ -6977,20 +6931,6 @@ static void rna_def_modifier_simulation(BlenderRNA *brna) RNA_define_lib_overridable(true); - prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE); - RNA_def_property_ui_text(prop, "Simulation", "Simulation to access"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_update(prop, 0, "rna_SimulationModifier_simulation_update"); - - prop = RNA_def_property(srna, "data_path", PROP_STRING, PROP_NONE); - RNA_def_property_string_funcs(prop, - "rna_SimulationModifier_data_path_get", - "rna_SimulationModifier_data_path_length", - "rna_SimulationModifier_data_path_set"); - RNA_def_property_ui_text( - prop, "Data Path", "Identifier of the simulation component that should be accessed"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - RNA_define_lib_overridable(false); } # endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 8c99a4cc1a1..0b8764f8a77 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -84,21 +84,6 @@ static const EnumPropertyItem node_socket_type_items[] = { {SOCK_SHADER, "SHADER", 0, "Shader", ""}, {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, - {SOCK_EMITTERS, "EMITTERS", 0, "Emitters", ""}, - {SOCK_EVENTS, "EVENTS", 0, "Events", ""}, - {SOCK_FORCES, "FORCES", 0, "Forces", ""}, - {SOCK_CONTROL_FLOW, "CONTROL_FLOW", 0, "Control Flow", ""}, - {0, NULL, 0, NULL, NULL}, -}; - -static const EnumPropertyItem particle_attribute_socket_type_items[] = { - {SOCK_FLOAT, "FLOAT", 0, "Float", ""}, - {SOCK_INT, "INT", 0, "Int", ""}, - {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, - {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, - {SOCK_RGBA, "RGBA", 0, "Color", ""}, - {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, - {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -3758,15 +3743,6 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA rna_Node_update(bmain, scene, ptr); } -static void rna_SimulationNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr) -{ - bNodeTree *ntree = (bNodeTree *)ptr->owner_id; - bNode *node = (bNode *)ptr->data; - - nodeUpdate(ntree, node); - rna_Node_update(bmain, scene, ptr); -} - static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr) { bNode *node = ptr->data; @@ -8164,82 +8140,6 @@ static void def_tex_bricks(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } -/* -- Simulation Nodes --------------------------------------------------------- */ - -static void def_sim_particle_time_step_event(StructRNA *srna) -{ - static const EnumPropertyItem mode_items[] = { - {NODE_PARTICLE_TIME_STEP_EVENT_BEGIN, - "BEGIN", - 0, - "Begin", - "Execute for every particle at the beginning of each time step"}, - {NODE_PARTICLE_TIME_STEP_EVENT_END, - "END", - 0, - "End", - "Execute for every particle at the end of each time step"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - - prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, mode_items); - RNA_def_property_ui_text(prop, "Mode", "When in each time step is the event triggered"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); -} - -static void def_sim_particle_attribute(StructRNA *srna) -{ - PropertyRNA *prop; - - prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, particle_attribute_socket_type_items); - RNA_def_property_ui_text( - prop, - "Data Type", - "Expected type of the attribute. A default value is returned if the type is not correct"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); -} - -static void def_sim_set_particle_attribute(StructRNA *srna) -{ - PropertyRNA *prop; - - prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, particle_attribute_socket_type_items); - RNA_def_property_ui_text( - prop, - "Data Type", - "Expected type of the attribute. Nothing is done if the type is not correct"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); -} - -static void def_sim_time(StructRNA *srna) -{ - static const EnumPropertyItem mode_items[] = { - {NODE_SIM_INPUT_SIMULATION_TIME, - "SIMULATION_TIME", - 0, - "Simulation Time", - "Time since start of simulation"}, - {NODE_SIM_INPUT_SCENE_TIME, "SCENE_TIME", 0, "Scene Time", "Time shown in the timeline"}, - {0, NULL, 0, NULL, NULL}, - }; - - PropertyRNA *prop; - - prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); - RNA_def_property_enum_items(prop, mode_items); - RNA_def_property_ui_text(prop, "Mode", "The time to output"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); -} - /* -------------------------------------------------------------------------- */ static void rna_def_shader_node(BlenderRNA *brna) diff --git a/source/blender/modifiers/intern/MOD_simulation.cc b/source/blender/modifiers/intern/MOD_simulation.cc index f851bf3fe9b..28b4c329730 100644 --- a/source/blender/modifiers/intern/MOD_simulation.cc +++ b/source/blender/modifiers/intern/MOD_simulation.cc @@ -74,18 +74,19 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(smd, DNA_struct_default_get(SimulationModifierData), modifier); } -static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *UNUSED(ctx)) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - if (smd->simulation) { - DEG_add_simulation_relation(ctx->node, smd->simulation, "Accessed Simulation"); - } + UNUSED_VARS(smd); } -static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +static void foreachIDLink(ModifierData *md, + Object *UNUSED(ob), + IDWalkFunc UNUSED(walk), + void *UNUSED(userData)) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - walk(userData, ob, (ID **)&smd->simulation, IDWALK_CB_USER); + UNUSED_VARS(smd); } static bool isDisabled(const struct Scene *UNUSED(scene), @@ -93,45 +94,16 @@ static bool isDisabled(const struct Scene *UNUSED(scene), bool UNUSED(useRenderParams)) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - return smd->simulation == nullptr; -} - -static const ParticleSimulationState *find_particle_state(SimulationModifierData *smd) -{ - return reinterpret_cast<const ParticleSimulationState *>( - BKE_simulation_state_try_find_by_name_and_type( - smd->simulation, smd->data_path, SIM_TYPE_NAME_PARTICLE_SIMULATION)); + UNUSED_VARS(smd); + return false; } static PointCloud *modifyPointCloud(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), - PointCloud *input_pointcloud) + PointCloud *pointcloud) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - const ParticleSimulationState *state = find_particle_state(smd); - if (state == nullptr) { - return input_pointcloud; - } - - PointCloud *pointcloud = BKE_pointcloud_new_for_eval(input_pointcloud, state->tot_particles); - if (state->tot_particles == 0) { - return pointcloud; - } - - const float3 *positions = static_cast<const float3 *>( - CustomData_get_layer_named(&state->attributes, CD_PROP_FLOAT3, "Position")); - const float *radii = static_cast<const float *>( - CustomData_get_layer_named(&state->attributes, CD_PROP_FLOAT, "Radius")); - memcpy(pointcloud->co, positions, sizeof(float3) * state->tot_particles); - - CustomData_add_layer_named( - &pointcloud->pdata, CD_PROP_FLOAT, CD_CALLOC, NULL, state->tot_particles, "Radius"); - BKE_pointcloud_update_customdata_pointers(pointcloud); - - for (int i = 0; i < state->tot_particles; i++) { - pointcloud->radius[i] = radii[i]; - } - + UNUSED_VARS(smd); return pointcloud; } @@ -145,8 +117,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropSep(layout, true); uiLayoutSetPropDecorate(layout, false); - uiItemR(layout, ptr, "simulation", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "data_path", 0, NULL, ICON_NONE); + uiItemL(layout, "This modifier does nothing currently", ICON_INFO); modifier_panel_end(layout, ptr); } @@ -159,32 +130,28 @@ static void panelRegister(ARegionType *region_type) static void blendWrite(BlendWriter *writer, const ModifierData *md) { const SimulationModifierData *smd = reinterpret_cast<const SimulationModifierData *>(md); - BLO_write_string(writer, smd->data_path); + UNUSED_VARS(smd, writer); } static void blendRead(BlendDataReader *reader, ModifierData *md) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - BLO_read_data_address(reader, &smd->data_path); + UNUSED_VARS(smd, reader); } static void copyData(const ModifierData *md, ModifierData *target, const int flag) { const SimulationModifierData *smd = reinterpret_cast<const SimulationModifierData *>(md); SimulationModifierData *tsmd = reinterpret_cast<SimulationModifierData *>(target); + UNUSED_VARS(smd, tsmd); BKE_modifier_copydata_generic(md, target, flag); - if (smd->data_path != nullptr) { - tsmd->data_path = BLI_strdup(smd->data_path); - } } static void freeData(ModifierData *md) { SimulationModifierData *smd = reinterpret_cast<SimulationModifierData *>(md); - if (smd->data_path) { - MEM_freeN(smd->data_path); - } + UNUSED_VARS(smd); } ModifierTypeInfo modifierType_Simulation = { diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 4172dc06a9f..78b3e6236f0 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -230,21 +230,7 @@ set(SRC shader/node_shader_tree.c shader/node_shader_util.c - simulation/nodes/node_sim_age_reached_event.cc simulation/nodes/node_sim_common.cc - simulation/nodes/node_sim_emit_particles.cc - simulation/nodes/node_sim_execute_condition.cc - simulation/nodes/node_sim_force.cc - simulation/nodes/node_sim_kill_particle.cc - simulation/nodes/node_sim_multi_execute.cc - simulation/nodes/node_sim_particle_attribute.cc - simulation/nodes/node_sim_particle_birth_event.cc - simulation/nodes/node_sim_particle_mesh_collision_event.cc - simulation/nodes/node_sim_particle_mesh_emitter.cc - simulation/nodes/node_sim_particle_simulation.cc - simulation/nodes/node_sim_particle_time_step_event.cc - simulation/nodes/node_sim_set_particle_attribute.cc - simulation/nodes/node_sim_simulation_time.cc simulation/node_simulation_tree.cc simulation/node_simulation_util.cc diff --git a/source/blender/nodes/NOD_simulation.h b/source/blender/nodes/NOD_simulation.h index 266ded997c6..6b3d51b46a9 100644 --- a/source/blender/nodes/NOD_simulation.h +++ b/source/blender/nodes/NOD_simulation.h @@ -26,21 +26,6 @@ void register_node_tree_type_sim(void); void register_node_type_sim_group(void); -void register_node_type_sim_particle_simulation(void); -void register_node_type_sim_force(void); -void register_node_type_sim_set_particle_attribute(void); -void register_node_type_sim_particle_birth_event(void); -void register_node_type_sim_particle_time_step_event(void); -void register_node_type_sim_execute_condition(void); -void register_node_type_sim_multi_execute(void); -void register_node_type_sim_particle_mesh_emitter(void); -void register_node_type_sim_particle_mesh_collision_event(void); -void register_node_type_sim_emit_particles(void); -void register_node_type_sim_time(void); -void register_node_type_sim_particle_attribute(void); -void register_node_type_sim_age_reached_event(void); -void register_node_type_sim_kill_particle(void); - #ifdef __cplusplus } #endif diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 7922a73902c..0173706b570 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -258,21 +258,6 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_NOISE, 0, "TEX_NO DefNode(TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_STUCCI", TexStucci, "Stucci", "" ) DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" ) -DefNode(SimulationNode, SIM_NODE_PARTICLE_SIMULATION, 0, "PARTICLE_SIMULATION", ParticleSimulation, "Particle Simulation", "") -DefNode(SimulationNode, SIM_NODE_FORCE, 0, "FORCE", Force, "Force", "") -DefNode(SimulationNode, SIM_NODE_SET_PARTICLE_ATTRIBUTE, def_sim_set_particle_attribute, "SET_PARTICLE_ATTRIBUTE", SetParticleAttribute, "Set Particle Attribute", "") -DefNode(SimulationNode, SIM_NODE_PARTICLE_BIRTH_EVENT, 0, "PARTICLE_BIRTH_EVENT", ParticleBirthEvent, "Particle Birth Event", "") -DefNode(SimulationNode, SIM_NODE_PARTICLE_TIME_STEP_EVENT, def_sim_particle_time_step_event, "PARTICLE_TIME_STEP_EVENT", ParticleTimeStepEvent, "Particle Time Step Event", "") -DefNode(SimulationNode, SIM_NODE_EXECUTE_CONDITION, 0, "EXECUTE_CONDITION", ExecuteCondition, "Execute Condition", "") -DefNode(SimulationNode, SIM_NODE_MULTI_EXECUTE, 0, "MULTI_EXECUTE", MultiExecute, "Multi Execute", "") -DefNode(SimulationNode, SIM_NODE_PARTICLE_MESH_EMITTER, 0, "PARTICLE_MESH_EMITTER", ParticleMeshEmitter, "Particle Mesh Emitter", "") -DefNode(SimulationNode, SIM_NODE_PARTICLE_MESH_COLLISION_EVENT, 0, "PARTICLE_MESH_COLLISION_EVENT", ParticleMeshCollisionEvent, "Particle Mesh Collision Event", "") -DefNode(SimulationNode, SIM_NODE_EMIT_PARTICLES, 0, "EMIT_PARTICLES", EmitParticles, "Emit Particles", "") -DefNode(SimulationNode, SIM_NODE_TIME, def_sim_time, "TIME", Time, "Time", "") -DefNode(SimulationNode, SIM_NODE_PARTICLE_ATTRIBUTE, def_sim_particle_attribute, "PARTICLE_ATTRIBUTE", ParticleAttribute, "Particle Attribute", "") -DefNode(SimulationNode, SIM_NODE_AGE_REACHED_EVENT, 0, "AGE_REACHED_EVENT", AgeReachedEvent, "Age Reached Event", "") -DefNode(SimulationNode, SIM_NODE_KILL_PARTICLE, 0, "KILL_PARTICLE", KillParticle, "Kill Particle", "") - DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "") DefNode(FunctionNode, FN_NODE_FLOAT_COMPARE, def_float_compare, "FLOAT_COMPARE", FloatCompare, "Float Compare", "") DefNode(FunctionNode, FN_NODE_SWITCH, def_fn_switch, "SWITCH", Switch, "Switch", "") diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 0dfae7424cb..0cedc6597c8 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -549,19 +549,6 @@ static bNodeSocketType *make_socket_type_virtual(void) return stype; } -static bNodeSocketType *make_socket_type_effector(int type) -{ - bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE); - stype->input_link_limit = 0xFFF; - return stype; -} - -static bNodeSocketType *make_socket_type_control_flow(int type) -{ - bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE); - return stype; -} - static bNodeSocketType *make_socket_type_bool() { bNodeSocketType *socktype = make_standard_socket_type(SOCK_BOOLEAN, PROP_NONE); @@ -721,11 +708,5 @@ void register_standard_node_socket_types(void) nodeRegisterSocketType(make_standard_socket_type(SOCK_IMAGE, PROP_NONE)); - nodeRegisterSocketType(make_socket_type_effector(SOCK_EMITTERS)); - nodeRegisterSocketType(make_socket_type_effector(SOCK_EVENTS)); - nodeRegisterSocketType(make_socket_type_effector(SOCK_FORCES)); - - nodeRegisterSocketType(make_socket_type_control_flow(SOCK_CONTROL_FLOW)); - nodeRegisterSocketType(make_socket_type_virtual()); } diff --git a/source/blender/nodes/simulation/nodes/node_sim_age_reached_event.cc b/source/blender/nodes/simulation/nodes/node_sim_age_reached_event.cc deleted file mode 100644 index add8c4eba4d..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_age_reached_event.cc +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_age_reached_event_in[] = { - {SOCK_FLOAT, N_("Age"), 3, 0, 0, 0, 0, 10000000}, - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_age_reached_event_out[] = { - {SOCK_EVENTS, N_("Event")}, - {-1, ""}, -}; - -void register_node_type_sim_age_reached_event() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_AGE_REACHED_EVENT, "Age Reached Event", 0, 0); - node_type_socket_templates( - &ntype, sim_node_age_reached_event_in, sim_node_age_reached_event_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc b/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc deleted file mode 100644 index e23984dbf34..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_emit_particle_in[] = { - {SOCK_INT, N_("Amount"), 10, 0, 0, 0, 0, 10000000}, - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_emit_particle_out[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {SOCK_EMITTERS, N_("Emitter")}, - {-1, ""}, -}; - -void register_node_type_sim_emit_particles() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_EMIT_PARTICLES, "Emit Particles", 0, 0); - node_type_socket_templates(&ntype, sim_node_emit_particle_in, sim_node_emit_particle_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc b/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc deleted file mode 100644 index 69f30d1ad0d..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_execute_condition_in[] = { - {SOCK_BOOLEAN, N_("Condition")}, - {SOCK_CONTROL_FLOW, N_("If True")}, - {SOCK_CONTROL_FLOW, N_("If False")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_execute_condition_out[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -void register_node_type_sim_execute_condition() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_EXECUTE_CONDITION, "Execute Condition", 0, 0); - node_type_socket_templates( - &ntype, sim_node_execute_condition_in, sim_node_execute_condition_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_force.cc b/source/blender/nodes/simulation/nodes/node_sim_force.cc deleted file mode 100644 index eccd2e4e2ab..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_force.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_force_in[] = { - {SOCK_VECTOR, N_("Force"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_force_out[] = { - {SOCK_FORCES, N_("Force")}, - {-1, ""}, -}; - -void register_node_type_sim_force() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_FORCE, "Force", 0, 0); - node_type_socket_templates(&ntype, sim_node_force_in, sim_node_force_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_kill_particle.cc b/source/blender/nodes/simulation/nodes/node_sim_kill_particle.cc deleted file mode 100644 index 793b40d9365..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_kill_particle.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_kill_particle_in[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_kill_particle_out[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -void register_node_type_sim_kill_particle() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_KILL_PARTICLE, "Kill Particle", 0, 0); - node_type_socket_templates(&ntype, sim_node_kill_particle_in, sim_node_kill_particle_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc b/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc deleted file mode 100644 index 5944db7e2bc..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_multi_execute_in[] = { - {SOCK_CONTROL_FLOW, "1"}, - {SOCK_CONTROL_FLOW, "2"}, - {SOCK_CONTROL_FLOW, "3"}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_multi_execute_out[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -void register_node_type_sim_multi_execute() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_MULTI_EXECUTE, "Multi Execute", 0, 0); - node_type_socket_templates(&ntype, sim_node_multi_execute_in, sim_node_multi_execute_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc deleted file mode 100644 index b6b67ee334e..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 "BLI_listbase.h" -#include "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_particle_attribute_in[] = { - {SOCK_STRING, N_("Name")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_particle_attribute_out[] = { - {SOCK_FLOAT, N_("Float")}, - {SOCK_INT, N_("Int")}, - {SOCK_BOOLEAN, N_("Boolean")}, - {SOCK_VECTOR, N_("Vector")}, - {SOCK_RGBA, N_("Color")}, - {SOCK_OBJECT, N_("Object")}, - {SOCK_IMAGE, N_("Image")}, - {-1, ""}, -}; - -static void sim_node_particle_attribute_update(bNodeTree *UNUSED(ntree), bNode *node) -{ - LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { - nodeSetSocketAvailability(sock, sock->type == node->custom1); - } -} - -void register_node_type_sim_particle_attribute() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_PARTICLE_ATTRIBUTE, "Particle Attribute", 0, 0); - node_type_socket_templates( - &ntype, sim_node_particle_attribute_in, sim_node_particle_attribute_out); - node_type_update(&ntype, sim_node_particle_attribute_update); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc deleted file mode 100644 index 8332a3ecd9f..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_particle_birth_event_in[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_particle_birth_event_out[] = { - {SOCK_EVENTS, N_("Event")}, - {-1, ""}, -}; - -void register_node_type_sim_particle_birth_event() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_PARTICLE_BIRTH_EVENT, "Particle Birth Event", 0, 0); - node_type_socket_templates( - &ntype, sim_node_particle_birth_event_in, sim_node_particle_birth_event_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc deleted file mode 100644 index 48671172136..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_particle_mesh_collision_event_in[] = { - {SOCK_OBJECT, N_("Object")}, - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_particle_mesh_collision_event_out[] = { - {SOCK_EVENTS, N_("Event")}, - {-1, ""}, -}; - -void register_node_type_sim_particle_mesh_collision_event() -{ - static bNodeType ntype; - - sim_node_type_base( - &ntype, SIM_NODE_PARTICLE_MESH_COLLISION_EVENT, "Particle Mesh Collision Event", 0, 0); - node_type_socket_templates(&ntype, - sim_node_particle_mesh_collision_event_in, - sim_node_particle_mesh_collision_event_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc deleted file mode 100644 index 5e1a6c35d52..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -#include "float.h" - -static bNodeSocketTemplate sim_node_particle_mesh_emitter_in[] = { - {SOCK_OBJECT, N_("Object")}, - {SOCK_FLOAT, N_("Rate"), 100.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_particle_mesh_emitter_out[] = { - {SOCK_EMITTERS, N_("Emitter")}, - {-1, ""}, -}; - -void register_node_type_sim_particle_mesh_emitter() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_PARTICLE_MESH_EMITTER, "Mesh Emitter", 0, 0); - node_type_socket_templates( - &ntype, sim_node_particle_mesh_emitter_in, sim_node_particle_mesh_emitter_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc deleted file mode 100644 index 159c9b23da1..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_particle_simulation_in[] = { - {SOCK_EMITTERS, N_("Emitters")}, - {SOCK_EVENTS, N_("Events")}, - {SOCK_FORCES, N_("Forces")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_particle_simulation_out[] = { - {-1, ""}, -}; - -void register_node_type_sim_particle_simulation() -{ - static bNodeType ntype; - - sim_node_type_base( - &ntype, SIM_NODE_PARTICLE_SIMULATION, "Particle Simulation", NODE_CLASS_OUTPUT, 0); - node_type_socket_templates( - &ntype, sim_node_particle_simulation_in, sim_node_particle_simulation_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc deleted file mode 100644 index cda8ddeb644..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_particle_time_step_event_in[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_particle_time_step_event_out[] = { - {SOCK_EVENTS, N_("Event")}, - {-1, ""}, -}; - -void register_node_type_sim_particle_time_step_event() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_PARTICLE_TIME_STEP_EVENT, "Particle Time Step Event", 0, 0); - node_type_socket_templates( - &ntype, sim_node_particle_time_step_event_in, sim_node_particle_time_step_event_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc b/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc deleted file mode 100644 index 8f5c6818cb4..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 "BLI_listbase.h" -#include "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_set_particle_attribute_in[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {SOCK_STRING, N_("Name")}, - {SOCK_FLOAT, N_("Float"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, - {SOCK_INT, N_("Int"), 0, 0, 0, 0, -10000, 10000}, - {SOCK_BOOLEAN, N_("Boolean")}, - {SOCK_VECTOR, N_("Vector")}, - {SOCK_RGBA, N_("Color")}, - {SOCK_OBJECT, N_("Object")}, - {SOCK_IMAGE, N_("Image")}, - {-1, ""}, -}; - -static bNodeSocketTemplate sim_node_set_particle_attribute_out[] = { - {SOCK_CONTROL_FLOW, N_("Execute")}, - {-1, ""}, -}; - -static void sim_node_set_particle_attribute_update(bNodeTree *UNUSED(ntree), bNode *node) -{ - int index = 0; - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - if (index >= 2) { - nodeSetSocketAvailability(sock, sock->type == node->custom1); - } - index++; - } -} - -void register_node_type_sim_set_particle_attribute() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_SET_PARTICLE_ATTRIBUTE, "Set Particle Attribute", 0, 0); - node_type_socket_templates( - &ntype, sim_node_set_particle_attribute_in, sim_node_set_particle_attribute_out); - node_type_update(&ntype, sim_node_set_particle_attribute_update); - nodeRegisterType(&ntype); -} diff --git a/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc b/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc deleted file mode 100644 index 40e1c43fb69..00000000000 --- a/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 "node_simulation_util.h" - -static bNodeSocketTemplate sim_node_time_out[] = { - {SOCK_FLOAT, N_("Time")}, - {-1, ""}, -}; - -void register_node_type_sim_time() -{ - static bNodeType ntype; - - sim_node_type_base(&ntype, SIM_NODE_TIME, "Time", 0, 0); - node_type_socket_templates(&ntype, nullptr, sim_node_time_out); - nodeRegisterType(&ntype); -} diff --git a/source/blender/simulation/CMakeLists.txt b/source/blender/simulation/CMakeLists.txt index e47586d55cc..c536d6a7d69 100644 --- a/source/blender/simulation/CMakeLists.txt +++ b/source/blender/simulation/CMakeLists.txt @@ -41,32 +41,16 @@ set(SRC intern/hair_volume.cpp intern/implicit_blender.c 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_solver_influences.cc - intern/simulation_update.cc intern/ConstrainedConjugateGradient.h intern/eigen_utils.h intern/implicit.h - intern/particle_allocator.hh - intern/particle_function.hh - intern/particle_mesh_emitter.hh - intern/simulation_collect_influences.hh - intern/simulation_solver.hh - intern/simulation_solver_influences.hh - intern/time_interval.hh SIM_mass_spring.h - SIM_simulation_update.hh ) set(LIB bf_blenkernel - bf_nodes ) if(WITH_OPENMP_STATIC) diff --git a/source/blender/simulation/SIM_simulation_update.hh b/source/blender/simulation/SIM_simulation_update.hh deleted file mode 100644 index 7c2726f038e..00000000000 --- a/source/blender/simulation/SIM_simulation_update.hh +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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. - */ - -#pragma once - -struct Depsgraph; -struct Scene; -struct Simulation; - -namespace blender::sim { - -void update_simulation_in_depsgraph(Depsgraph *depsgraph, - Scene *scene_cow, - Simulation *simulation_cow); - -bool update_simulation_dependencies(Simulation *simulation); - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/particle_allocator.cc b/source/blender/simulation/intern/particle_allocator.cc deleted file mode 100644 index 91ca667a239..00000000000 --- a/source/blender/simulation/intern/particle_allocator.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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_allocator.hh" - -#include "BLI_rand.hh" - -namespace blender::sim { - -AttributesAllocator::~AttributesAllocator() -{ - for (std::unique_ptr<AttributesBlock> &block : allocated_blocks_) { - for (int i : attributes_info_.index_range()) { - const fn::CPPType &type = attributes_info_.type_of(i); - type.destruct_n(block->buffers[i], block->size); - MEM_freeN(block->buffers[i]); - } - } -} - -fn::MutableAttributesRef AttributesAllocator::allocate_uninitialized(int size) -{ - std::unique_ptr<AttributesBlock> block = std::make_unique<AttributesBlock>(); - block->buffers = Array<void *>(attributes_info_.size(), nullptr); - block->size = size; - - for (int i : attributes_info_.index_range()) { - const fn::CPPType &type = attributes_info_.type_of(i); - void *buffer = MEM_mallocN_aligned(size * type.size(), type.alignment(), AT); - block->buffers[i] = buffer; - } - - fn::MutableAttributesRef attributes{attributes_info_, block->buffers, size}; - - { - std::lock_guard lock{mutex_}; - allocated_blocks_.append(std::move(block)); - allocated_attributes_.append(attributes); - total_allocated_ += size; - } - - return attributes; -} - -fn::MutableAttributesRef ParticleAllocator::allocate(int size) -{ - const fn::AttributesInfo &info = attributes_allocator_.attributes_info(); - fn::MutableAttributesRef attributes = attributes_allocator_.allocate_uninitialized(size); - for (int i : info.index_range()) { - const fn::CPPType &type = info.type_of(i); - StringRef name = info.name_of(i); - if (name == "ID") { - int start_id = next_id_.fetch_add(size); - MutableSpan<int> ids = attributes.get<int>("ID"); - for (int pindex : IndexRange(size)) { - ids[pindex] = start_id + pindex; - } - } - else if (name == "Hash") { - MutableSpan<int> hashes = attributes.get<int>("Hash"); - RandomNumberGenerator rng(hash_seed_ ^ static_cast<uint32_t>(next_id_)); - for (int pindex : IndexRange(size)) { - hashes[pindex] = static_cast<int>(rng.get_uint32()); - } - } - else { - type.fill_uninitialized(info.default_of(i), attributes.get(i).data(), size); - } - } - return attributes; -} - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/particle_allocator.hh b/source/blender/simulation/intern/particle_allocator.hh deleted file mode 100644 index c0bbdb845d9..00000000000 --- a/source/blender/simulation/intern/particle_allocator.hh +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "BLI_array.hh" -#include "BLI_vector.hh" - -#include "FN_attributes_ref.hh" - -#include <atomic> -#include <mutex> - -namespace blender::sim { - -class AttributesAllocator : NonCopyable, NonMovable { - private: - struct AttributesBlock { - Array<void *> buffers; - int size; - }; - - const fn::AttributesInfo &attributes_info_; - Vector<std::unique_ptr<AttributesBlock>> allocated_blocks_; - Vector<fn::MutableAttributesRef> allocated_attributes_; - int total_allocated_ = 0; - std::mutex mutex_; - - public: - AttributesAllocator(const fn::AttributesInfo &attributes_info) - : attributes_info_(attributes_info) - { - } - - ~AttributesAllocator(); - - Span<fn::MutableAttributesRef> get_allocations() const - { - return allocated_attributes_; - } - - int total_allocated() const - { - return total_allocated_; - } - - const fn::AttributesInfo &attributes_info() const - { - return attributes_info_; - } - - fn::MutableAttributesRef allocate_uninitialized(int size); -}; - -class ParticleAllocator : NonCopyable, NonMovable { - private: - AttributesAllocator attributes_allocator_; - std::atomic<int> next_id_; - uint32_t hash_seed_; - - public: - ParticleAllocator(const fn::AttributesInfo &attributes_info, int next_id, uint32_t hash_seed) - : attributes_allocator_(attributes_info), next_id_(next_id), hash_seed_(hash_seed) - { - } - - const fn::AttributesInfo &attributes_info() const - { - return attributes_allocator_.attributes_info(); - } - - Span<fn::MutableAttributesRef> get_allocations() const - { - return attributes_allocator_.get_allocations(); - } - - int total_allocated() const - { - return attributes_allocator_.total_allocated(); - } - - fn::MutableAttributesRef allocate(int size); -}; - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/particle_function.cc b/source/blender/simulation/intern/particle_function.cc deleted file mode 100644 index 69977eb2054..00000000000 --- a/source/blender/simulation/intern/particle_function.cc +++ /dev/null @@ -1,166 +0,0 @@ -/* - * 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_function.hh" - -namespace blender::sim { - -ParticleFunction::ParticleFunction(const fn::MultiFunction *global_fn, - const fn::MultiFunction *per_particle_fn, - Span<const ParticleFunctionInput *> global_inputs, - Span<const ParticleFunctionInput *> per_particle_inputs, - Span<bool> output_is_global) - : global_fn_(global_fn), - per_particle_fn_(per_particle_fn), - global_inputs_(global_inputs), - per_particle_inputs_(per_particle_inputs), - output_is_global_(output_is_global) -{ - for (int i : output_is_global_.index_range()) { - if (output_is_global_[i]) { - int param_index = global_inputs_.size() + global_output_indices_.size(); - fn::MFParamType param_type = global_fn_->param_type(param_index); - BLI_assert(param_type.is_output()); - output_types_.append(param_type.data_type()); - output_names_.append(global_fn_->param_name(param_index)); - global_output_indices_.append(i); - } - else { - int param_index = per_particle_inputs_.size() + per_particle_output_indices_.size(); - fn::MFParamType param_type = per_particle_fn_->param_type(param_index); - BLI_assert(param_type.is_output()); - output_types_.append(param_type.data_type()); - output_names_.append(per_particle_fn_->param_name(param_index)); - per_particle_output_indices_.append(i); - } - } -} - -ParticleFunctionEvaluator::ParticleFunctionEvaluator(const ParticleFunction &particle_fn, - const SimulationSolveContext &solve_context, - const ParticleChunkContext &particles) - : particle_fn_(particle_fn), - solve_context_(solve_context), - particles_(particles), - mask_(particles_.index_mask), - outputs_(particle_fn_.output_types_.size(), nullptr) -{ - global_context_.add_global_context("PersistentDataHandleMap", &solve_context_.handle_map); - per_particle_context_.add_global_context("PersistentDataHandleMap", &solve_context_.handle_map); -} - -ParticleFunctionEvaluator::~ParticleFunctionEvaluator() -{ - for (int output_index : outputs_.index_range()) { - void *buffer = outputs_[output_index]; - fn::MFDataType data_type = particle_fn_.output_types_[output_index]; - BLI_assert(data_type.is_single()); /* For now. */ - const fn::CPPType &type = data_type.single_type(); - - if (particle_fn_.output_is_global_[output_index]) { - type.destruct(buffer); - } - else { - type.destruct_indices(outputs_[0], mask_); - } - } -} - -void ParticleFunctionEvaluator::compute() -{ - BLI_assert(!is_computed_); - this->compute_globals(); - this->compute_per_particle(); - is_computed_ = true; -} - -fn::GVSpan ParticleFunctionEvaluator::get(int output_index, StringRef expected_name) const -{ -#ifdef DEBUG - if (expected_name != "") { - StringRef real_name = particle_fn_.output_names_[output_index]; - BLI_assert(expected_name == real_name); - } - BLI_assert(is_computed_); -#endif - UNUSED_VARS_NDEBUG(expected_name); - const void *buffer = outputs_[output_index]; - const fn::CPPType &type = particle_fn_.output_types_[output_index].single_type(); - if (particle_fn_.output_is_global_[output_index]) { - return fn::GVSpan::FromSingleWithMaxSize(type, buffer); - } - - return fn::GVSpan(fn::GSpan(type, buffer, mask_.min_array_size())); -} - -void ParticleFunctionEvaluator::compute_globals() -{ - if (particle_fn_.global_fn_ == nullptr) { - return; - } - - fn::MFParamsBuilder params(*particle_fn_.global_fn_, mask_.min_array_size()); - - /* Add input parameters. */ - ParticleFunctionInputContext input_context{solve_context_, particles_}; - for (const ParticleFunctionInput *input : particle_fn_.global_inputs_) { - input->add_input(input_context, params, resources_); - } - - /* Add output parameters. */ - for (int output_index : particle_fn_.global_output_indices_) { - fn::MFDataType data_type = particle_fn_.output_types_[output_index]; - BLI_assert(data_type.is_single()); /* For now. */ - - const fn::CPPType &type = data_type.single_type(); - void *buffer = resources_.linear_allocator().allocate(type.size(), type.alignment()); - params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, 1)); - outputs_[output_index] = buffer; - } - - particle_fn_.global_fn_->call({0}, params, global_context_); -} - -void ParticleFunctionEvaluator::compute_per_particle() -{ - if (particle_fn_.per_particle_fn_ == nullptr) { - return; - } - - fn::MFParamsBuilder params(*particle_fn_.per_particle_fn_, mask_.min_array_size()); - - /* Add input parameters. */ - ParticleFunctionInputContext input_context{solve_context_, particles_}; - for (const ParticleFunctionInput *input : particle_fn_.per_particle_inputs_) { - input->add_input(input_context, params, resources_); - } - - /* Add output parameters. */ - for (int output_index : particle_fn_.per_particle_output_indices_) { - fn::MFDataType data_type = particle_fn_.output_types_[output_index]; - BLI_assert(data_type.is_single()); /* For now. */ - - const fn::CPPType &type = data_type.single_type(); - void *buffer = resources_.linear_allocator().allocate(type.size() * mask_.min_array_size(), - type.alignment()); - params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, mask_.min_array_size())); - outputs_[output_index] = buffer; - } - - particle_fn_.per_particle_fn_->call(mask_, params, global_context_); -} - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/particle_function.hh b/source/blender/simulation/intern/particle_function.hh deleted file mode 100644 index ead4e6f3c31..00000000000 --- a/source/blender/simulation/intern/particle_function.hh +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "FN_attributes_ref.hh" -#include "FN_multi_function.hh" - -#include "BLI_resource_collector.hh" - -#include "simulation_solver.hh" - -namespace blender::sim { - -struct ParticleFunctionInputContext { - const SimulationSolveContext &solve_context; - const ParticleChunkContext &particles; -}; - -class ParticleFunctionInput { - public: - virtual ~ParticleFunctionInput() = default; - virtual void add_input(ParticleFunctionInputContext &context, - fn::MFParamsBuilder ¶ms, - ResourceCollector &resources) const = 0; -}; - -class ParticleFunction { - private: - const fn::MultiFunction *global_fn_; - const fn::MultiFunction *per_particle_fn_; - Array<const ParticleFunctionInput *> global_inputs_; - Array<const ParticleFunctionInput *> per_particle_inputs_; - Array<bool> output_is_global_; - Vector<int> global_output_indices_; - Vector<int> per_particle_output_indices_; - Vector<fn::MFDataType> output_types_; - Vector<StringRefNull> output_names_; - - friend class ParticleFunctionEvaluator; - - public: - ParticleFunction(const fn::MultiFunction *global_fn, - const fn::MultiFunction *per_particle_fn, - Span<const ParticleFunctionInput *> global_inputs, - Span<const ParticleFunctionInput *> per_particle_inputs, - Span<bool> output_is_global); -}; - -class ParticleFunctionEvaluator { - private: - ResourceCollector resources_; - const ParticleFunction &particle_fn_; - const SimulationSolveContext &solve_context_; - const ParticleChunkContext &particles_; - IndexMask mask_; - fn::MFContextBuilder global_context_; - fn::MFContextBuilder per_particle_context_; - Vector<void *> outputs_; - bool is_computed_ = false; - - public: - ParticleFunctionEvaluator(const ParticleFunction &particle_fn, - const SimulationSolveContext &solve_context, - const ParticleChunkContext &particles); - ~ParticleFunctionEvaluator(); - - void compute(); - fn::GVSpan get(int output_index, StringRef expected_name = "") const; - - template<typename T> fn::VSpan<T> get(int output_index, StringRef expected_name = "") const - { - return this->get(output_index, expected_name).typed<T>(); - } - - private: - void compute_globals(); - void compute_per_particle(); -}; - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/particle_mesh_emitter.cc b/source/blender/simulation/intern/particle_mesh_emitter.cc deleted file mode 100644 index 3d43d4d8001..00000000000 --- a/source/blender/simulation/intern/particle_mesh_emitter.cc +++ /dev/null @@ -1,362 +0,0 @@ -/* - * 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 "BLI_vector_adaptor.hh" - -#include "BKE_mesh_runtime.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" - -namespace blender::sim { - -ParticleMeshEmitter::~ParticleMeshEmitter() = default; - -struct EmitterSettings { - Object *object; - float rate; -}; - -static BLI_NOINLINE 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.stop()) { - break; - } - if (birth_time <= emit_interval.start()) { - continue; - } - r_birth_times.append(birth_time); - } -} - -static BLI_NOINLINE Span<MLoopTri> get_mesh_triangles(Mesh &mesh) -{ - const MLoopTri *triangles = BKE_mesh_runtime_looptri_ensure(&mesh); - int amount = BKE_mesh_runtime_looptri_len(&mesh); - return Span(triangles, amount); -} - -static BLI_NOINLINE void compute_triangle_areas(Mesh &mesh, - Span<MLoopTri> triangles, - MutableSpan<float> r_areas) -{ - assert_same_size(triangles, r_areas); - - for (int i : triangles.index_range()) { - const MLoopTri &tri = triangles[i]; - - const float3 v1 = mesh.mvert[mesh.mloop[tri.tri[0]].v].co; - const float3 v2 = mesh.mvert[mesh.mloop[tri.tri[1]].v].co; - const float3 v3 = mesh.mvert[mesh.mloop[tri.tri[2]].v].co; - - const float area = area_tri_v3(v1, v2, v3); - r_areas[i] = area; - } -} - -static BLI_NOINLINE void compute_triangle_weights(Mesh &mesh, - Span<MLoopTri> triangles, - MutableSpan<float> r_weights) -{ - assert_same_size(triangles, r_weights); - compute_triangle_areas(mesh, triangles, r_weights); -} - -static BLI_NOINLINE void compute_cumulative_distribution(Span<float> weights, - MutableSpan<float> r_cumulative_weights) -{ - BLI_assert(weights.size() + 1 == r_cumulative_weights.size()); - - r_cumulative_weights[0] = 0; - for (int i : weights.index_range()) { - r_cumulative_weights[i + 1] = r_cumulative_weights[i] + weights[i]; - } -} - -static void sample_cumulative_distribution_recursive(RandomNumberGenerator &rng, - int amount, - int start, - int one_after_end, - Span<float> cumulative_weights, - VectorAdaptor<int> &r_sampled_indices) -{ - BLI_assert(start <= one_after_end); - const int size = one_after_end - start; - if (size == 0) { - BLI_assert(amount == 0); - } - else if (amount == 0) { - return; - } - else if (size == 1) { - r_sampled_indices.append_n_times(start, amount); - } - else { - const int middle = start + size / 2; - const float left_weight = cumulative_weights[middle] - cumulative_weights[start]; - const float right_weight = cumulative_weights[one_after_end] - cumulative_weights[middle]; - BLI_assert(left_weight >= 0.0f && right_weight >= 0.0f); - const float weight_sum = left_weight + right_weight; - BLI_assert(weight_sum > 0.0f); - - const float left_factor = left_weight / weight_sum; - const float right_factor = right_weight / weight_sum; - - int left_amount = amount * left_factor; - int right_amount = amount * right_factor; - - if (left_amount + right_amount < amount) { - BLI_assert(left_amount + right_amount + 1 == amount); - const float weight_per_item = weight_sum / amount; - const float total_remaining_weight = weight_sum - - (left_amount + right_amount) * weight_per_item; - const float left_remaining_weight = left_weight - left_amount * weight_per_item; - const float left_remaining_factor = left_remaining_weight / total_remaining_weight; - if (rng.get_float() < left_remaining_factor) { - left_amount++; - } - else { - right_amount++; - } - } - - sample_cumulative_distribution_recursive( - rng, left_amount, start, middle, cumulative_weights, r_sampled_indices); - sample_cumulative_distribution_recursive( - rng, right_amount, middle, one_after_end, cumulative_weights, r_sampled_indices); - } -} - -static BLI_NOINLINE void sample_cumulative_distribution(RandomNumberGenerator &rng, - Span<float> cumulative_weights, - MutableSpan<int> r_samples) -{ - VectorAdaptor<int> sampled_indices(r_samples); - sample_cumulative_distribution_recursive(rng, - r_samples.size(), - 0, - cumulative_weights.size() - 1, - cumulative_weights, - sampled_indices); - BLI_assert(sampled_indices.is_full()); -} - -static BLI_NOINLINE bool sample_weighted_buckets(RandomNumberGenerator &rng, - Span<float> weights, - MutableSpan<int> r_samples) -{ - Array<float> cumulative_weights(weights.size() + 1); - compute_cumulative_distribution(weights, cumulative_weights); - - if (r_samples.size() > 0 && cumulative_weights.as_span().last() == 0.0f) { - /* All weights are zero. */ - return false; - } - - sample_cumulative_distribution(rng, cumulative_weights, r_samples); - return true; -} - -static BLI_NOINLINE void sample_looptris(RandomNumberGenerator &rng, - Mesh &mesh, - Span<MLoopTri> triangles, - Span<int> triangles_to_sample, - MutableSpan<float3> r_sampled_positions, - MutableSpan<float3> r_sampled_normals) -{ - assert_same_size(triangles_to_sample, r_sampled_positions, r_sampled_normals); - - MLoop *loops = mesh.mloop; - MVert *verts = mesh.mvert; - - for (uint i : triangles_to_sample.index_range()) { - const uint triangle_index = triangles_to_sample[i]; - const MLoopTri &triangle = triangles[triangle_index]; - - const float3 v1 = verts[loops[triangle.tri[0]].v].co; - const float3 v2 = verts[loops[triangle.tri[1]].v].co; - const float3 v3 = verts[loops[triangle.tri[2]].v].co; - - const float3 bary_coords = rng.get_barycentric_coordinates(); - - float3 position; - interp_v3_v3v3v3(position, v1, v2, v3, bary_coords); - - float3 normal; - normal_tri_v3(normal, v1, v2, v3); - - r_sampled_positions[i] = position; - r_sampled_normals[i] = normal; - } -} - -static BLI_NOINLINE bool compute_new_particle_attributes(ParticleEmitterContext &context, - EmitterSettings &settings, - ParticleMeshEmitterSimulationState &state, - Vector<float3> &r_positions, - Vector<float3> &r_velocities, - Vector<float> &r_birth_times) -{ - if (settings.object == nullptr) { - return false; - } - if (settings.rate <= 0.000001f) { - return false; - } - if (settings.object->type != OB_MESH) { - return false; - } - Mesh &mesh = *static_cast<Mesh *>(settings.object->data); - if (mesh.totvert == 0) { - return false; - } - - const float start_time = context.emit_interval.start(); - const uint32_t seed = DefaultHash<StringRef>{}(state.head.name); - RandomNumberGenerator rng{*reinterpret_cast<const uint32_t *>(&start_time) ^ seed}; - - compute_birth_times(settings.rate, context.emit_interval, state, r_birth_times); - const int particle_amount = r_birth_times.size(); - if (particle_amount == 0) { - return false; - } - - const float last_birth_time = r_birth_times.last(); - rng.shuffle(r_birth_times.as_mutable_span()); - - Span<MLoopTri> triangles = get_mesh_triangles(mesh); - if (triangles.is_empty()) { - return false; - } - - Array<float> triangle_weights(triangles.size()); - compute_triangle_weights(mesh, triangles, triangle_weights); - - Array<int> triangles_to_sample(particle_amount); - if (!sample_weighted_buckets(rng, triangle_weights, triangles_to_sample)) { - return false; - } - - r_positions.resize(particle_amount); - r_velocities.resize(particle_amount); - sample_looptris(rng, mesh, triangles, triangles_to_sample, r_positions, r_velocities); - - if (context.solve_context.dependency_animations.is_object_transform_changing(*settings.object)) { - Array<float4x4> local_to_world_matrices(particle_amount); - context.solve_context.dependency_animations.get_object_transforms( - *settings.object, r_birth_times, local_to_world_matrices); - - for (int i : IndexRange(particle_amount)) { - const float4x4 &position_to_world = local_to_world_matrices[i]; - const float4x4 normal_to_world = position_to_world.inverted_transposed_affine(); - r_positions[i] = position_to_world * r_positions[i]; - r_velocities[i] = normal_to_world * r_velocities[i]; - } - } - else { - const float4x4 position_to_world = settings.object->obmat; - const float4x4 normal_to_world = position_to_world.inverted_transposed_affine(); - for (int i : IndexRange(particle_amount)) { - r_positions[i] = position_to_world * r_positions[i]; - r_velocities[i] = normal_to_world * r_velocities[i]; - } - } - - for (int i : IndexRange(particle_amount)) { - r_velocities[i].normalize(); - } - - state.last_birth_time = last_birth_time; - return true; -} - -static BLI_NOINLINE 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; - Vector<float> new_birth_times; - - if (!compute_new_particle_attributes( - context, settings, *state, new_positions, new_velocities, new_birth_times)) { - return; - } - - for (StringRef name : particle_names_) { - ParticleAllocator *allocator = context.try_get_particle_allocator(name); - if (allocator == nullptr) { - continue; - } - - int amount = new_positions.size(); - fn::MutableAttributesRef attributes = allocator->allocate(amount); - - attributes.get<float3>("Position").copy_from(new_positions); - attributes.get<float3>("Velocity").copy_from(new_velocities); - attributes.get<float>("Birth Time").copy_from(new_birth_times); - - if (action_ != nullptr) { - ParticleChunkContext particles{ - *context.solve_context.state_map.lookup<ParticleSimulationState>(name), - IndexRange(amount), - attributes, - nullptr}; - ParticleActionContext action_context{context.solve_context, particles}; - action_->execute(action_context); - } - } -} - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/particle_mesh_emitter.hh b/source/blender/simulation/intern/particle_mesh_emitter.hh deleted file mode 100644 index cdcf2a34e16..00000000000 --- a/source/blender/simulation/intern/particle_mesh_emitter.hh +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "simulation_solver_influences.hh" - -#include "FN_multi_function.hh" - -namespace blender::sim { - -class ParticleMeshEmitter final : public ParticleEmitter { - private: - std::string own_state_name_; - Array<std::string> particle_names_; - const fn::MultiFunction &inputs_fn_; - const ParticleAction *action_; - - public: - ParticleMeshEmitter(std::string own_state_name, - Array<std::string> particle_names, - const fn::MultiFunction &inputs_fn, - const ParticleAction *action) - : own_state_name_(std::move(own_state_name)), - particle_names_(particle_names), - inputs_fn_(inputs_fn), - action_(action) - { - } - - ~ParticleMeshEmitter(); - - void emit(ParticleEmitterContext &context) const override; -}; - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_collect_influences.cc b/source/blender/simulation/intern/simulation_collect_influences.cc deleted file mode 100644 index 818415e5d88..00000000000 --- a/source/blender/simulation/intern/simulation_collect_influences.cc +++ /dev/null @@ -1,907 +0,0 @@ -/* - * 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 "simulation_collect_influences.hh" -#include "particle_function.hh" -#include "particle_mesh_emitter.hh" - -#include "FN_attributes_ref.hh" -#include "FN_multi_function_network_evaluation.hh" -#include "FN_multi_function_network_optimization.hh" - -#include "NOD_node_tree_multi_function.hh" - -#include "DEG_depsgraph_query.h" - -#include "BLI_hash.h" -#include "BLI_rand.hh" -#include "BLI_set.hh" - -namespace blender::sim { - -using fn::GVSpan; -using fn::MFContextBuilder; -using fn::MFDataType; -using fn::MFDummyNode; -using fn::MFFunctionNode; -using fn::MFInputSocket; -using fn::MFNetwork; -using fn::MFNetworkEvaluator; -using fn::MFNode; -using fn::MFOutputSocket; -using fn::MFParamsBuilder; -using fn::MFParamType; -using fn::MultiFunction; -using fn::VSpan; -using nodes::DerivedNodeTree; -using nodes::DInputSocket; -using nodes::DNode; -using nodes::DOutputSocket; -using nodes::DParentNode; -using nodes::MFNetworkTreeMap; -using nodes::NodeTreeRefMap; - -struct DummyDataSources { - Map<const MFOutputSocket *, std::string> particle_attributes; - Set<const MFOutputSocket *> simulation_time; - Set<const MFOutputSocket *> scene_time; -}; - -extern "C" { -void WM_clipboard_text_set(const char *buf, bool selection); -} - -static std::string dnode_to_path(const DNode &dnode) -{ - std::string path; - for (const DParentNode *parent = dnode.parent(); parent; parent = parent->parent()) { - path = parent->node_ref().name() + "/" + path; - } - path = path + dnode.name(); - return path; -} - -struct CollectContext : NonCopyable, NonMovable { - SimulationInfluences &influences; - RequiredStates &required_states; - ResourceCollector &resources; - MFNetworkTreeMap &network_map; - MFNetwork &network; - const DerivedNodeTree &tree; - - DummyDataSources data_sources; - Span<const DNode *> particle_simulation_nodes; - Map<const DNode *, std::string> node_paths; - - CollectContext(SimulationInfluences &influences, - RequiredStates &required_states, - ResourceCollector &resources, - MFNetworkTreeMap &network_map) - : influences(influences), - required_states(required_states), - resources(resources), - network_map(network_map), - network(network_map.network()), - tree(network_map.tree()) - { - particle_simulation_nodes = tree.nodes_by_type("SimulationNodeParticleSimulation"); - } -}; - -static const ParticleAction *create_particle_action(CollectContext &context, - const DOutputSocket &dsocket, - Span<StringRefNull> particle_names); - -static const ParticleAction *create_particle_action(CollectContext &context, - const DInputSocket &dsocket, - Span<StringRefNull> particle_names) -{ - BLI_assert(dsocket.bsocket()->type == SOCK_CONTROL_FLOW); - if (dsocket.linked_sockets().size() != 1) { - return nullptr; - } - return create_particle_action(context, *dsocket.linked_sockets()[0], particle_names); -} - -static StringRefNull get_identifier(CollectContext &context, const DNode &dnode) -{ - return context.node_paths.lookup_or_add_cb(&dnode, [&]() { return dnode_to_path(dnode); }); -} - -static Span<const DNode *> nodes_by_type(CollectContext &context, StringRefNull idname) -{ - return context.tree.nodes_by_type(idname); -} - -static Array<StringRefNull> find_linked_particle_simulations(CollectContext &context, - const DOutputSocket &output_socket) -{ - VectorSet<StringRefNull> names; - for (const DInputSocket *target_socket : output_socket.linked_sockets()) { - if (target_socket->node().idname() == "SimulationNodeParticleSimulation") { - names.add(get_identifier(context, target_socket->node())); - } - } - return names.as_span(); -} - -/* Returns true on success. */ -static bool compute_global_inputs(MFNetworkTreeMap &network_map, - ResourceCollector &resources, - Span<const MFInputSocket *> sockets, - MutableSpan<GMutableSpan> r_results) -{ - int amount = sockets.size(); - if (amount == 0) { - return true; - } - - if (network_map.network().have_dummy_or_unlinked_dependencies(sockets)) { - return false; - } - - MFNetworkEvaluator network_fn{{}, sockets}; - MFParamsBuilder params{network_fn, 1}; - for (int param_index : network_fn.param_indices()) { - MFParamType param_type = network_fn.param_type(param_index); - BLI_assert(param_type.category() == MFParamType::Category::SingleOutput); /* For now. */ - const CPPType &type = param_type.data_type().single_type(); - void *buffer = resources.linear_allocator().allocate(type.size(), type.alignment()); - resources.add(buffer, type.destruct_cb(), AT); - GMutableSpan span{type, buffer, 1}; - r_results[param_index] = span; - params.add_uninitialized_single_output(span); - } - MFContextBuilder context; - network_fn.call(IndexRange(1), params, context); - return true; -} - -static std::optional<Array<std::string>> compute_global_string_inputs( - MFNetworkTreeMap &network_map, Span<const MFInputSocket *> sockets) -{ - ResourceCollector local_resources; - Array<GMutableSpan> computed_values(sockets.size(), NoInitialization()); - if (!compute_global_inputs(network_map, local_resources, sockets, computed_values)) { - return {}; - } - - Array<std::string> strings(sockets.size()); - for (int i : sockets.index_range()) { - strings[i] = std::move(computed_values[i].typed<std::string>()[0]); - } - return strings; -} - -/** - * This will find all the particle attribute input nodes. Then it will compute the attribute names - * by evaluating the network (those names should not depend on per particle data). In the end, - * input nodes that access the same attribute are combined. - */ -static void prepare_particle_attribute_nodes(CollectContext &context) -{ - Span<const DNode *> attribute_dnodes = nodes_by_type(context, "SimulationNodeParticleAttribute"); - - Vector<MFInputSocket *> name_sockets; - for (const DNode *dnode : attribute_dnodes) { - MFInputSocket &name_socket = context.network_map.lookup_dummy(dnode->input(0)); - name_sockets.append(&name_socket); - } - - std::optional<Array<std::string>> attribute_names = compute_global_string_inputs( - context.network_map, name_sockets); - if (!attribute_names.has_value()) { - return; - } - - MultiValueMap<std::pair<std::string, MFDataType>, MFNode *> attribute_nodes_by_name_and_type; - for (int i : attribute_names->index_range()) { - attribute_nodes_by_name_and_type.add( - {(*attribute_names)[i], name_sockets[i]->node().output(0).data_type()}, - &name_sockets[i]->node()); - } - - Map<const MFOutputSocket *, std::string> attribute_inputs; - for (auto item : attribute_nodes_by_name_and_type.items()) { - StringRef attribute_name = item.key.first; - MFDataType data_type = item.key.second; - Span<MFNode *> nodes = item.value; - - MFOutputSocket &new_attribute_socket = context.network.add_input( - "Attribute '" + attribute_name + "'", data_type); - for (MFNode *node : nodes) { - context.network.relink(node->output(0), new_attribute_socket); - } - context.network.remove(nodes); - - context.data_sources.particle_attributes.add_new(&new_attribute_socket, attribute_name); - } -} - -static void prepare_time_input_nodes(CollectContext &context) -{ - Span<const DNode *> time_input_dnodes = nodes_by_type(context, "SimulationNodeTime"); - Vector<const DNode *> simulation_time_inputs; - Vector<const DNode *> scene_time_inputs; - for (const DNode *dnode : time_input_dnodes) { - NodeSimInputTimeType type = (NodeSimInputTimeType)dnode->node_ref().bnode()->custom1; - switch (type) { - case NODE_SIM_INPUT_SIMULATION_TIME: { - simulation_time_inputs.append(dnode); - break; - } - case NODE_SIM_INPUT_SCENE_TIME: { - scene_time_inputs.append(dnode); - break; - } - } - } - - if (simulation_time_inputs.size() > 0) { - MFOutputSocket &new_socket = context.network.add_input("Simulation Time", - MFDataType::ForSingle<float>()); - for (const DNode *dnode : simulation_time_inputs) { - MFOutputSocket &old_socket = context.network_map.lookup_dummy(dnode->output(0)); - context.network.relink(old_socket, new_socket); - context.network.remove(old_socket.node()); - } - context.data_sources.simulation_time.add(&new_socket); - } - if (scene_time_inputs.size() > 0) { - MFOutputSocket &new_socket = context.network.add_input("Scene Time", - MFDataType::ForSingle<float>()); - for (const DNode *dnode : scene_time_inputs) { - MFOutputSocket &old_socket = context.network_map.lookup_dummy(dnode->output(0)); - context.network.relink(old_socket, new_socket); - context.network.remove(old_socket.node()); - } - context.data_sources.scene_time.add(&new_socket); - } -} - -class ParticleAttributeInput : public ParticleFunctionInput { - private: - std::string attribute_name_; - const CPPType &attribute_type_; - - public: - ParticleAttributeInput(std::string attribute_name, const CPPType &attribute_type) - : attribute_name_(std::move(attribute_name)), attribute_type_(attribute_type) - { - } - - void add_input(ParticleFunctionInputContext &context, - MFParamsBuilder ¶ms, - ResourceCollector &UNUSED(resources)) const override - { - std::optional<GSpan> span = context.particles.attributes.try_get(attribute_name_, - attribute_type_); - if (span.has_value()) { - params.add_readonly_single_input(*span); - } - else { - params.add_readonly_single_input(GVSpan::FromDefault(attribute_type_)); - } - } -}; - -class SceneTimeInput : public ParticleFunctionInput { - void add_input(ParticleFunctionInputContext &context, - MFParamsBuilder ¶ms, - ResourceCollector &resources) const override - { - const float time = DEG_get_ctime(&context.solve_context.depsgraph); - float *time_ptr = &resources.construct<float>(AT, time); - params.add_readonly_single_input(time_ptr); - } -}; - -class SimulationTimeInput : public ParticleFunctionInput { - void add_input(ParticleFunctionInputContext &context, - MFParamsBuilder ¶ms, - ResourceCollector &resources) const override - { - /* TODO: Vary this per particle. */ - const float time = context.solve_context.solve_interval.stop(); - float *time_ptr = &resources.construct<float>(AT, time); - params.add_readonly_single_input(time_ptr); - } -}; - -static const ParticleFunction *create_particle_function_for_inputs( - CollectContext &context, Span<const MFInputSocket *> sockets_to_compute) -{ - BLI_assert(sockets_to_compute.size() >= 1); - const MFNetwork &network = sockets_to_compute[0]->node().network(); - - VectorSet<const MFOutputSocket *> dummy_deps; - VectorSet<const MFInputSocket *> unlinked_input_deps; - network.find_dependencies(sockets_to_compute, dummy_deps, unlinked_input_deps); - BLI_assert(unlinked_input_deps.size() == 0); - - Vector<const ParticleFunctionInput *> per_particle_inputs; - for (const MFOutputSocket *socket : dummy_deps) { - if (context.data_sources.particle_attributes.contains(socket)) { - const std::string *attribute_name = context.data_sources.particle_attributes.lookup_ptr( - socket); - if (attribute_name == nullptr) { - return nullptr; - } - per_particle_inputs.append(&context.resources.construct<ParticleAttributeInput>( - AT, *attribute_name, socket->data_type().single_type())); - } - else if (context.data_sources.scene_time.contains(socket)) { - per_particle_inputs.append(&context.resources.construct<SceneTimeInput>(AT)); - } - else if (context.data_sources.simulation_time.contains(socket)) { - per_particle_inputs.append(&context.resources.construct<SimulationTimeInput>(AT)); - } - } - - const MultiFunction &per_particle_fn = context.resources.construct<MFNetworkEvaluator>( - AT, dummy_deps.as_span(), sockets_to_compute); - - Array<bool> output_is_global(sockets_to_compute.size(), false); - - const ParticleFunction &particle_fn = context.resources.construct<ParticleFunction>( - AT, - nullptr, - &per_particle_fn, - Span<const ParticleFunctionInput *>(), - per_particle_inputs.as_span(), - output_is_global.as_span()); - - return &particle_fn; -} - -static const ParticleFunction *create_particle_function_for_inputs( - CollectContext &context, Span<const DInputSocket *> dsockets_to_compute) -{ - Vector<const MFInputSocket *> sockets_to_compute; - for (const DInputSocket *dsocket : dsockets_to_compute) { - const MFInputSocket &socket = context.network_map.lookup_dummy(*dsocket); - sockets_to_compute.append(&socket); - } - return create_particle_function_for_inputs(context, sockets_to_compute); -} - -class ParticleFunctionForce : public ParticleForce { - private: - const ParticleFunction &particle_fn_; - - public: - ParticleFunctionForce(const ParticleFunction &particle_fn) : particle_fn_(particle_fn) - { - } - - void add_force(ParticleForceContext &context) const override - { - IndexMask mask = context.particles.index_mask; - MutableSpan<float3> r_combined_force = context.force_dst; - - ParticleFunctionEvaluator evaluator{particle_fn_, context.solve_context, context.particles}; - evaluator.compute(); - VSpan<float3> forces = evaluator.get<float3>(0, "Force"); - - for (int64_t i : mask) { - r_combined_force[i] += forces[i]; - } - } -}; - -static void create_forces_for_particle_simulation(CollectContext &context, - const DNode &simulation_node) -{ - Vector<const ParticleForce *> forces; - for (const DOutputSocket *origin_socket : simulation_node.input(2, "Forces").linked_sockets()) { - const DNode &origin_node = origin_socket->node(); - if (origin_node.idname() != "SimulationNodeForce") { - continue; - } - - const ParticleFunction *particle_fn = create_particle_function_for_inputs( - context, {&origin_node.input(0, "Force")}); - - if (particle_fn == nullptr) { - continue; - } - - const ParticleForce &force = context.resources.construct<ParticleFunctionForce>(AT, - *particle_fn); - forces.append(&force); - } - - StringRef particle_name = get_identifier(context, simulation_node); - context.influences.particle_forces.add_multiple_as(particle_name, forces); -} - -static void collect_forces(CollectContext &context) -{ - for (const DNode *dnode : context.particle_simulation_nodes) { - create_forces_for_particle_simulation(context, *dnode); - } -} - -static ParticleEmitter *create_particle_emitter(CollectContext &context, const DNode &dnode) -{ - Array<StringRefNull> names = find_linked_particle_simulations(context, dnode.output(0)); - if (names.size() == 0) { - return nullptr; - } - - Array<const MFInputSocket *> input_sockets{2}; - for (int i : input_sockets.index_range()) { - input_sockets[i] = &context.network_map.lookup_dummy(dnode.input(i)); - } - - if (context.network.have_dummy_or_unlinked_dependencies(input_sockets)) { - return nullptr; - } - - MultiFunction &inputs_fn = context.resources.construct<MFNetworkEvaluator>( - AT, Span<const MFOutputSocket *>(), input_sockets.as_span()); - - const ParticleAction *birth_action = create_particle_action( - context, dnode.input(2, "Execute"), names); - - StringRefNull own_state_name = get_identifier(context, dnode); - context.required_states.add(own_state_name, SIM_TYPE_NAME_PARTICLE_MESH_EMITTER); - ParticleEmitter &emitter = context.resources.construct<ParticleMeshEmitter>( - AT, own_state_name, names.as_span(), inputs_fn, birth_action); - return &emitter; -} - -static void collect_emitters(CollectContext &context) -{ - for (const DNode *dnode : nodes_by_type(context, "SimulationNodeParticleMeshEmitter")) { - ParticleEmitter *emitter = create_particle_emitter(context, *dnode); - if (emitter != nullptr) { - context.influences.particle_emitters.append(emitter); - } - } -} - -static void collect_birth_events(CollectContext &context) -{ - for (const DNode *event_dnode : nodes_by_type(context, "SimulationNodeParticleBirthEvent")) { - const DInputSocket &execute_input = event_dnode->input(0); - if (execute_input.linked_sockets().size() != 1) { - continue; - } - - Array<StringRefNull> particle_names = find_linked_particle_simulations(context, - event_dnode->output(0)); - - const DOutputSocket &execute_source = *execute_input.linked_sockets()[0]; - const ParticleAction *action = create_particle_action(context, execute_source, particle_names); - if (action == nullptr) { - continue; - } - - for (StringRefNull particle_name : particle_names) { - context.influences.particle_birth_actions.add_as(particle_name, action); - } - } -} - -static void collect_time_step_events(CollectContext &context) -{ - for (const DNode *event_dnode : nodes_by_type(context, "SimulationNodeParticleTimeStepEvent")) { - const DInputSocket &execute_input = event_dnode->input(0); - Array<StringRefNull> particle_names = find_linked_particle_simulations(context, - event_dnode->output(0)); - - const ParticleAction *action = create_particle_action(context, execute_input, particle_names); - if (action == nullptr) { - continue; - } - - NodeSimParticleTimeStepEventType type = - (NodeSimParticleTimeStepEventType)event_dnode->node_ref().bnode()->custom1; - if (type == NODE_PARTICLE_TIME_STEP_EVENT_BEGIN) { - for (StringRefNull particle_name : particle_names) { - context.influences.particle_time_step_begin_actions.add_as(particle_name, action); - } - } - else { - for (StringRefNull particle_name : particle_names) { - context.influences.particle_time_step_end_actions.add_as(particle_name, action); - } - } - } -} - -class SequenceParticleAction : public ParticleAction { - private: - Vector<const ParticleAction *> actions_; - - public: - SequenceParticleAction(Span<const ParticleAction *> actions) : actions_(std::move(actions)) - { - } - - void execute(ParticleActionContext &context) const override - { - for (const ParticleAction *action : actions_) { - action->execute(context); - } - } -}; - -class SetParticleAttributeAction : public ParticleAction { - private: - std::string attribute_name_; - const CPPType &cpp_type_; - const ParticleFunction &inputs_fn_; - - public: - SetParticleAttributeAction(std::string attribute_name, - const CPPType &cpp_type, - const ParticleFunction &inputs_fn) - : attribute_name_(std::move(attribute_name)), cpp_type_(cpp_type), inputs_fn_(inputs_fn) - { - } - - void execute(ParticleActionContext &context) const override - { - std::optional<GMutableSpan> attribute_array = context.particles.attributes.try_get( - attribute_name_, cpp_type_); - if (!attribute_array.has_value()) { - return; - } - - ParticleFunctionEvaluator evaluator{inputs_fn_, context.solve_context, context.particles}; - evaluator.compute(); - GVSpan values = evaluator.get(0); - - if (values.is_single_element()) { - cpp_type_.fill_initialized_indices( - values.as_single_element(), attribute_array->data(), context.particles.index_mask); - } - else { - GSpan value_array = values.as_full_array(); - cpp_type_.copy_to_initialized_indices( - value_array.data(), attribute_array->data(), context.particles.index_mask); - } - - if (attribute_name_ == "Velocity") { - context.particles.update_diffs_after_velocity_change(); - } - } -}; - -static const ParticleAction *concatenate_actions(CollectContext &context, - Span<const ParticleAction *> actions) -{ - Vector<const ParticleAction *> non_null_actions; - for (const ParticleAction *action : actions) { - if (action != nullptr) { - non_null_actions.append(action); - } - } - if (non_null_actions.size() == 0) { - return nullptr; - } - if (non_null_actions.size() == 1) { - return non_null_actions[0]; - } - return &context.resources.construct<SequenceParticleAction>(AT, std::move(non_null_actions)); -} - -static const ParticleAction *create_set_particle_attribute_action( - CollectContext &context, const DOutputSocket &dsocket, Span<StringRefNull> particle_names) -{ - const DNode &dnode = dsocket.node(); - - const ParticleAction *previous_action = create_particle_action( - context, dnode.input(0), particle_names); - - MFInputSocket &name_socket = context.network_map.lookup_dummy(dnode.input(1)); - MFInputSocket &value_socket = name_socket.node().input(1); - std::optional<Array<std::string>> names = compute_global_string_inputs(context.network_map, - {&name_socket}); - if (!names.has_value()) { - return previous_action; - } - - std::string attribute_name = (*names)[0]; - if (attribute_name.empty()) { - return previous_action; - } - const CPPType &attribute_type = value_socket.data_type().single_type(); - - const ParticleFunction *inputs_fn = create_particle_function_for_inputs(context, - {&value_socket}); - if (inputs_fn == nullptr) { - return previous_action; - } - - for (StringRef particle_name : particle_names) { - context.influences.particle_attributes_builder.lookup_as(particle_name) - ->add(attribute_name, attribute_type); - } - - ParticleAction &this_action = context.resources.construct<SetParticleAttributeAction>( - AT, attribute_name, attribute_type, *inputs_fn); - - return concatenate_actions(context, {previous_action, &this_action}); -} - -class ParticleConditionAction : public ParticleAction { - private: - const ParticleFunction &inputs_fn_; - const ParticleAction *action_true_; - const ParticleAction *action_false_; - - public: - ParticleConditionAction(const ParticleFunction &inputs_fn, - const ParticleAction *action_true, - const ParticleAction *action_false) - : inputs_fn_(inputs_fn), action_true_(action_true), action_false_(action_false) - { - } - - void execute(ParticleActionContext &context) const override - { - ParticleFunctionEvaluator evaluator{inputs_fn_, context.solve_context, context.particles}; - evaluator.compute(); - VSpan<bool> conditions = evaluator.get<bool>(0, "Condition"); - - if (conditions.is_single_element()) { - const bool condition = conditions.as_single_element(); - if (condition) { - if (action_true_ != nullptr) { - action_true_->execute(context); - } - } - else { - if (action_false_ != nullptr) { - action_false_->execute(context); - } - } - } - else { - Span<bool> conditions_array = conditions.as_full_array(); - - Vector<int64_t> true_indices; - Vector<int64_t> false_indices; - for (int i : context.particles.index_mask) { - if (conditions_array[i]) { - true_indices.append(i); - } - else { - false_indices.append(i); - } - } - - if (action_true_ != nullptr) { - ParticleChunkContext chunk_context{context.particles.state, - true_indices.as_span(), - context.particles.attributes, - context.particles.integration}; - ParticleActionContext action_context{context.solve_context, chunk_context}; - action_true_->execute(action_context); - } - if (action_false_ != nullptr) { - ParticleChunkContext chunk_context{context.particles.state, - false_indices.as_span(), - context.particles.attributes, - context.particles.integration}; - ParticleActionContext action_context{context.solve_context, chunk_context}; - action_false_->execute(action_context); - } - } - } -}; - -static const ParticleAction *create_particle_condition_action(CollectContext &context, - const DOutputSocket &dsocket, - Span<StringRefNull> particle_names) -{ - const DNode &dnode = dsocket.node(); - - const ParticleFunction *inputs_fn = create_particle_function_for_inputs( - context, {&dnode.input(0, "Condition")}); - if (inputs_fn == nullptr) { - return nullptr; - } - - const ParticleAction *true_action = create_particle_action( - context, dnode.input(1), particle_names); - const ParticleAction *false_action = create_particle_action( - context, dnode.input(2), particle_names); - - if (true_action == nullptr && false_action == nullptr) { - return nullptr; - } - return &context.resources.construct<ParticleConditionAction>( - AT, *inputs_fn, true_action, false_action); -} - -class KillParticleAction : public ParticleAction { - public: - void execute(ParticleActionContext &context) const override - { - MutableSpan<int> dead_states = context.particles.attributes.get<int>("Dead"); - for (int i : context.particles.index_mask) { - dead_states[i] = true; - } - } -}; - -static const ParticleAction *create_particle_action(CollectContext &context, - const DOutputSocket &dsocket, - Span<StringRefNull> particle_names) -{ - const DNode &dnode = dsocket.node(); - StringRef idname = dnode.idname(); - if (idname == "SimulationNodeSetParticleAttribute") { - return create_set_particle_attribute_action(context, dsocket, particle_names); - } - if (idname == "SimulationNodeExecuteCondition") { - return create_particle_condition_action(context, dsocket, particle_names); - } - if (idname == "SimulationNodeKillParticle") { - return &context.resources.construct<KillParticleAction>(AT); - } - return nullptr; -} - -static void initialize_particle_attribute_builders(CollectContext &context) -{ - for (const DNode *dnode : context.particle_simulation_nodes) { - StringRef name = get_identifier(context, *dnode); - AttributesInfoBuilder &attributes_builder = context.resources.construct<AttributesInfoBuilder>( - AT); - attributes_builder.add<float3>("Position", {0, 0, 0}); - attributes_builder.add<float3>("Velocity", {0, 0, 0}); - attributes_builder.add<int>("ID", 0); - /* TODO: Use bool property, but need to add CD_PROP_BOOL first. */ - attributes_builder.add<int>("Dead", 0); - /* TODO: Use uint32_t, but we don't have a corresponding custom property type. */ - attributes_builder.add<int>("Hash", 0); - attributes_builder.add<float>("Birth Time", 0.0f); - attributes_builder.add<float>("Radius", 0.02f); - context.influences.particle_attributes_builder.add_new(name, &attributes_builder); - } -} - -static void optimize_function_network(CollectContext &context) -{ - fn::mf_network_optimization::constant_folding(context.network, context.resources); - fn::mf_network_optimization::common_subnetwork_elimination(context.network); - fn::mf_network_optimization::dead_node_removal(context.network); - // WM_clipboard_text_set(network.to_dot().c_str(), false); -} - -class AgeReachedEvent : public ParticleEvent { - private: - std::string attribute_name_; - const ParticleFunction &inputs_fn_; - const ParticleAction &action_; - - public: - AgeReachedEvent(std::string attribute_name, - const ParticleFunction &inputs_fn, - const ParticleAction &action) - : attribute_name_(std::move(attribute_name)), inputs_fn_(inputs_fn), action_(action) - { - } - - void filter(ParticleEventFilterContext &context) const override - { - Span<float> birth_times = context.particles.attributes.get<float>("Birth Time"); - std::optional<Span<int>> has_been_triggered = context.particles.attributes.try_get<int>( - attribute_name_); - if (!has_been_triggered.has_value()) { - return; - } - - ParticleFunctionEvaluator evaluator{inputs_fn_, context.solve_context, context.particles}; - evaluator.compute(); - VSpan<float> trigger_ages = evaluator.get<float>(0, "Age"); - - const float end_time = context.particles.integration->end_time; - for (int i : context.particles.index_mask) { - if ((*has_been_triggered)[i]) { - continue; - } - const float trigger_age = trigger_ages[i]; - const float birth_time = birth_times[i]; - const float trigger_time = birth_time + trigger_age; - if (trigger_time > end_time) { - continue; - } - - const float duration = context.particles.integration->durations[i]; - TimeInterval interval(end_time - duration, duration); - const float time_factor = interval.safe_factor_at_time(trigger_time); - - context.factor_dst[i] = std::max<float>(0.0f, time_factor); - } - } - - void execute(ParticleActionContext &context) const override - { - MutableSpan<int> has_been_triggered = context.particles.attributes.get<int>(attribute_name_); - for (int i : context.particles.index_mask) { - has_been_triggered[i] = 1; - } - action_.execute(context); - } -}; - -static void collect_age_reached_events(CollectContext &context) -{ - for (const DNode *dnode : nodes_by_type(context, "SimulationNodeAgeReachedEvent")) { - const DInputSocket &age_input = dnode->input(0, "Age"); - const DInputSocket &execute_input = dnode->input(1, "Execute"); - Array<StringRefNull> particle_names = find_linked_particle_simulations(context, - dnode->output(0)); - const ParticleAction *action = create_particle_action(context, execute_input, particle_names); - if (action == nullptr) { - continue; - } - const ParticleFunction *inputs_fn = create_particle_function_for_inputs(context, {&age_input}); - if (inputs_fn == nullptr) { - continue; - } - - std::string attribute_name = get_identifier(context, *dnode); - const ParticleEvent &event = context.resources.construct<AgeReachedEvent>( - AT, attribute_name, *inputs_fn, *action); - for (StringRefNull particle_name : particle_names) { - const bool added_attribute = context.influences.particle_attributes_builder - .lookup_as(particle_name) - ->add<int>(attribute_name, 0); - if (added_attribute) { - context.influences.particle_events.add_as(particle_name, &event); - } - } - } -} - -void collect_simulation_influences(Simulation &simulation, - ResourceCollector &resources, - SimulationInfluences &r_influences, - RequiredStates &r_required_states) -{ - NodeTreeRefMap tree_refs; - const DerivedNodeTree tree{simulation.nodetree, tree_refs}; - - MFNetwork &network = resources.construct<MFNetwork>(AT); - MFNetworkTreeMap network_map = insert_node_tree_into_mf_network(network, tree, resources); - - CollectContext context{r_influences, r_required_states, resources, network_map}; - initialize_particle_attribute_builders(context); - - prepare_particle_attribute_nodes(context); - prepare_time_input_nodes(context); - - collect_forces(context); - collect_emitters(context); - collect_birth_events(context); - collect_time_step_events(context); - collect_age_reached_events(context); - - optimize_function_network(context); - - for (const DNode *dnode : context.particle_simulation_nodes) { - r_required_states.add(get_identifier(context, *dnode), SIM_TYPE_NAME_PARTICLE_SIMULATION); - } -} - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_collect_influences.hh b/source/blender/simulation/intern/simulation_collect_influences.hh deleted file mode 100644 index 8673a308b04..00000000000 --- a/source/blender/simulation/intern/simulation_collect_influences.hh +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "NOD_derived_node_tree.hh" - -#include "BLI_resource_collector.hh" - -#include "simulation_solver_influences.hh" - -namespace blender::sim { - -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, - 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 deleted file mode 100644 index d53ccd2bd49..00000000000 --- a/source/blender/simulation/intern/simulation_solver.cc +++ /dev/null @@ -1,522 +0,0 @@ -/* - * 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 "simulation_solver.hh" - -#include "BKE_customdata.h" -#include "BKE_persistent_data_handle.hh" - -#include "BLI_rand.hh" -#include "BLI_set.hh" - -#include "DEG_depsgraph_query.h" - -namespace blender::sim { - -static CustomDataType cpp_to_custom_data_type(const CPPType &type) -{ - if (type.is<float3>()) { - return CD_PROP_FLOAT3; - } - if (type.is<float>()) { - return CD_PROP_FLOAT; - } - if (type.is<int32_t>()) { - return CD_PROP_INT32; - } - BLI_assert(false); - return CD_PROP_FLOAT; -} - -static const CPPType &custom_to_cpp_data_type(CustomDataType type) -{ - switch (type) { - case CD_PROP_FLOAT3: - return CPPType::get<float3>(); - case CD_PROP_FLOAT: - return CPPType::get<float>(); - case CD_PROP_INT32: - return CPPType::get<int32_t>(); - default: - BLI_assert(false); - return CPPType::get<float>(); - } -} - -class CustomDataAttributesRef { - private: - Array<void *> buffers_; - int64_t size_; - const AttributesInfo &info_; - - public: - CustomDataAttributesRef(CustomData &custom_data, int64_t size, const AttributesInfo &info) - : buffers_(info.size(), nullptr), size_(size), info_(info) - { - for (int attribute_index : info.index_range()) { - StringRefNull name = info.name_of(attribute_index); - const CPPType &cpp_type = info.type_of(attribute_index); - CustomDataType custom_type = cpp_to_custom_data_type(cpp_type); - void *data = CustomData_get_layer_named(&custom_data, custom_type, name.c_str()); - buffers_[attribute_index] = data; - } - } - - operator MutableAttributesRef() - { - return MutableAttributesRef(info_, buffers_, size_); - } - - operator AttributesRef() const - { - return AttributesRef(info_, buffers_, size_); - } -}; - -static void ensure_attributes_exist(ParticleSimulationState *state, const AttributesInfo &info) -{ - bool found_layer_to_remove; - do { - found_layer_to_remove = false; - for (int layer_index = 0; layer_index < state->attributes.totlayer; layer_index++) { - CustomDataLayer *layer = &state->attributes.layers[layer_index]; - BLI_assert(layer->name != nullptr); - const CPPType &cpp_type = custom_to_cpp_data_type((CustomDataType)layer->type); - StringRefNull name = layer->name; - if (!info.has_attribute(name, cpp_type)) { - found_layer_to_remove = true; - CustomData_free_layer(&state->attributes, layer->type, state->tot_particles, layer_index); - break; - } - } - } while (found_layer_to_remove); - - for (int attribute_index : info.index_range()) { - StringRefNull attribute_name = info.name_of(attribute_index); - const CPPType &cpp_type = info.type_of(attribute_index); - CustomDataType custom_type = cpp_to_custom_data_type(cpp_type); - if (CustomData_get_layer_named(&state->attributes, custom_type, attribute_name.c_str()) == - nullptr) { - void *data = CustomData_add_layer_named(&state->attributes, - custom_type, - CD_CALLOC, - nullptr, - state->tot_particles, - attribute_name.c_str()); - cpp_type.fill_uninitialized(info.default_of(attribute_index), data, state->tot_particles); - } - } -} - -BLI_NOINLINE static void apply_remaining_diffs(ParticleChunkContext &context) -{ - BLI_assert(context.integration != nullptr); - MutableSpan<float3> positions = context.attributes.get<float3>("Position"); - MutableSpan<float3> velocities = context.attributes.get<float3>("Velocity"); - - for (int i : context.index_mask) { - positions[i] += context.integration->position_diffs[i]; - velocities[i] += context.integration->velocity_diffs[i]; - } -} - -BLI_NOINLINE static void find_next_event_per_particle( - SimulationSolveContext &solve_context, - ParticleChunkContext &particles, - Span<const ParticleEvent *> events, - MutableSpan<int> r_next_event_indices, - MutableSpan<float> r_time_factors_to_next_event) -{ - r_next_event_indices.fill_indices(particles.index_mask, -1); - r_time_factors_to_next_event.fill_indices(particles.index_mask, 1.0f); - - Array<float> time_factors(particles.index_mask.min_array_size()); - for (int event_index : events.index_range()) { - time_factors.fill(-1.0f); - ParticleEventFilterContext event_context{solve_context, particles, time_factors}; - const ParticleEvent &event = *events[event_index]; - event.filter(event_context); - - for (int i : particles.index_mask) { - const float time_factor = time_factors[i]; - const float previously_smallest_time_factor = r_time_factors_to_next_event[i]; - if (time_factor >= 0.0f && time_factor <= previously_smallest_time_factor) { - r_time_factors_to_next_event[i] = time_factor; - r_next_event_indices[i] = event_index; - } - } - } -} - -BLI_NOINLINE static void forward_particles_to_next_event_or_end( - ParticleChunkContext &particles, Span<float> time_factors_to_next_event) -{ - MutableSpan<float3> positions = particles.attributes.get<float3>("Position"); - MutableSpan<float3> velocities = particles.attributes.get<float3>("Velocity"); - - MutableSpan<float3> position_diffs = particles.integration->position_diffs; - MutableSpan<float3> velocity_diffs = particles.integration->velocity_diffs; - MutableSpan<float> durations = particles.integration->durations; - - for (int i : particles.index_mask) { - const float time_factor = time_factors_to_next_event[i]; - positions[i] += position_diffs[i] * time_factor; - velocities[i] += velocity_diffs[i] * time_factor; - - const float remaining_time_factor = 1.0f - time_factor; - position_diffs[i] *= remaining_time_factor; - velocity_diffs[i] *= remaining_time_factor; - durations[i] *= remaining_time_factor; - } -} - -BLI_NOINLINE static void group_particles_by_event( - IndexMask mask, - Span<int> next_event_indices, - MutableSpan<Vector<int64_t>> r_particles_per_event) -{ - for (int i : mask) { - int event_index = next_event_indices[i]; - if (event_index >= 0) { - r_particles_per_event[event_index].append(i); - } - } -} - -BLI_NOINLINE static void execute_events(SimulationSolveContext &solve_context, - ParticleChunkContext &all_particles, - Span<const ParticleEvent *> events, - Span<Vector<int64_t>> particles_per_event) -{ - for (int event_index : events.index_range()) { - Span<int64_t> pindices = particles_per_event[event_index]; - if (pindices.is_empty()) { - continue; - } - - const ParticleEvent &event = *events[event_index]; - ParticleChunkContext particles{ - all_particles.state, pindices, all_particles.attributes, all_particles.integration}; - ParticleActionContext action_context{solve_context, particles}; - event.execute(action_context); - } -} - -BLI_NOINLINE static void find_unfinished_particles(IndexMask index_mask, - Span<float> time_factors_to_next_event, - Vector<int64_t> &r_unfinished_pindices) -{ - for (int i : index_mask) { - float time_factor = time_factors_to_next_event[i]; - if (time_factor < 1.0f) { - r_unfinished_pindices.append(i); - } - } -} - -BLI_NOINLINE static void simulate_to_next_event(SimulationSolveContext &solve_context, - ParticleChunkContext &particles, - Span<const ParticleEvent *> events, - Vector<int64_t> &r_unfinished_pindices) -{ - int array_size = particles.index_mask.min_array_size(); - Array<int> next_event_indices(array_size); - Array<float> time_factors_to_next_event(array_size); - - find_next_event_per_particle( - solve_context, particles, events, next_event_indices, time_factors_to_next_event); - - forward_particles_to_next_event_or_end(particles, time_factors_to_next_event); - - Array<Vector<int64_t>> particles_per_event(events.size()); - group_particles_by_event(particles.index_mask, next_event_indices, particles_per_event); - - execute_events(solve_context, particles, events, particles_per_event); - find_unfinished_particles( - particles.index_mask, time_factors_to_next_event, r_unfinished_pindices); -} - -BLI_NOINLINE static void simulate_with_max_n_events(SimulationSolveContext &solve_context, - ParticleSimulationState &state, - ParticleChunkContext &particles, - int max_events) -{ - Span<const ParticleEvent *> events = solve_context.influences.particle_events.lookup_as( - state.head.name); - if (events.size() == 0) { - apply_remaining_diffs(particles); - return; - } - - Vector<int64_t> unfininished_pindices = particles.index_mask.indices(); - for (int iteration : IndexRange(max_events)) { - UNUSED_VARS(iteration); - if (unfininished_pindices.is_empty()) { - break; - } - - Vector<int64_t> new_unfinished_pindices; - ParticleChunkContext remaining_particles{particles.state, - unfininished_pindices.as_span(), - particles.attributes, - particles.integration}; - simulate_to_next_event(solve_context, remaining_particles, events, new_unfinished_pindices); - unfininished_pindices = std::move(new_unfinished_pindices); - } - - if (!unfininished_pindices.is_empty()) { - ParticleChunkContext remaining_particles{particles.state, - unfininished_pindices.as_span(), - particles.attributes, - particles.integration}; - apply_remaining_diffs(remaining_particles); - } -} - -BLI_NOINLINE static void simulate_particle_chunk(SimulationSolveContext &solve_context, - ParticleSimulationState &state, - MutableAttributesRef attributes, - MutableSpan<float> remaining_durations, - float end_time) -{ - int particle_amount = attributes.size(); - - Span<const ParticleAction *> begin_actions = - solve_context.influences.particle_time_step_begin_actions.lookup_as(state.head.name); - for (const ParticleAction *action : begin_actions) { - ParticleChunkContext particles{state, IndexMask(particle_amount), attributes}; - ParticleActionContext action_context{solve_context, particles}; - action->execute(action_context); - } - - Array<float3> force_vectors{particle_amount, {0, 0, 0}}; - Span<const ParticleForce *> forces = solve_context.influences.particle_forces.lookup_as( - state.head.name); - for (const ParticleForce *force : forces) { - ParticleChunkContext particles{state, IndexMask(particle_amount), attributes}; - ParticleForceContext particle_force_context{solve_context, particles, force_vectors}; - force->add_force(particle_force_context); - } - - MutableSpan<float3> velocities = attributes.get<float3>("Velocity"); - - Array<float3> position_diffs(particle_amount); - Array<float3> velocity_diffs(particle_amount); - for (int i : IndexRange(particle_amount)) { - const float time_step = remaining_durations[i]; - velocity_diffs[i] = force_vectors[i] * time_step; - position_diffs[i] = (velocities[i] + velocity_diffs[i] / 2.0f) * time_step; - } - - ParticleChunkIntegrationContext integration_context = { - position_diffs, velocity_diffs, remaining_durations, end_time}; - ParticleChunkContext particle_chunk_context{ - state, IndexMask(particle_amount), attributes, &integration_context}; - - simulate_with_max_n_events(solve_context, state, particle_chunk_context, 10); - - Span<const ParticleAction *> end_actions = - solve_context.influences.particle_time_step_end_actions.lookup_as(state.head.name); - for (const ParticleAction *action : end_actions) { - ParticleChunkContext particles{state, IndexMask(particle_amount), attributes}; - ParticleActionContext action_context{solve_context, particles}; - action->execute(action_context); - } -} - -BLI_NOINLINE static void simulate_existing_particles(SimulationSolveContext &solve_context, - ParticleSimulationState &state, - const AttributesInfo &attributes_info) -{ - CustomDataAttributesRef custom_data_attributes{ - state.attributes, state.tot_particles, attributes_info}; - MutableAttributesRef attributes = custom_data_attributes; - - Array<float> remaining_durations(state.tot_particles, solve_context.solve_interval.duration()); - simulate_particle_chunk( - solve_context, state, attributes, remaining_durations, solve_context.solve_interval.stop()); -} - -BLI_NOINLINE static void run_emitters(SimulationSolveContext &solve_context, - ParticleAllocators &particle_allocators) -{ - for (const ParticleEmitter *emitter : solve_context.influences.particle_emitters) { - ParticleEmitterContext emitter_context{ - solve_context, particle_allocators, solve_context.solve_interval}; - emitter->emit(emitter_context); - } -} - -BLI_NOINLINE static int count_particles_after_time_step(ParticleSimulationState &state, - ParticleAllocator &allocator) -{ - CustomDataAttributesRef custom_data_attributes{ - state.attributes, state.tot_particles, allocator.attributes_info()}; - MutableAttributesRef attributes = custom_data_attributes; - int new_particle_amount = attributes.get<int>("Dead").count(0); - - for (MutableAttributesRef emitted_attributes : allocator.get_allocations()) { - new_particle_amount += emitted_attributes.get<int>("Dead").count(0); - } - - return new_particle_amount; -} - -BLI_NOINLINE static void remove_dead_and_add_new_particles(ParticleSimulationState &state, - ParticleAllocator &allocator) -{ - const int new_particle_amount = count_particles_after_time_step(state, allocator); - - CustomDataAttributesRef custom_data_attributes{ - state.attributes, state.tot_particles, allocator.attributes_info()}; - - Vector<MutableAttributesRef> particle_sources; - particle_sources.append(custom_data_attributes); - particle_sources.extend(allocator.get_allocations()); - - CustomDataLayer *dead_layer = nullptr; - - for (CustomDataLayer &layer : MutableSpan(state.attributes.layers, state.attributes.totlayer)) { - StringRefNull name = layer.name; - if (name == "Dead") { - dead_layer = &layer; - continue; - } - const CPPType &cpp_type = custom_to_cpp_data_type((CustomDataType)layer.type); - GMutableSpan new_buffer{ - cpp_type, - MEM_mallocN_aligned(new_particle_amount * cpp_type.size(), cpp_type.alignment(), AT), - new_particle_amount}; - - int current = 0; - for (MutableAttributesRef attributes : particle_sources) { - Span<int> dead_states = attributes.get<int>("Dead"); - GSpan source_buffer = attributes.get(name); - BLI_assert(source_buffer.type() == cpp_type); - for (int i : attributes.index_range()) { - if (dead_states[i] == 0) { - cpp_type.copy_to_uninitialized(source_buffer[i], new_buffer[current]); - current++; - } - } - } - - if (layer.data != nullptr) { - MEM_freeN(layer.data); - } - layer.data = new_buffer.data(); - } - - BLI_assert(dead_layer != nullptr); - if (dead_layer->data != nullptr) { - MEM_freeN(dead_layer->data); - } - dead_layer->data = MEM_callocN(sizeof(int) * new_particle_amount, AT); - - state.tot_particles = new_particle_amount; - state.next_particle_id += allocator.total_allocated(); -} - -void initialize_simulation_states(Simulation &simulation, - Depsgraph &UNUSED(depsgraph), - const SimulationInfluences &UNUSED(influences), - const bke::PersistentDataHandleMap &UNUSED(handle_map)) -{ - simulation.current_simulation_time = 0.0f; -} - -void solve_simulation_time_step(Simulation &simulation, - Depsgraph &depsgraph, - const SimulationInfluences &influences, - const bke::PersistentDataHandleMap &handle_map, - const DependencyAnimations &dependency_animations, - float time_step) -{ - 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, - dependency_animations}; - - Span<ParticleSimulationState *> particle_simulation_states = - state_map.lookup<ParticleSimulationState>(); - - Map<std::string, std::unique_ptr<AttributesInfo>> attribute_infos; - Map<std::string, std::unique_ptr<ParticleAllocator>> particle_allocators_map; - for (ParticleSimulationState *state : particle_simulation_states) { - const AttributesInfoBuilder &builder = *influences.particle_attributes_builder.lookup_as( - state->head.name); - auto info = std::make_unique<AttributesInfo>(builder); - - ensure_attributes_exist(state, *info); - - uint32_t hash_seed = DefaultHash<StringRef>{}(state->head.name); - particle_allocators_map.add_new( - state->head.name, - std::make_unique<ParticleAllocator>(*info, state->next_particle_id, hash_seed)); - attribute_infos.add_new(state->head.name, std::move(info)); - } - - ParticleAllocators particle_allocators{particle_allocators_map}; - - for (ParticleSimulationState *state : particle_simulation_states) { - const AttributesInfo &attributes_info = *attribute_infos.lookup_as(state->head.name); - simulate_existing_particles(solve_context, *state, attributes_info); - } - - run_emitters(solve_context, particle_allocators); - - for (ParticleSimulationState *state : particle_simulation_states) { - ParticleAllocator &allocator = *particle_allocators.try_get_allocator(state->head.name); - - for (MutableAttributesRef attributes : allocator.get_allocations()) { - Span<const ParticleAction *> actions = influences.particle_birth_actions.lookup_as( - state->head.name); - for (const ParticleAction *action : actions) { - ParticleChunkContext chunk_context{*state, IndexRange(attributes.size()), attributes}; - ParticleActionContext action_context{solve_context, chunk_context}; - action->execute(action_context); - } - } - } - - for (ParticleSimulationState *state : particle_simulation_states) { - ParticleAllocator &allocator = *particle_allocators.try_get_allocator(state->head.name); - - for (MutableAttributesRef attributes : allocator.get_allocations()) { - Array<float> remaining_durations(attributes.size()); - Span<float> birth_times = attributes.get<float>("Birth Time"); - const float end_time = solve_context.solve_interval.stop(); - for (int i : attributes.index_range()) { - remaining_durations[i] = end_time - birth_times[i]; - } - simulate_particle_chunk(solve_context, *state, attributes, remaining_durations, end_time); - } - - remove_dead_and_add_new_particles(*state, allocator); - } - - simulation.current_simulation_time = solve_context.solve_interval.stop(); -} - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_solver.hh b/source/blender/simulation/intern/simulation_solver.hh deleted file mode 100644 index 2cf8eb2aa27..00000000000 --- a/source/blender/simulation/intern/simulation_solver.hh +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "simulation_collect_influences.hh" - -struct Depsgraph; - -namespace blender::sim { - -void initialize_simulation_states(Simulation &simulation, - Depsgraph &depsgraph, - const SimulationInfluences &influences, - const bke::PersistentDataHandleMap &handle_map); - -void solve_simulation_time_step(Simulation &simulation, - Depsgraph &depsgraph, - const SimulationInfluences &influences, - const bke::PersistentDataHandleMap &handle_map, - const DependencyAnimations &dependency_animations, - float time_step); - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_solver_influences.cc b/source/blender/simulation/intern/simulation_solver_influences.cc deleted file mode 100644 index 3485d7c7bfb..00000000000 --- a/source/blender/simulation/intern/simulation_solver_influences.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 "simulation_solver_influences.hh" - -#include "DNA_object_types.h" - -namespace blender::sim { - -ParticleForce::~ParticleForce() -{ -} - -ParticleEmitter::~ParticleEmitter() -{ -} - -ParticleAction::~ParticleAction() -{ -} - -ParticleEvent::~ParticleEvent() -{ -} - -DependencyAnimations::~DependencyAnimations() -{ -} - -bool DependencyAnimations::is_object_transform_changing(Object &UNUSED(object)) const -{ - return false; -} - -void DependencyAnimations::get_object_transforms(Object &object, - Span<float> simulation_times, - MutableSpan<float4x4> r_transforms) const -{ - assert_same_size(simulation_times, r_transforms); - float4x4 world_matrix = object.obmat; - r_transforms.fill(world_matrix); -} - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_solver_influences.hh b/source/blender/simulation/intern/simulation_solver_influences.hh deleted file mode 100644 index d33aec855b2..00000000000 --- a/source/blender/simulation/intern/simulation_solver_influences.hh +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "BLI_float3.hh" -#include "BLI_float4x4.hh" -#include "BLI_multi_value_map.hh" -#include "BLI_span.hh" - -#include "DNA_simulation_types.h" - -#include "FN_attributes_ref.hh" - -#include "BKE_persistent_data_handle.hh" -#include "BKE_simulation.h" - -#include "particle_allocator.hh" -#include "time_interval.hh" - -namespace blender::sim { - -using fn::AttributesInfo; -using fn::AttributesInfoBuilder; -using fn::AttributesRef; -using fn::CPPType; -using fn::GMutableSpan; -using fn::GSpan; -using fn::MutableAttributesRef; - -struct ParticleActionContext; -struct ParticleEmitterContext; -struct ParticleEventFilterContext; -struct ParticleForceContext; - -class ParticleEmitter { - public: - virtual ~ParticleEmitter(); - virtual void emit(ParticleEmitterContext &context) const = 0; -}; - -class ParticleForce { - public: - virtual ~ParticleForce(); - virtual void add_force(ParticleForceContext &context) const = 0; -}; - -class ParticleAction { - public: - virtual ~ParticleAction(); - virtual void execute(ParticleActionContext &context) const = 0; -}; - -class ParticleEvent { - public: - virtual ~ParticleEvent(); - virtual void filter(ParticleEventFilterContext &context) const = 0; - virtual void execute(ParticleActionContext &context) const = 0; -}; - -struct SimulationInfluences { - MultiValueMap<std::string, const ParticleForce *> particle_forces; - MultiValueMap<std::string, const ParticleAction *> particle_birth_actions; - MultiValueMap<std::string, const ParticleAction *> particle_time_step_begin_actions; - MultiValueMap<std::string, const ParticleAction *> particle_time_step_end_actions; - MultiValueMap<std::string, const ParticleEvent *> particle_events; - Map<std::string, AttributesInfoBuilder *> particle_attributes_builder; - Vector<const ParticleEmitter *> particle_emitters; -}; - -class SimulationStateMap { - private: - Map<StringRefNull, SimulationState *> states_by_name_; - MultiValueMap<StringRefNull, SimulationState *> states_by_type_; - - public: - void add(SimulationState *state) - { - states_by_name_.add_new(state->name, state); - states_by_type_.add(state->type, state); - } - - template<typename StateType> StateType *lookup(StringRef name) const - { - const char *type = BKE_simulation_get_state_type_name<StateType>(); - return reinterpret_cast<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 - { - return states_by_type_.lookup_as(type); - } -}; - -class DependencyAnimations { - public: - ~DependencyAnimations(); - - virtual bool is_object_transform_changing(Object &object) const; - virtual void get_object_transforms(Object &object, - Span<float> simulation_times, - MutableSpan<float4x4> r_transforms) const; -}; - -struct SimulationSolveContext { - Simulation &simulation; - Depsgraph &depsgraph; - const SimulationInfluences &influences; - TimeInterval solve_interval; - const SimulationStateMap &state_map; - const bke::PersistentDataHandleMap &handle_map; - const DependencyAnimations &dependency_animations; -}; - -class ParticleAllocators { - private: - Map<std::string, std::unique_ptr<ParticleAllocator>> &allocators_; - - public: - ParticleAllocators(Map<std::string, std::unique_ptr<ParticleAllocator>> &allocators) - : allocators_(allocators) - { - } - - ParticleAllocator *try_get_allocator(StringRef particle_simulation_name) - { - auto *ptr = allocators_.lookup_ptr_as(particle_simulation_name); - if (ptr != nullptr) { - return ptr->get(); - } - else { - return nullptr; - } - } -}; - -struct ParticleChunkIntegrationContext { - MutableSpan<float3> position_diffs; - MutableSpan<float3> velocity_diffs; - MutableSpan<float> durations; - float end_time; -}; - -struct ParticleChunkContext { - ParticleSimulationState &state; - IndexMask index_mask; - MutableAttributesRef attributes; - ParticleChunkIntegrationContext *integration = nullptr; - - void update_diffs_after_velocity_change() - { - if (integration == nullptr) { - return; - } - - Span<float> remaining_durations = integration->durations; - MutableSpan<float3> position_diffs = integration->position_diffs; - Span<float3> velocities = attributes.get<float3>("Velocity"); - - for (int i : index_mask) { - const float duration = remaining_durations[i]; - /* This is certainly not a perfect way to "re-integrate" the velocity, but it should be good - * enough for most use cases. Changing the velocity in an instant is not physically correct - * anyway. */ - position_diffs[i] = velocities[i] * duration; - } - } -}; - -struct ParticleEmitterContext { - SimulationSolveContext &solve_context; - ParticleAllocators &particle_allocators; - TimeInterval emit_interval; - - template<typename StateType> StateType *lookup_state(StringRef name) - { - return solve_context.state_map.lookup<StateType>(name); - } - - ParticleAllocator *try_get_particle_allocator(StringRef particle_simulation_name) - { - return particle_allocators.try_get_allocator(particle_simulation_name); - } -}; - -struct ParticleForceContext { - SimulationSolveContext &solve_context; - ParticleChunkContext &particles; - MutableSpan<float3> force_dst; -}; - -struct ParticleActionContext { - SimulationSolveContext &solve_context; - ParticleChunkContext &particles; -}; - -struct ParticleEventFilterContext { - SimulationSolveContext &solve_context; - ParticleChunkContext &particles; - MutableSpan<float> factor_dst; -}; - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/simulation_update.cc b/source/blender/simulation/intern/simulation_update.cc deleted file mode 100644 index 452b222bb08..00000000000 --- a/source/blender/simulation/intern/simulation_update.cc +++ /dev/null @@ -1,357 +0,0 @@ -/* - * 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 "SIM_simulation_update.hh" - -#include "BKE_customdata.h" -#include "BKE_lib_id.h" -#include "BKE_object.h" -#include "BKE_simulation.h" - -#include "DNA_modifier_types.h" -#include "DNA_scene_types.h" -#include "DNA_simulation_types.h" - -#include "DEG_depsgraph_query.h" - -#include "BLI_array.hh" -#include "BLI_float3.hh" -#include "BLI_listbase.h" -#include "BLI_map.hh" -#include "BLI_rand.h" -#include "BLI_set.hh" -#include "BLI_vector.hh" - -#include "NOD_node_tree_dependencies.hh" - -#include "particle_function.hh" -#include "simulation_collect_influences.hh" -#include "simulation_solver.hh" - -namespace blender::sim { - -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 (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 RequiredStates &required_states) -{ - LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) { - if (!required_states.is_required(state->name, state->type)) { - BKE_simulation_state_remove(simulation, state); - } - } -} - -static void add_missing_states(Simulation *simulation, const RequiredStates &required_states) -{ - for (auto &&item : required_states.states().items()) { - const char *name = item.key.c_str(); - const char *type = item.value; - - SimulationState *state = BKE_simulation_state_try_find_by_name_and_type( - simulation, name, type); - - if (state == nullptr) { - BKE_simulation_state_add(simulation, type, name); - } - } -} - -static void reinitialize_empty_simulation_states(Simulation *simulation, - const RequiredStates &required_states) -{ - 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 RequiredStates &required_states) -{ - remove_unused_states(simulation, required_states); - add_missing_states(simulation, required_states); -} - -class SampledDependencyAnimations : public DependencyAnimations { - private: - TimeInterval simulation_time_interval_; - MultiValueMap<Object *, float4x4> object_transforms_cache_; - - public: - SampledDependencyAnimations(TimeInterval simulation_time_interval) - : simulation_time_interval_(simulation_time_interval) - { - } - - void add_object_transforms(Object &object, Span<float4x4> transforms) - { - object_transforms_cache_.add_multiple(&object, transforms); - } - - bool is_object_transform_changing(Object &object) const - { - return object_transforms_cache_.lookup(&object).size() >= 2; - } - - void get_object_transforms(Object &object, - Span<float> simulation_times, - MutableSpan<float4x4> r_transforms) const - { - assert_same_size(simulation_times, r_transforms); - Span<float4x4> cached_transforms = object_transforms_cache_.lookup(&object); - if (cached_transforms.size() == 0) { - r_transforms.fill(object.obmat); - return; - } - if (cached_transforms.size() == 1) { - r_transforms.fill(cached_transforms[0]); - return; - } - - for (int i : simulation_times.index_range()) { - const float simulation_time = simulation_times[i]; - if (simulation_time <= simulation_time_interval_.start()) { - r_transforms[i] = cached_transforms.first(); - continue; - } - if (simulation_time >= simulation_time_interval_.stop()) { - r_transforms[i] = cached_transforms.last(); - continue; - } - const float factor = simulation_time_interval_.factor_at_time(simulation_time); - BLI_assert(factor > 0.0f && factor < 1.0f); - const float scaled_factor = factor * (cached_transforms.size() - 1); - const int lower_sample = static_cast<int>(scaled_factor); - const int upper_sample = lower_sample + 1; - const float mix_factor = scaled_factor - lower_sample; - r_transforms[i] = float4x4::interpolate( - cached_transforms[lower_sample], cached_transforms[upper_sample], mix_factor); - } - } -}; - -static void sample_object_transforms(Object &object, - Depsgraph &depsgraph, - Scene &scene, - TimeInterval scene_frame_interval, - MutableSpan<float4x4> r_transforms) -{ - if (r_transforms.size() == 0) { - return; - } - if (r_transforms.size() == 1) { - r_transforms[0] = object.obmat; - return; - } - - Array<float> frames(r_transforms.size()); - scene_frame_interval.compute_uniform_samples(frames); - - for (int i : frames.index_range()) { - float frame = frames[i]; - const int recursion_depth = 5; - BKE_object_modifier_update_subframe( - &depsgraph, &scene, &object, false, recursion_depth, frame, eModifierType_None); - r_transforms[i] = object.obmat; - } -} - -template<typename T> static bool all_values_equal(Span<T> values) -{ - if (values.size() == 0) { - return true; - } - for (const T &value : values.drop_front(1)) { - if (value != values[0]) { - return false; - } - } - return true; -} - -static void prepare_dependency_animations(Depsgraph &depsgraph, - Scene &scene, - Simulation &simulation, - TimeInterval scene_frame_interval, - SampledDependencyAnimations &r_dependency_animations) -{ - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation.dependencies) { - ID *id_cow = DEG_get_evaluated_id(&depsgraph, dependency->id); - if (id_cow == nullptr) { - continue; - } - if (GS(id_cow->name) != ID_OB) { - continue; - } - Object &object_cow = *reinterpret_cast<Object *>(id_cow); - constexpr int sample_count = 10; - Array<float4x4, sample_count> transforms(sample_count); - sample_object_transforms(object_cow, depsgraph, scene, scene_frame_interval, transforms); - - /* If all samples are the same, only store one. */ - Span<float4x4> transforms_to_use = (all_values_equal(transforms.as_span())) ? - transforms.as_span().take_front(1) : - transforms.as_span(); - - r_dependency_animations.add_object_transforms(object_cow, transforms_to_use); - } -} - -void update_simulation_in_depsgraph(Depsgraph *depsgraph, - Scene *scene_cow, - Simulation *simulation_cow) -{ - int current_frame = scene_cow->r.cfra; - if (simulation_cow->current_frame == current_frame) { - return; - } - - /* Below we modify the original state/cache. Only the active depsgraph is allowed to do that. */ - if (!DEG_is_active(depsgraph)) { - return; - } - - Simulation *simulation_orig = reinterpret_cast<Simulation *>( - DEG_get_original_id(&simulation_cow->id)); - - ResourceCollector resources; - SimulationInfluences influences; - RequiredStates required_states; - - collect_simulation_influences(*simulation_cow, resources, influences, required_states); - - bke::PersistentDataHandleMap handle_map; - LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation_orig->dependencies) { - ID *id_cow = DEG_get_evaluated_id(depsgraph, dependency->id); - if (id_cow != nullptr) { - handle_map.add(dependency->handle, *id_cow); - } - } - - if (current_frame == 1) { - reinitialize_empty_simulation_states(simulation_orig, required_states); - - initialize_simulation_states(*simulation_orig, *depsgraph, influences, handle_map); - simulation_orig->current_frame = 1; - - copy_states_to_cow(simulation_orig, simulation_cow); - } - else if (current_frame == simulation_orig->current_frame + 1) { - update_simulation_state_list(simulation_orig, required_states); - - const float fps = scene_cow->r.frs_sec / scene_cow->r.frs_sec_base; - const float time_step = 1.0f / fps; - TimeInterval scene_frame_interval(current_frame - 1, 1); - TimeInterval simulation_time_interval(simulation_orig->current_simulation_time, time_step); - SampledDependencyAnimations dependency_animations{simulation_time_interval}; - prepare_dependency_animations( - *depsgraph, *scene_cow, *simulation_orig, scene_frame_interval, dependency_animations); - - solve_simulation_time_step( - *simulation_orig, *depsgraph, influences, handle_map, dependency_animations, time_step); - simulation_orig->current_frame = current_frame; - - copy_states_to_cow(simulation_orig, simulation_cow); - } -} - -/* Returns true when dependencies have changed. */ -bool update_simulation_dependencies(Simulation *simulation) -{ - nodes::NodeTreeDependencies dependencies = nodes::find_node_tree_dependencies( - *simulation->nodetree); - - ListBase *dependency_list = &simulation->dependencies; - - bool dependencies_changed = false; - - Map<ID *, SimulationDependency *> dependency_by_id; - Map<SimulationDependency *, int> old_flag_by_dependency; - Set<int> used_handles; - - /* Remove unused handle items and clear flags that are reinitialized later. */ - LISTBASE_FOREACH_MUTABLE (SimulationDependency *, dependency, dependency_list) { - if (dependencies.depends_on(dependency->id)) { - dependency_by_id.add_new(dependency->id, dependency); - used_handles.add_new(dependency->handle); - old_flag_by_dependency.add_new(dependency, dependency->flag); - dependency->flag &= ~(SIM_DEPENDS_ON_TRANSFORM | SIM_DEPENDS_ON_GEOMETRY); - } - else { - if (dependency->id != nullptr) { - id_us_min(dependency->id); - } - BLI_remlink(dependency_list, dependency); - MEM_freeN(dependency); - dependencies_changed = true; - } - } - - /* Add handle items for new id dependencies. */ - int next_handle = 0; - for (ID *id : dependencies.id_dependencies()) { - dependency_by_id.lookup_or_add_cb(id, [&]() { - while (used_handles.contains(next_handle)) { - next_handle++; - } - used_handles.add_new(next_handle); - - SimulationDependency *dependency = static_cast<SimulationDependency *>( - MEM_callocN(sizeof(*dependency), AT)); - id_us_plus(id); - dependency->id = id; - dependency->handle = next_handle; - BLI_addtail(dependency_list, dependency); - - return dependency; - }); - } - - /* Set appropriate dependency flags. */ - for (Object *object : dependencies.transform_dependencies()) { - SimulationDependency *dependency = dependency_by_id.lookup(&object->id); - dependency->flag |= SIM_DEPENDS_ON_TRANSFORM; - } - for (Object *object : dependencies.geometry_dependencies()) { - SimulationDependency *dependency = dependency_by_id.lookup(&object->id); - dependency->flag |= SIM_DEPENDS_ON_GEOMETRY; - } - - if (!dependencies_changed) { - /* Check if any flags have changed. */ - LISTBASE_FOREACH (SimulationDependency *, dependency, dependency_list) { - uint32_t old_flag = old_flag_by_dependency.lookup_default(dependency, 0); - uint32_t new_flag = dependency->flag; - if (old_flag != new_flag) { - dependencies_changed = true; - break; - } - } - } - - return dependencies_changed; -} - -} // namespace blender::sim diff --git a/source/blender/simulation/intern/time_interval.hh b/source/blender/simulation/intern/time_interval.hh deleted file mode 100644 index 034628fa9be..00000000000 --- a/source/blender/simulation/intern/time_interval.hh +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include "BLI_utildefines.h" - -namespace blender::sim { - -/** - * The start time is exclusive and the end time is inclusive. If the duration is zero, the interval - * describes a single point in time. - */ -class TimeInterval { - private: - float start_; - float duration_; - - public: - TimeInterval(float start, float duration) : start_(start), duration_(duration) - { - BLI_assert(duration_ >= 0.0f); - } - - float start() const - { - return start_; - } - - float stop() const - { - return start_ + duration_; - } - - float duration() const - { - return duration_; - } - - float time_at_factor(float factor) const - { - return start_ + factor * duration_; - } - - float factor_at_time(float time) const - { - BLI_assert(duration_ > 0.0f); - return (time - start_) / duration_; - } - - float safe_factor_at_time(float time) const - { - if (duration_ > 0.0f) { - return this->factor_at_time(time); - } - return 0.0f; - } - - void compute_uniform_samples(MutableSpan<float> r_samples) const - { - int64_t amount = r_samples.size(); - if (amount == 0) { - return; - } - if (amount == 1) { - r_samples[0] = this->time_at_factor(0.5f); - return; - } - - const float step = duration_ / (float)(amount - 1); - for (int64_t i : r_samples.index_range()) { - r_samples[i] = start_ + i * step; - } - } -}; - -} // namespace blender::sim |