Simulation output and input nodes
This commit is contained in:
parent
2cb6b0b4eb
commit
5aaa435ac7
|
@ -291,6 +291,17 @@ class NODE_MT_category_GEO_POINT(Menu):
|
|||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_simulation(Menu):
|
||||
bl_idname = "NODE_MT_category_simulation"
|
||||
bl_label = "Simulation"
|
||||
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSimulationInput")
|
||||
node_add_menu.add_node_type(layout, "GeometryNodeSimulationOutput")
|
||||
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
|
||||
|
||||
|
||||
class NODE_MT_category_GEO_TEXT(Menu):
|
||||
bl_idname = "NODE_MT_category_GEO_TEXT"
|
||||
bl_label = "Text"
|
||||
|
@ -428,6 +439,7 @@ class NODE_MT_geometry_node_add_all(Menu):
|
|||
layout.menu("NODE_MT_geometry_node_mesh_topology")
|
||||
layout.menu("NODE_MT_category_GEO_OUTPUT")
|
||||
layout.menu("NODE_MT_category_GEO_POINT")
|
||||
layout.menu("NODE_MT_category_simulation")
|
||||
layout.menu("NODE_MT_category_GEO_TEXT")
|
||||
layout.menu("NODE_MT_category_GEO_TEXTURE")
|
||||
layout.menu("NODE_MT_category_GEO_UTILITIES")
|
||||
|
@ -455,6 +467,7 @@ classes = (
|
|||
NODE_MT_geometry_node_mesh_topology,
|
||||
NODE_MT_category_GEO_OUTPUT,
|
||||
NODE_MT_category_GEO_POINT,
|
||||
NODE_MT_category_simulation,
|
||||
NODE_MT_category_GEO_TEXT,
|
||||
NODE_MT_category_GEO_TEXTURE,
|
||||
NODE_MT_category_GEO_UTILITIES,
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_compute_context.hh"
|
||||
#include "BLI_map.hh"
|
||||
|
||||
#include "BKE_geometry_set.hh"
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
struct CacheData {
|
||||
Map<int, GeometrySet> geometry_per_frame;
|
||||
};
|
||||
|
||||
struct ComputeCaches {
|
||||
Map<ComputeContextHash, CacheData> cache_per_context;
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
|
@ -1396,6 +1396,9 @@ struct TexResult;
|
|||
/** \name Geometry Nodes
|
||||
* \{ */
|
||||
|
||||
#define GEO_NODE_SIMULATION_INPUT 1198
|
||||
#define GEO_NODE_SIMULATION_OUTPUT 1199
|
||||
|
||||
#define GEO_NODE_TRIANGULATE 1000
|
||||
#define GEO_NODE_TRANSFORM 1002
|
||||
#define GEO_NODE_MESH_BOOLEAN 1003
|
||||
|
|
|
@ -2213,7 +2213,7 @@ bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idnam
|
|||
|
||||
BKE_ntree_update_tag_node_new(ntree, node);
|
||||
|
||||
if (ELEM(node->type, GEO_NODE_INPUT_SCENE_TIME, GEO_NODE_SELF_OBJECT)) {
|
||||
if (ELEM(node->type, GEO_NODE_INPUT_SCENE_TIME, GEO_NODE_SELF_OBJECT, GEO_NODE_SIMULATION_INPUT)) {
|
||||
DEG_relations_tag_update(CTX_data_main(C));
|
||||
}
|
||||
|
||||
|
@ -3061,7 +3061,10 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user)
|
|||
|
||||
/* Also update relations for the scene time node, which causes a dependency
|
||||
* on time that users expect to be removed when the node is removed. */
|
||||
if (node_has_id || ELEM(node->type, GEO_NODE_INPUT_SCENE_TIME, GEO_NODE_SELF_OBJECT)) {
|
||||
if (node_has_id || ELEM(node->type,
|
||||
GEO_NODE_INPUT_SCENE_TIME,
|
||||
GEO_NODE_SELF_OBJECT,
|
||||
GEO_NODE_SIMULATION_INPUT)) {
|
||||
if (bmain != nullptr) {
|
||||
DEG_relations_tag_update(bmain);
|
||||
}
|
||||
|
@ -4771,6 +4774,8 @@ static void registerGeometryNodes()
|
|||
register_node_type_geo_set_shade_smooth();
|
||||
register_node_type_geo_set_spline_cyclic();
|
||||
register_node_type_geo_set_spline_resolution();
|
||||
register_node_type_geo_simulation_input();
|
||||
register_node_type_geo_simulation_output();
|
||||
register_node_type_geo_store_named_attribute();
|
||||
register_node_type_geo_string_join();
|
||||
register_node_type_geo_string_to_curves();
|
||||
|
|
|
@ -10,6 +10,15 @@
|
|||
#include "DNA_listBase.h"
|
||||
#include "DNA_session_uuid_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace blender::bke {
|
||||
struct ComputeCaches;
|
||||
}
|
||||
using ComputeCachesHandle = blender::bke::ComputeCaches;
|
||||
#else
|
||||
typedef struct ComputeCachesHandle ComputeCachesHandle;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -2295,7 +2304,9 @@ typedef struct NodesModifierData {
|
|||
* This can be used to help the user to debug a node tree.
|
||||
*/
|
||||
void *runtime_eval_log;
|
||||
void *_pad1;
|
||||
|
||||
/** #ComputeCaches. */
|
||||
ComputeCachesHandle *simulation_caches;
|
||||
} NodesModifierData;
|
||||
|
||||
typedef struct MeshToVolumeModifierData {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_compute_cache.hh"
|
||||
#include "BKE_compute_contexts.hh"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_geometry_fields.hh"
|
||||
|
@ -336,7 +337,7 @@ static bool check_tree_for_time_node(const bNodeTree &tree,
|
|||
return false;
|
||||
}
|
||||
LISTBASE_FOREACH (const bNode *, node, &tree.nodes) {
|
||||
if (node->type == GEO_NODE_INPUT_SCENE_TIME) {
|
||||
if (ELEM(node->type, GEO_NODE_INPUT_SCENE_TIME, GEO_NODE_SIMULATION_INPUT)) {
|
||||
return true;
|
||||
}
|
||||
if (node->type == NODE_GROUP) {
|
||||
|
@ -1106,6 +1107,7 @@ static GeometrySet compute_geometry(
|
|||
const blender::nodes::GeometryNodesLazyFunctionGraphInfo &lf_graph_info,
|
||||
const bNode &output_node,
|
||||
GeometrySet input_geometry_set,
|
||||
blender::bke::ComputeCaches &compute_caches,
|
||||
NodesModifierData *nmd,
|
||||
const ModifierEvalContext *ctx)
|
||||
{
|
||||
|
@ -1133,6 +1135,7 @@ static GeometrySet compute_geometry(
|
|||
blender::nodes::GeoNodesModifierData geo_nodes_modifier_data;
|
||||
geo_nodes_modifier_data.depsgraph = ctx->depsgraph;
|
||||
geo_nodes_modifier_data.self_object = ctx->object;
|
||||
geo_nodes_modifier_data.cache_per_frame = &compute_caches;
|
||||
auto eval_log = std::make_unique<GeoModifierLog>();
|
||||
if (logging_enabled(ctx)) {
|
||||
geo_nodes_modifier_data.eval_log = eval_log.get();
|
||||
|
@ -1301,8 +1304,24 @@ static void modifyGeometry(ModifierData *md,
|
|||
use_orig_index_polys = CustomData_has_layer(&mesh.pdata, CD_ORIGINDEX);
|
||||
}
|
||||
|
||||
geometry_set = compute_geometry(
|
||||
tree, *lf_graph_info, *output_node, std::move(geometry_set), nmd, ctx);
|
||||
NodesModifierData *orig_nmd = reinterpret_cast<NodesModifierData *>(
|
||||
BKE_modifier_get_original(ctx->object, md));
|
||||
if (!orig_nmd->simulation_caches) {
|
||||
orig_nmd->simulation_caches = new blender::bke::ComputeCaches();
|
||||
}
|
||||
|
||||
geometry_set = compute_geometry(tree,
|
||||
*lf_graph_info,
|
||||
*output_node,
|
||||
std::move(geometry_set),
|
||||
*orig_nmd->simulation_caches,
|
||||
nmd,
|
||||
ctx);
|
||||
|
||||
if (orig_nmd->simulation_caches->cache_per_context.is_empty()) {
|
||||
delete orig_nmd->simulation_caches;
|
||||
orig_nmd->simulation_caches = nullptr;
|
||||
}
|
||||
|
||||
if (geometry_set.has_mesh()) {
|
||||
/* Add #CD_ORIGINDEX layers if they don't exist already. This is required because the
|
||||
|
@ -1827,6 +1846,7 @@ static void blendWrite(BlendWriter *writer, const ID * /*id_owner*/, const Modif
|
|||
* and don't necessarily need to be written, but we can't just free them. */
|
||||
IDP_BlendWrite(writer, nmd->settings.properties);
|
||||
}
|
||||
/* TODO: Write cached geometry. */
|
||||
}
|
||||
|
||||
static void blendRead(BlendDataReader *reader, ModifierData *md)
|
||||
|
@ -1840,6 +1860,8 @@ static void blendRead(BlendDataReader *reader, ModifierData *md)
|
|||
IDP_BlendDataRead(reader, &nmd->settings.properties);
|
||||
}
|
||||
nmd->runtime_eval_log = nullptr;
|
||||
/* TODO: Read cached geometry. */
|
||||
nmd->simulation_caches = nullptr;
|
||||
}
|
||||
|
||||
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
|
||||
|
@ -1850,6 +1872,11 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
|
|||
BKE_modifier_copydata_generic(md, target, flag);
|
||||
|
||||
tnmd->runtime_eval_log = nullptr;
|
||||
if (nmd->simulation_caches) {
|
||||
const blender::bke::ComputeCaches &src_caches = *static_cast<blender::bke::ComputeCaches *>(
|
||||
nmd->simulation_caches);
|
||||
tnmd->simulation_caches = new blender::bke::ComputeCaches(src_caches);
|
||||
}
|
||||
|
||||
if (nmd->settings.properties != nullptr) {
|
||||
tnmd->settings.properties = IDP_CopyProperty_ex(nmd->settings.properties, flag);
|
||||
|
@ -1864,6 +1891,8 @@ static void freeData(ModifierData *md)
|
|||
nmd->settings.properties = nullptr;
|
||||
}
|
||||
|
||||
delete static_cast<blender::bke::ComputeCaches *>(nmd->simulation_caches);
|
||||
|
||||
clear_runtime_data(nmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -151,6 +151,8 @@ void register_node_type_geo_set_position(void);
|
|||
void register_node_type_geo_set_shade_smooth(void);
|
||||
void register_node_type_geo_set_spline_cyclic(void);
|
||||
void register_node_type_geo_set_spline_resolution(void);
|
||||
void register_node_type_geo_simulation_input(void);
|
||||
void register_node_type_geo_simulation_output(void);
|
||||
void register_node_type_geo_store_named_attribute(void);
|
||||
void register_node_type_geo_string_join(void);
|
||||
void register_node_type_geo_string_to_curves(void);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include "BLI_compute_context.hh"
|
||||
|
||||
#include "BKE_compute_cache.hh"
|
||||
|
||||
struct Object;
|
||||
struct Depsgraph;
|
||||
|
||||
|
@ -44,6 +46,9 @@ struct GeoNodesModifierData {
|
|||
Depsgraph *depsgraph = nullptr;
|
||||
/** Optional logger. */
|
||||
geo_eval_log::GeoModifierLog *eval_log = nullptr;
|
||||
|
||||
bke::ComputeCaches *cache_per_frame;
|
||||
|
||||
/**
|
||||
* Some nodes should be executed even when their output is not used (e.g. active viewer nodes and
|
||||
* the node groups they are contained in).
|
||||
|
|
|
@ -410,6 +410,8 @@ DefNode(GeometryNode, GEO_NODE_SET_POSITION, 0, "SET_POSITION", SetPosition, "Se
|
|||
DefNode(GeometryNode, GEO_NODE_SET_SHADE_SMOOTH, 0, "SET_SHADE_SMOOTH", SetShadeSmooth, "Set Shade Smooth", "Control the smoothness of mesh normals around each face by changing the \"shade smooth\" attribute")
|
||||
DefNode(GeometryNode, GEO_NODE_SET_SPLINE_CYCLIC, 0, "SET_SPLINE_CYCLIC", SetSplineCyclic, "Set Spline Cyclic", "Control whether each spline loops back on itself by changing the \"cyclic\" attribute")
|
||||
DefNode(GeometryNode, GEO_NODE_SET_SPLINE_RESOLUTION, 0, "SET_SPLINE_RESOLUTION", SetSplineResolution, "Set Spline Resolution", "Control how many evaluated points should be generated on every curve segment")
|
||||
DefNode(GeometryNode, GEO_NODE_SIMULATION_INPUT, 0, "SIMULATION_INPUT", SimulationInput, "Simulation Input", "")
|
||||
DefNode(GeometryNode, GEO_NODE_SIMULATION_OUTPUT, 0, "SIMULATION_OUTPUT", SimulationOutput, "Simulation Output", "")
|
||||
DefNode(GeometryNode, GEO_NODE_SPLIT_EDGES, 0, "SPLIT_EDGES", SplitEdges, "Split Edges", "Duplicate mesh edges and break connections with the surrounding faces")
|
||||
DefNode(GeometryNode, GEO_NODE_STORE_NAMED_ATTRIBUTE, def_geo_store_named_attribute, "STORE_NAMED_ATTRIBUTE", StoreNamedAttribute, "Store Named Attribute", "Store the result of a field on a geometry as an attribute with the specified name")
|
||||
DefNode(GeometryNode, GEO_NODE_STRING_JOIN, 0, "STRING_JOIN", StringJoin, "Join Strings", "Combine any number of input strings")
|
||||
|
|
|
@ -160,6 +160,8 @@ set(SRC
|
|||
nodes/node_geo_set_shade_smooth.cc
|
||||
nodes/node_geo_set_spline_cyclic.cc
|
||||
nodes/node_geo_set_spline_resolution.cc
|
||||
nodes/node_geo_simulation_input.cc
|
||||
nodes/node_geo_simulation_output.cc
|
||||
nodes/node_geo_store_named_attribute.cc
|
||||
nodes/node_geo_string_join.cc
|
||||
nodes/node_geo_string_to_curves.cc
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_simulation_input_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Geometry>(N_("Geometry"));
|
||||
b.add_output<decl::Geometry>(N_("Geometry"));
|
||||
}
|
||||
|
||||
static void node_geo_exec(GeoNodeExecParams params)
|
||||
{
|
||||
const Scene *scene = DEG_get_input_scene(params.depsgraph());
|
||||
const float scene_ctime = BKE_scene_ctime_get(scene);
|
||||
const int scene_frame = int(scene_ctime);
|
||||
const int previous_frame = scene_frame - 1;
|
||||
|
||||
const GeoNodesLFUserData &lf_data = *params.user_data();
|
||||
bke::ComputeCaches &all_caches = *lf_data.modifier_data->cache_per_frame;
|
||||
bke::CacheData *cache = all_caches.cache_per_context.lookup_ptr(lf_data.compute_context->hash());
|
||||
if (!cache) {
|
||||
params.set_output("Geometry", params.extract_input<GeometrySet>("Geometry"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cache->geometry_per_frame.contains(previous_frame)) {
|
||||
GeometrySet geometry_set = cache->geometry_per_frame.lookup(previous_frame);
|
||||
params.set_output("Geometry", std::move(geometry_set));
|
||||
// params.set_input_unused("Geometry");
|
||||
return;
|
||||
}
|
||||
|
||||
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
|
||||
params.set_output("Geometry", std::move(geometry_set));
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_geo_simulation_input_cc
|
||||
|
||||
void register_node_type_geo_simulation_input()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_geo_simulation_input_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
geo_node_type_base(&ntype, GEO_NODE_SIMULATION_INPUT, "Simulation Input", NODE_CLASS_INTERFACE);
|
||||
ntype.geometry_node_execute = file_ns::node_geo_exec;
|
||||
ntype.declare = file_ns::node_declare;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_simulation_output_cc {
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_input<decl::Geometry>(N_("Geometry"));
|
||||
b.add_output<decl::Geometry>(N_("Geometry"));
|
||||
}
|
||||
|
||||
static void node_geo_exec(GeoNodeExecParams params)
|
||||
{
|
||||
const Scene *scene = DEG_get_input_scene(params.depsgraph());
|
||||
const float scene_ctime = BKE_scene_ctime_get(scene);
|
||||
const int scene_frame = int(scene_ctime);
|
||||
|
||||
const GeoNodesLFUserData &lf_data = *params.user_data();
|
||||
bke::ComputeCaches &all_caches = *lf_data.modifier_data->cache_per_frame;
|
||||
bke::CacheData &cache = all_caches.cache_per_context.lookup_or_add_default(
|
||||
lf_data.compute_context->hash());
|
||||
|
||||
if (cache.geometry_per_frame.contains(scene_frame)) {
|
||||
params.set_output("Geometry", cache.geometry_per_frame.lookup(scene_frame));
|
||||
// params.set_input_unused("Geometry");
|
||||
return;
|
||||
}
|
||||
|
||||
GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
|
||||
geometry_set.ensure_owns_direct_data();
|
||||
cache.geometry_per_frame.add_new(scene_frame, geometry_set);
|
||||
|
||||
params.set_output("Geometry", std::move(geometry_set));
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_geo_simulation_output_cc
|
||||
|
||||
void register_node_type_geo_simulation_output()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_geo_simulation_output_cc;
|
||||
|
||||
static bNodeType ntype;
|
||||
|
||||
geo_node_type_base(
|
||||
&ntype, GEO_NODE_SIMULATION_OUTPUT, "Simulation Output", NODE_CLASS_INTERFACE);
|
||||
ntype.geometry_node_execute = file_ns::node_geo_exec;
|
||||
ntype.declare = file_ns::node_declare;
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
Loading…
Reference in New Issue