|
|
|
|
@@ -677,78 +677,115 @@ static void prepare_simulation_states_for_evaluation(const NodesModifierData &nm
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DEG_is_active(ctx.depsgraph)) {
|
|
|
|
|
if (ctx.object->flag & OB_FLAG_USE_SIMULATION_CACHE) {
|
|
|
|
|
if (DEG_is_active(ctx.depsgraph)) {
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
/* Invalidate cached data on user edits. */
|
|
|
|
|
if (nmd.modifier.flag & eModifierFlag_UserModified) {
|
|
|
|
|
if (simulation_cache.cache_state != bke::sim::CacheState::Baked) {
|
|
|
|
|
simulation_cache.invalidate();
|
|
|
|
|
{
|
|
|
|
|
/* Invalidate cached data on user edits. */
|
|
|
|
|
if (nmd.modifier.flag & eModifierFlag_UserModified) {
|
|
|
|
|
if (simulation_cache.cache_state != bke::sim::CacheState::Baked) {
|
|
|
|
|
simulation_cache.invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
/* Reset cached data if necessary. */
|
|
|
|
|
{
|
|
|
|
|
/* Reset cached data if necessary. */
|
|
|
|
|
const bke::sim::StatesAroundFrame sim_states = simulation_cache.get_states_around_frame(
|
|
|
|
|
current_frame);
|
|
|
|
|
if (simulation_cache.cache_state == bke::sim::CacheState::Invalid &&
|
|
|
|
|
(current_frame == start_frame ||
|
|
|
|
|
(sim_states.current == nullptr && sim_states.prev == nullptr &&
|
|
|
|
|
sim_states.next != nullptr)))
|
|
|
|
|
{
|
|
|
|
|
simulation_cache.reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Decide if a new simulation state should be created in this evaluation. */
|
|
|
|
|
const bke::sim::StatesAroundFrame sim_states = simulation_cache.get_states_around_frame(
|
|
|
|
|
current_frame);
|
|
|
|
|
if (simulation_cache.cache_state == bke::sim::CacheState::Invalid &&
|
|
|
|
|
(current_frame == start_frame ||
|
|
|
|
|
(sim_states.current == nullptr && sim_states.prev == nullptr &&
|
|
|
|
|
sim_states.next != nullptr)))
|
|
|
|
|
{
|
|
|
|
|
simulation_cache.reset();
|
|
|
|
|
if (simulation_cache.cache_state != bke::sim::CacheState::Baked) {
|
|
|
|
|
if (sim_states.current == nullptr) {
|
|
|
|
|
if (is_start_frame || !simulation_cache.has_states()) {
|
|
|
|
|
bke::sim::ModifierSimulationState ¤t_sim_state =
|
|
|
|
|
simulation_cache.get_state_at_frame_for_write(current_frame);
|
|
|
|
|
exec_data.current_simulation_state_for_write = ¤t_sim_state;
|
|
|
|
|
exec_data.simulation_time_delta = 0.0f;
|
|
|
|
|
if (!is_start_frame) {
|
|
|
|
|
/* When starting a new simulation at another frame than the start frame,
|
|
|
|
|
* it can't match what would be baked, so invalidate it immediately. */
|
|
|
|
|
simulation_cache.invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (sim_states.prev != nullptr && sim_states.next == nullptr) {
|
|
|
|
|
const float max_delta_frames = 1.0f;
|
|
|
|
|
const float scene_delta_frames = float(current_frame) - float(sim_states.prev->frame);
|
|
|
|
|
const float delta_frames = std::min(max_delta_frames, scene_delta_frames);
|
|
|
|
|
if (delta_frames != scene_delta_frames) {
|
|
|
|
|
simulation_cache.invalidate();
|
|
|
|
|
}
|
|
|
|
|
bke::sim::ModifierSimulationState ¤t_sim_state =
|
|
|
|
|
simulation_cache.get_state_at_frame_for_write(current_frame);
|
|
|
|
|
exec_data.current_simulation_state_for_write = ¤t_sim_state;
|
|
|
|
|
const float delta_seconds = delta_frames / FPS;
|
|
|
|
|
exec_data.simulation_time_delta = delta_seconds;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Decide if a new simulation state should be created in this evaluation. */
|
|
|
|
|
|
|
|
|
|
/* Load read-only states to give nodes access to cached data. */
|
|
|
|
|
const bke::sim::StatesAroundFrame sim_states = simulation_cache.get_states_around_frame(
|
|
|
|
|
current_frame);
|
|
|
|
|
if (simulation_cache.cache_state != bke::sim::CacheState::Baked) {
|
|
|
|
|
if (sim_states.current == nullptr) {
|
|
|
|
|
if (is_start_frame || !simulation_cache.has_states()) {
|
|
|
|
|
bke::sim::ModifierSimulationState ¤t_sim_state =
|
|
|
|
|
simulation_cache.get_state_at_frame_for_write(current_frame);
|
|
|
|
|
exec_data.current_simulation_state_for_write = ¤t_sim_state;
|
|
|
|
|
exec_data.simulation_time_delta = 0.0f;
|
|
|
|
|
if (!is_start_frame) {
|
|
|
|
|
/* When starting a new simulation at another frame than the start frame, it can't match
|
|
|
|
|
* what would be baked, so invalidate it immediately. */
|
|
|
|
|
simulation_cache.invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (sim_states.prev != nullptr && sim_states.next == nullptr) {
|
|
|
|
|
const float max_delta_frames = 1.0f;
|
|
|
|
|
const float scene_delta_frames = float(current_frame) - float(sim_states.prev->frame);
|
|
|
|
|
const float delta_frames = std::min(max_delta_frames, scene_delta_frames);
|
|
|
|
|
if (delta_frames != scene_delta_frames) {
|
|
|
|
|
simulation_cache.invalidate();
|
|
|
|
|
}
|
|
|
|
|
bke::sim::ModifierSimulationState ¤t_sim_state =
|
|
|
|
|
simulation_cache.get_state_at_frame_for_write(current_frame);
|
|
|
|
|
exec_data.current_simulation_state_for_write = ¤t_sim_state;
|
|
|
|
|
const float delta_seconds = delta_frames / FPS;
|
|
|
|
|
exec_data.simulation_time_delta = delta_seconds;
|
|
|
|
|
}
|
|
|
|
|
if (sim_states.current) {
|
|
|
|
|
sim_states.current->state.ensure_bake_loaded(*nmd.node_group);
|
|
|
|
|
exec_data.current_simulation_state = &sim_states.current->state;
|
|
|
|
|
}
|
|
|
|
|
if (sim_states.prev) {
|
|
|
|
|
sim_states.prev->state.ensure_bake_loaded(*nmd.node_group);
|
|
|
|
|
exec_data.prev_simulation_state = &sim_states.prev->state;
|
|
|
|
|
if (sim_states.next) {
|
|
|
|
|
sim_states.next->state.ensure_bake_loaded(*nmd.node_group);
|
|
|
|
|
exec_data.next_simulation_state = &sim_states.next->state;
|
|
|
|
|
exec_data.simulation_state_mix_factor =
|
|
|
|
|
(float(current_frame) - float(sim_states.prev->frame)) /
|
|
|
|
|
(float(sim_states.next->frame) - float(sim_states.prev->frame));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEG_is_active(ctx.depsgraph)) {
|
|
|
|
|
bke::sim::ModifierSimulationCacheRealtime &realtime_cache = simulation_cache.realtime_cache;
|
|
|
|
|
|
|
|
|
|
/* Load read-only states to give nodes access to cached data. */
|
|
|
|
|
const bke::sim::StatesAroundFrame sim_states = simulation_cache.get_states_around_frame(
|
|
|
|
|
current_frame);
|
|
|
|
|
if (sim_states.current) {
|
|
|
|
|
sim_states.current->state.ensure_bake_loaded(*nmd.node_group);
|
|
|
|
|
exec_data.current_simulation_state = &sim_states.current->state;
|
|
|
|
|
}
|
|
|
|
|
if (sim_states.prev) {
|
|
|
|
|
sim_states.prev->state.ensure_bake_loaded(*nmd.node_group);
|
|
|
|
|
exec_data.prev_simulation_state = &sim_states.prev->state;
|
|
|
|
|
if (sim_states.next) {
|
|
|
|
|
sim_states.next->state.ensure_bake_loaded(*nmd.node_group);
|
|
|
|
|
exec_data.next_simulation_state = &sim_states.next->state;
|
|
|
|
|
exec_data.simulation_state_mix_factor =
|
|
|
|
|
(float(current_frame) - float(sim_states.prev->frame)) /
|
|
|
|
|
(float(sim_states.next->frame) - float(sim_states.prev->frame));
|
|
|
|
|
/* Reset the cache when going backwards in time. */
|
|
|
|
|
if (realtime_cache.prev_frame >= current_frame) {
|
|
|
|
|
simulation_cache.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Advance in time, making the last "current" state the new "previous" state. */
|
|
|
|
|
realtime_cache.prev_frame = realtime_cache.current_frame;
|
|
|
|
|
realtime_cache.prev_state = std::move(realtime_cache.current_state);
|
|
|
|
|
if (realtime_cache.prev_state) {
|
|
|
|
|
exec_data.prev_simulation_state = realtime_cache.prev_state.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create a new current state used to pass the data to the next frame. */
|
|
|
|
|
realtime_cache.current_state = std::make_unique<bke::sim::ModifierSimulationState>();
|
|
|
|
|
realtime_cache.current_frame = current_frame;
|
|
|
|
|
exec_data.current_simulation_state_for_write = realtime_cache.current_state.get();
|
|
|
|
|
exec_data.current_simulation_state = exec_data.current_simulation_state_for_write;
|
|
|
|
|
|
|
|
|
|
/* Calculate the delta time. */
|
|
|
|
|
if (realtime_cache.prev_state) {
|
|
|
|
|
const float max_delta_frames = 1.0f;
|
|
|
|
|
const float scene_delta_frames = float(current_frame) - float(realtime_cache.prev_frame);
|
|
|
|
|
const float delta_frames = std::min(max_delta_frames, scene_delta_frames);
|
|
|
|
|
const float delta_seconds = delta_frames / FPS;
|
|
|
|
|
exec_data.simulation_time_delta = delta_seconds;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
exec_data.simulation_time_delta = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -841,14 +878,6 @@ static void modifyGeometry(ModifierData *md,
|
|
|
|
|
nmd_orig->runtime_eval_log = eval_log.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DEG_is_active(ctx->depsgraph)) {
|
|
|
|
|
/* When caching is turned off, remove all states except the last which was just created in this
|
|
|
|
|
* evaluation. Check if active status to avoid changing original data in other depsgraphs. */
|
|
|
|
|
if (!(ctx->object->flag & OB_FLAG_USE_SIMULATION_CACHE)) {
|
|
|
|
|
nmd_orig->simulation_cache->ptr->clear_prev_states();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (use_orig_index_verts || use_orig_index_edges || use_orig_index_polys) {
|
|
|
|
|
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
|
|
|
|
|
/* Add #CD_ORIGINDEX layers if they don't exist already. This is required because the
|
|
|
|
|
|