WIP: Experiment: Geometry Nodes: support baking individual simulations #112179

Closed
Jacques Lucke wants to merge 51 commits from JacquesLucke/blender:simulation-bake-individual into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
6 changed files with 69 additions and 11 deletions
Showing only changes of commit de64899907 - Show all commits

View File

@ -84,6 +84,10 @@ std::optional<BakePath> get_node_bake_path(const Main &bmain,
const Object &object,
const NodesModifierData &nmd,
int node_id);
std::optional<IndexRange> get_node_bake_frame_range(const Scene &scene,
const Object &object,
const NodesModifierData &nmd,
int node_id);
std::optional<std::string> get_modifier_bake_path(const Main &bmain,
const Object &object,
const NodesModifierData &nmd);

View File

@ -84,6 +84,20 @@ std::optional<bake::BakePath> get_node_bake_path(const Main &bmain,
return bake::BakePath::from_single_root(zone_bake_dir);
}
std::optional<IndexRange> get_node_bake_frame_range(const Scene & /*scene*/,
const Object & /*object*/,
const NodesModifierData &nmd,
int node_id)
{
const NodesModifierBake *bake = nmd.find_bake(node_id);
if (bake == nullptr) {
return std::nullopt;
}
const int start = bake->frame_start;
const int end = std::max(start, bake->frame_end);
return IndexRange(start, end - start + 1);
}
/**
* Turn the name into something that can be used as file name. It does not necessarily have to be
* human readable, but it can help if it is at least partially readable.

View File

@ -2329,6 +2329,8 @@ typedef struct NodesModifierBake {
int id;
char _pad[4];
char *directory;
int frame_start;
int frame_end;
} NodesModifierBake;
typedef struct NodesModifierData {
@ -2348,6 +2350,11 @@ typedef struct NodesModifierData {
void *_pad2;
NodesModifierRuntimeHandle *runtime;
#ifdef __cplusplus
NodesModifierBake *find_bake(int id);
const NodesModifierBake *find_bake(int id) const;
#endif
} NodesModifierData;
typedef enum NodesModifierFlag {

View File

@ -7061,6 +7061,14 @@ static void rna_def_modifier_nodes_bake(BlenderRNA *brna)
prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH);
RNA_def_property_ui_text(prop, "Directory", "Location on disk where the bake data is stored");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_ui_text(prop, "Start Frame", "Frame where the baking starts");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME);
RNA_def_property_ui_text(prop, "End Frame", "Frame where the baking ends");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_nodes_bakes(BlenderRNA *brna)

View File

@ -446,6 +446,8 @@ static void update_bakes_from_node_group(NodesModifierData &nmd)
}
else {
new_bake.id = id;
new_bake.frame_start = 1;
new_bake.frame_end = 100;
}
}
@ -469,6 +471,21 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
}
NodesModifierBake *NodesModifierData::find_bake(const int id)
{
return const_cast<NodesModifierBake *>(std::as_const(*this).find_bake(id));
}
const NodesModifierBake *NodesModifierData::find_bake(const int id) const
{
for (const NodesModifierBake &bake : blender::Span{this->bakes, this->bakes_num}) {
if (bake.id == id) {
return &bake;
}
}
return nullptr;
}
namespace blender {
static void find_side_effect_nodes_for_viewer_path(
@ -726,8 +743,8 @@ class NodesModifierSimulationParams : public nodes::GeoNodesSimulationParams {
const ModifierEvalContext &ctx_;
const Main *bmain_;
SubFrame current_frame_;
SubFrame start_frame_;
bool is_start_frame_;
SubFrame scene_start_frame_;
bool is_scene_start_frame_;
bool use_frame_cache_;
bool depsgraph_is_active_;
bake::ModifierCache *modifier_cache_;
@ -741,8 +758,8 @@ class NodesModifierSimulationParams : public nodes::GeoNodesSimulationParams {
bmain_ = DEG_get_bmain(depsgraph);
current_frame_ = DEG_get_ctime(depsgraph);
const Scene *scene = DEG_get_input_scene(depsgraph);
start_frame_ = scene->r.sfra;
is_start_frame_ = current_frame_ == start_frame_;
scene_start_frame_ = scene->r.sfra;
is_scene_start_frame_ = current_frame_ == scene_start_frame_;
use_frame_cache_ = ctx_.object->flag & OB_FLAG_USE_SIMULATION_CACHE;
depsgraph_is_active_ = DEG_is_active(depsgraph);
modifier_cache_ = nmd.runtime->cache.get();
@ -763,7 +780,7 @@ class NodesModifierSimulationParams : public nodes::GeoNodesSimulationParams {
}
}
/* Reset cached data if necessary. */
if (is_start_frame_) {
if (is_scene_start_frame_) {
for (std::unique_ptr<bake::NodeCache> &node_cache : modifier_cache_->cache_by_id.values())
{
if (node_cache->cache_status == bake::CacheStatus::Invalid) {
@ -843,7 +860,7 @@ class NodesModifierSimulationParams : public nodes::GeoNodesSimulationParams {
/* Initialize the simulation. */
this->input_pass_through(zone_behavior);
this->output_store_frame_cache(node_cache, zone_behavior);
if (!is_start_frame_) {
if (!is_scene_start_frame_) {
/* If we initialize at a frame that is not the start frame, the simulation is not
* valid. */
node_cache.cache_status = bake::CacheStatus::Invalid;

View File

@ -882,11 +882,19 @@ static void node_layout_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
}
}
uiLayout *col = uiLayoutColumn(layout, true);
uiLayoutSetActive(col, !is_baked);
uiItemR(col, &bake_rna, "directory", UI_ITEM_NONE, "Path", ICON_NONE);
if (StringRef(bake->directory).is_empty()) {
uiItemL(col, "Uses modifier bake path", ICON_INFO);
{
uiLayout *col = uiLayoutColumn(layout, true);
uiLayoutSetActive(col, !is_baked);
uiItemR(col, &bake_rna, "directory", UI_ITEM_NONE, "Path", ICON_NONE);
if (StringRef(bake->directory).is_empty()) {
uiItemL(col, "Uses modifier bake path", ICON_INFO);
}
}
{
uiLayout *col = uiLayoutColumn(layout, true);
uiLayoutSetActive(col, !is_baked);
uiItemR(col, &bake_rna, "frame_start", UI_ITEM_NONE, "Start", ICON_NONE);
uiItemR(col, &bake_rna, "frame_end", UI_ITEM_NONE, "End", ICON_NONE);
}
}