Geometry Nodes: Add Active Camera input node

This adds a new "Active Camera" input geometry node, per #105761.

The node outputs the the scene's current active camera. It is available
from Input > Scene > Active Camera in the geometry nodes Add menu.

Typical usage would be to connect this node to an Object Info node to
obtain its transform. This works as expected when the camera's
transform is animated, and also when there are markers on the timeline
that change the active camera.

In order to support the aforementioned changes in the active camera,
this implementation adds depsgraph relations for all cameras referenced
by timeline markers. This eliminates the complexity of updating the
depsgraph whenever the scene switches to a different active camera,
but of course it comes at the cost of including more objects than
strictly necessary in the depsgraph for scenes that switch cameras.
Dynamically updating the depsgraph upon camera changes could be a
future improvement if there proves to be sufficient need for it.

Pull Request: https://projects.blender.org/blender/blender/pulls/113431
This commit is contained in:
Douglas Paul
2023-12-12 19:11:06 +01:00
committed by Hans Goudey
parent 86953dfac4
commit 75f160ee96
11 changed files with 88 additions and 7 deletions
@@ -283,6 +283,7 @@ class NODE_MT_geometry_node_GEO_INPUT_SCENE(Menu):
layout = self.layout
if context.space_data.geometry_nodes_type == 'TOOL':
node_add_menu.add_node_type(layout, "GeometryNodeTool3DCursor")
node_add_menu.add_node_type(layout, "GeometryNodeInputActiveCamera")
node_add_menu.add_node_type(layout, "GeometryNodeCollectionInfo")
node_add_menu.add_node_type(layout, "GeometryNodeImageInfo")
node_add_menu.add_node_type(layout, "GeometryNodeIsViewport")
+1
View File
@@ -1325,6 +1325,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define GEO_NODE_SPLIT_TO_INSTANCES 2116
#define GEO_NODE_INPUT_NAMED_LAYER_SELECTION 2117
#define GEO_NODE_INDEX_SWITCH 2118
#define GEO_NODE_INPUT_ACTIVE_CAMERA 2119
/** \} */
@@ -120,6 +120,10 @@ void DEG_add_scene_relation(DepsNodeHandle *node_handle,
Scene *scene,
eDepsSceneComponentType component,
const char *description);
void DEG_add_scene_camera_relation(DepsNodeHandle *node_handle,
Scene *scene,
eDepsObjectComponentType component,
const char *description);
void DEG_add_object_relation(DepsNodeHandle *node_handle,
Object *object,
eDepsObjectComponentType component,
@@ -83,6 +83,24 @@ void DEG_add_scene_relation(DepsNodeHandle *node_handle,
deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
void DEG_add_scene_camera_relation(DepsNodeHandle *node_handle,
Scene *scene,
eDepsObjectComponentType component,
const char *description)
{
if (scene->camera != nullptr) {
DEG_add_object_relation(node_handle, scene->camera, component, description);
}
/* Like DepsgraphNodeBuilder::build_scene_camera(), we also need to account for other cameras
* referenced by markers. */
LISTBASE_FOREACH (TimeMarker *, marker, &scene->markers) {
if (!ELEM(marker->camera, nullptr, scene->camera)) {
DEG_add_object_relation(node_handle, marker->camera, component, description);
}
}
}
void DEG_add_object_relation(DepsNodeHandle *node_handle,
Object *object,
eDepsObjectComponentType component,
@@ -249,8 +249,11 @@ static Depsgraph *build_depsgraph_from_indirect_ids(Main &bmain,
{
Set<ID *> ids_for_relations;
bool needs_own_transform_relation = false;
nodes::find_node_tree_dependencies(
node_tree_orig, ids_for_relations, needs_own_transform_relation);
bool needs_scene_camera_relation = false;
nodes::find_node_tree_dependencies(node_tree_orig,
ids_for_relations,
needs_own_transform_relation,
needs_scene_camera_relation);
IDP_foreach_property(
&const_cast<IDProperty &>(properties),
IDP_TYPE_FILTER_ID,
+8 -1
View File
@@ -164,9 +164,11 @@ static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphCont
DEG_add_node_tree_output_relation(ctx->node, nmd->node_group, "Nodes Modifier");
bool needs_own_transform_relation = false;
bool needs_scene_camera_relation = false;
Set<ID *> used_ids;
find_used_ids_from_settings(nmd->settings, used_ids);
nodes::find_node_tree_dependencies(*nmd->node_group, used_ids, needs_own_transform_relation);
nodes::find_node_tree_dependencies(
*nmd->node_group, used_ids, needs_own_transform_relation, needs_scene_camera_relation);
if (ctx->object->type == OB_CURVES) {
Curves *curves_id = static_cast<Curves *>(ctx->object->data);
@@ -203,6 +205,11 @@ static void update_depsgraph(ModifierData *md, const ModifierUpdateDepsgraphCont
if (needs_own_transform_relation) {
DEG_add_depends_on_transform_relation(ctx->node, "Nodes Modifier");
}
if (needs_scene_camera_relation) {
DEG_add_scene_camera_relation(ctx->node, ctx->scene, DEG_OB_COMP_TRANSFORM, "Nodes Modifier");
/* Active camera is a scene parameter that can change, so we need a relation for that, too. */
DEG_add_scene_relation(ctx->node, ctx->scene, DEG_SCENE_COMP_PARAMETERS, "Nodes Modifier");
}
}
static bool check_tree_for_time_node(const bNodeTree &tree, Set<const bNodeTree *> &checked_groups)
@@ -32,7 +32,8 @@ namespace blender::nodes {
void find_node_tree_dependencies(const bNodeTree &tree,
Set<ID *> &r_ids,
bool &r_needs_own_transform_relation);
bool &r_needs_own_transform_relation,
bool &r_needs_scene_camera_relation);
StringRef input_use_attribute_suffix();
StringRef input_attribute_name_suffix();
+1
View File
@@ -336,6 +336,7 @@ DefNode(GeometryNode, GEO_NODE_IMAGE_TEXTURE, def_geo_image_texture, "IMAGE_TEXT
DefNode(GeometryNode, GEO_NODE_INDEX_OF_NEAREST, 0, "INDEX_OF_NEAREST", IndexOfNearest, "Index of Nearest", "Find the nearest element in a group. Similar to the \"Sample Nearest\" node")
DefNode(GeometryNode, GEO_NODE_INDEX_SWITCH, def_geo_index_switch, "INDEX_SWITCH", IndexSwitch, "Index Switch", "Choose between an arbitrary number of values with an index")
DefNode(GeometryNode, GEO_NODE_IMAGE, def_geo_image, "IMAGE", InputImage, "Image", "Input image")
DefNode(GeometryNode, GEO_NODE_INPUT_ACTIVE_CAMERA, 0, "INPUT_ACTIVE_CAMERA", InputActiveCamera, "Active Camera", "Retrieve the scene's active camera")
DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_HANDLES, 0, "INPUT_CURVE_HANDLES", InputCurveHandlePositions, "Curve Handle Positions", "Retrieve the position of each Bézier control point's handles")
DefNode(GeometryNode, GEO_NODE_INPUT_CURVE_TILT, 0, "INPUT_CURVE_TILT", InputCurveTilt, "Curve Tilt", "Retrieve the angle at each control point used to twist the curve's normal around its tangent")
DefNode(GeometryNode, GEO_NODE_INPUT_ID, 0, "INPUT_ID", InputID, "ID", "Retrieve a stable random identifier value from the \"id\" attribute on the point domain, or the index if the attribute does not exist")
@@ -82,6 +82,7 @@ set(SRC
nodes/node_geo_image_texture.cc
nodes/node_geo_index_of_nearest.cc
nodes/node_geo_index_switch.cc
nodes/node_geo_input_active_camera.cc
nodes/node_geo_input_curve_handles.cc
nodes/node_geo_input_curve_tilt.cc
nodes/node_geo_input_edge_smooth.cc
@@ -0,0 +1,36 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_scene.h"
#include "DEG_depsgraph_query.hh"
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_input_active_camera_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Object>("Active Camera")
.description("The camera used for rendering the scene");
}
static void node_exec(GeoNodeExecParams params)
{
const Scene *scene = DEG_get_evaluated_scene(params.depsgraph());
Object *camera = DEG_get_evaluated_object(params.depsgraph(), scene->camera);
params.set_output("Active Camera", camera);
}
static void node_register()
{
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_ACTIVE_CAMERA, "Active Camera", NODE_CLASS_INPUT);
ntype.geometry_node_execute = node_exec;
ntype.declare = node_declare;
nodeRegisterType(&ntype);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_input_active_camera_cc
@@ -104,6 +104,7 @@ static bool node_needs_own_transform_relation(const bNode &node)
static void process_nodes_for_depsgraph(const bNodeTree &tree,
Set<ID *> &ids,
bool &r_needs_own_transform_relation,
bool &r_needs_scene_camera_relation,
Set<const bNodeTree *> &checked_groups)
{
if (!checked_groups.add(&tree)) {
@@ -115,21 +116,28 @@ static void process_nodes_for_depsgraph(const bNodeTree &tree,
add_used_ids_from_sockets(node->inputs, ids);
add_used_ids_from_sockets(node->outputs, ids);
r_needs_own_transform_relation |= node_needs_own_transform_relation(*node);
r_needs_scene_camera_relation |= (node->type == GEO_NODE_INPUT_ACTIVE_CAMERA);
}
for (const bNode *node : tree.group_nodes()) {
if (const bNodeTree *sub_tree = reinterpret_cast<const bNodeTree *>(node->id)) {
process_nodes_for_depsgraph(*sub_tree, ids, r_needs_own_transform_relation, checked_groups);
process_nodes_for_depsgraph(*sub_tree,
ids,
r_needs_own_transform_relation,
r_needs_scene_camera_relation,
checked_groups);
}
}
}
void find_node_tree_dependencies(const bNodeTree &tree,
Set<ID *> &r_ids,
bool &r_needs_own_transform_relation)
bool &r_needs_own_transform_relation,
bool &r_needs_scene_camera_relation)
{
Set<const bNodeTree *> checked_groups;
process_nodes_for_depsgraph(tree, r_ids, r_needs_own_transform_relation, checked_groups);
process_nodes_for_depsgraph(
tree, r_ids, r_needs_own_transform_relation, r_needs_scene_camera_relation, checked_groups);
}
StringRef input_use_attribute_suffix()