2020-07-17 13:47:57 +02:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2020-07-17 14:23:57 +02:00
|
|
|
#include "SIM_particle_function.hh"
|
2020-07-17 13:47:57 +02:00
|
|
|
#include "SIM_simulation_update.hh"
|
|
|
|
|
|
|
|
|
|
#include "BKE_customdata.h"
|
|
|
|
|
#include "BKE_simulation.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_vector.hh"
|
|
|
|
|
|
2020-07-17 21:19:48 +02:00
|
|
|
#include "simulation_collect_influences.hh"
|
2020-07-17 20:51:52 +02:00
|
|
|
#include "simulation_solver.hh"
|
|
|
|
|
|
2020-07-17 13:47:57 +02:00
|
|
|
namespace blender::sim {
|
|
|
|
|
|
|
|
|
|
static void copy_states_to_cow(Simulation *simulation_orig, Simulation *simulation_cow)
|
|
|
|
|
{
|
|
|
|
|
BKE_simulation_state_remove_all(simulation_cow);
|
|
|
|
|
simulation_cow->current_frame = simulation_orig->current_frame;
|
|
|
|
|
|
|
|
|
|
LISTBASE_FOREACH (SimulationState *, state_orig, &simulation_orig->states) {
|
|
|
|
|
switch ((eSimulationStateType)state_orig->type) {
|
|
|
|
|
case SIM_STATE_TYPE_PARTICLES: {
|
|
|
|
|
ParticleSimulationState *particle_state_orig = (ParticleSimulationState *)state_orig;
|
|
|
|
|
ParticleSimulationState *particle_state_cow = (ParticleSimulationState *)
|
|
|
|
|
BKE_simulation_state_add(simulation_cow, SIM_STATE_TYPE_PARTICLES, state_orig->name);
|
|
|
|
|
particle_state_cow->tot_particles = particle_state_orig->tot_particles;
|
|
|
|
|
CustomData_copy(&particle_state_orig->attributes,
|
|
|
|
|
&particle_state_cow->attributes,
|
|
|
|
|
CD_MASK_ALL,
|
|
|
|
|
CD_DUPLICATE,
|
|
|
|
|
particle_state_orig->tot_particles);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void remove_unused_states(Simulation *simulation, const VectorSet<std::string> &state_names)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) {
|
|
|
|
|
if (!state_names.contains(state->name)) {
|
|
|
|
|
BKE_simulation_state_remove(simulation, state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void reset_states(Simulation *simulation)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
|
|
|
|
|
switch ((eSimulationStateType)state->type) {
|
|
|
|
|
case SIM_STATE_TYPE_PARTICLES: {
|
|
|
|
|
ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
|
|
|
|
|
CustomData_free(&particle_state->attributes, particle_state->tot_particles);
|
|
|
|
|
particle_state->tot_particles = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SimulationState *try_find_state_by_name(Simulation *simulation, StringRef name)
|
|
|
|
|
{
|
|
|
|
|
LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
|
|
|
|
|
if (state->name == name) {
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void add_missing_particle_states(Simulation *simulation, Span<std::string> state_names)
|
|
|
|
|
{
|
|
|
|
|
for (StringRefNull name : state_names) {
|
|
|
|
|
SimulationState *state = try_find_state_by_name(simulation, name);
|
|
|
|
|
if (state != nullptr) {
|
|
|
|
|
BLI_assert(state->type == SIM_STATE_TYPE_PARTICLES);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BKE_simulation_state_add(simulation, SIM_STATE_TYPE_PARTICLES, name.c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void reinitialize_empty_simulation_states(Simulation *simulation,
|
|
|
|
|
const nodes::DerivedNodeTree &tree)
|
|
|
|
|
{
|
|
|
|
|
VectorSet<std::string> state_names;
|
|
|
|
|
for (const nodes::DNode *dnode : tree.nodes_by_type("SimulationNodeParticleSimulation")) {
|
|
|
|
|
state_names.add(dnode_to_path(*dnode));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove_unused_states(simulation, state_names);
|
|
|
|
|
reset_states(simulation);
|
|
|
|
|
add_missing_particle_states(simulation, state_names);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_simulation_state_list(Simulation *simulation,
|
|
|
|
|
const nodes::DerivedNodeTree &tree)
|
|
|
|
|
{
|
|
|
|
|
VectorSet<std::string> state_names;
|
|
|
|
|
for (const nodes::DNode *dnode : tree.nodes_by_type("SimulationNodeParticleSimulation")) {
|
|
|
|
|
state_names.add(dnode_to_path(*dnode));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove_unused_states(simulation, state_names);
|
|
|
|
|
add_missing_particle_states(simulation, state_names);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 = (Simulation *)DEG_get_original_id(&simulation_cow->id);
|
|
|
|
|
|
|
|
|
|
nodes::NodeTreeRefMap tree_refs;
|
|
|
|
|
/* TODO: Use simulation_cow, but need to add depsgraph relations before that. */
|
|
|
|
|
const nodes::DerivedNodeTree tree{simulation_orig->nodetree, tree_refs};
|
|
|
|
|
|
2020-07-17 21:19:48 +02:00
|
|
|
ResourceCollector resources;
|
|
|
|
|
SimulationInfluences influences;
|
|
|
|
|
collect_simulation_influences(tree, resources, influences);
|
2020-07-17 13:47:57 +02:00
|
|
|
|
|
|
|
|
if (current_frame == 1) {
|
|
|
|
|
reinitialize_empty_simulation_states(simulation_orig, tree);
|
|
|
|
|
|
2020-07-17 21:19:48 +02:00
|
|
|
initialize_simulation_states(*simulation_orig, *depsgraph, influences);
|
2020-07-17 13:47:57 +02:00
|
|
|
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, tree);
|
2020-07-17 20:51:52 +02:00
|
|
|
|
2020-07-17 13:47:57 +02:00
|
|
|
float time_step = 1.0f / 24.0f;
|
2020-07-17 21:19:48 +02:00
|
|
|
solve_simulation_time_step(*simulation_orig, *depsgraph, influences, time_step);
|
2020-07-17 13:47:57 +02:00
|
|
|
simulation_orig->current_frame = current_frame;
|
|
|
|
|
|
|
|
|
|
copy_states_to_cow(simulation_orig, simulation_cow);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace blender::sim
|