WIP: Geometry Nodes: Smart static dependency building of modifier #106434
|
@ -12,6 +12,7 @@
|
|||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_hash.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_multi_value_map.hh"
|
||||
|
@ -107,38 +108,65 @@ static void initData(ModifierData *md)
|
|||
MEMCPY_STRUCT_AFTER(nmd, DNA_struct_default_get(NodesModifierData), modifier);
|
||||
}
|
||||
|
||||
static void add_used_ids_from_sockets(const ListBase &sockets, Set<ID *> &ids)
|
||||
enum eNodeModifierIDRelation : int8_t {
|
||||
GEOMETRY = 1 << 0,
|
||||
TRANSFORM = 1 << 1,
|
||||
|
||||
COLLECTION = 1 << 2,
|
||||
CURVES = 1 << 3,
|
||||
|
||||
NOTHING = 0,
|
||||
ALL = ~0,
|
||||
};
|
||||
|
||||
inline eNodeModifierIDRelation &operator|=(eNodeModifierIDRelation &a, eNodeModifierIDRelation b)
|
||||
{
|
||||
return (eNodeModifierIDRelation &)((int8_t &)a |= (int8_t)b);
|
||||
}
|
||||
|
||||
inline eNodeModifierIDRelation operator|(eNodeModifierIDRelation a, eNodeModifierIDRelation b)
|
||||
{
|
||||
return (eNodeModifierIDRelation)((int8_t)a | (int8_t)b);
|
||||
}
|
||||
|
||||
inline eNodeModifierIDRelation operator&(eNodeModifierIDRelation a, eNodeModifierIDRelation b)
|
||||
{
|
||||
return (eNodeModifierIDRelation)((int8_t)a & (int8_t)b);
|
||||
}
|
||||
|
||||
static void add_used_ids_from_sockets(const ListBase &sockets,
|
||||
Map<ID *, eNodeModifierIDRelation> &ids)
|
||||
{
|
||||
LISTBASE_FOREACH (const bNodeSocket *, socket, &sockets) {
|
||||
switch (socket->type) {
|
||||
case SOCK_OBJECT: {
|
||||
if (Object *object = ((bNodeSocketValueObject *)socket->default_value)->value) {
|
||||
ids.add(&object->id);
|
||||
ids.lookup_or_add(&object->id, NOTHING) |= ALL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SOCK_COLLECTION: {
|
||||
if (Collection *collection =
|
||||
((bNodeSocketValueCollection *)socket->default_value)->value) {
|
||||
ids.add(&collection->id);
|
||||
ids.lookup_or_add(&collection->id, NOTHING) |= ALL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SOCK_MATERIAL: {
|
||||
if (Material *material = ((bNodeSocketValueMaterial *)socket->default_value)->value) {
|
||||
ids.add(&material->id);
|
||||
ids.lookup_or_add(&material->id, NOTHING) |= ALL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SOCK_TEXTURE: {
|
||||
if (Tex *texture = ((bNodeSocketValueTexture *)socket->default_value)->value) {
|
||||
ids.add(&texture->id);
|
||||
ids.lookup_or_add(&texture->id, NOTHING) |= ALL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SOCK_IMAGE: {
|
||||
if (Image *image = ((bNodeSocketValueImage *)socket->default_value)->value) {
|
||||
ids.add(&image->id);
|
||||
ids.lookup_or_add(&image->id, NOTHING) |= ALL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -152,34 +180,10 @@ static void add_used_ids_from_sockets(const ListBase &sockets, Set<ID *> &ids)
|
|||
* more properties like whether the node is muted, but we would have to accept the cost of updating
|
||||
* relations when those properties are changed.
|
||||
*/
|
||||
static bool node_needs_own_transform_relation(const bNode &node)
|
||||
{
|
||||
if (node.type == GEO_NODE_COLLECTION_INFO) {
|
||||
const NodeGeometryCollectionInfo &storage = *static_cast<const NodeGeometryCollectionInfo *>(
|
||||
node.storage);
|
||||
return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE;
|
||||
}
|
||||
|
||||
if (node.type == GEO_NODE_OBJECT_INFO) {
|
||||
const NodeGeometryObjectInfo &storage = *static_cast<const NodeGeometryObjectInfo *>(
|
||||
node.storage);
|
||||
return storage.transform_space == GEO_NODE_TRANSFORM_SPACE_RELATIVE;
|
||||
}
|
||||
|
||||
if (node.type == GEO_NODE_SELF_OBJECT) {
|
||||
return true;
|
||||
}
|
||||
if (node.type == GEO_NODE_DEFORM_CURVES_ON_SURFACE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void process_nodes_for_depsgraph(const bNodeTree &tree,
|
||||
Set<ID *> &ids,
|
||||
bool &r_needs_own_transform_relation,
|
||||
Set<const bNodeTree *> &checked_groups)
|
||||
Map<ID *, eNodeModifierIDRelation> &ids,
|
||||
Set<const bNodeTree *> &checked_groups,
|
||||
bool &r_needs_own_transform_relation)
|
||||
{
|
||||
if (!checked_groups.add(&tree)) {
|
||||
return;
|
||||
|
@ -187,28 +191,81 @@ static void process_nodes_for_depsgraph(const bNodeTree &tree,
|
|||
|
||||
tree.ensure_topology_cache();
|
||||
for (const bNode *node : tree.all_nodes()) {
|
||||
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);
|
||||
}
|
||||
if (node->is_group()) {
|
||||
const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node->id);
|
||||
if (group != nullptr) {
|
||||
process_nodes_for_depsgraph(*group, ids, checked_groups, r_needs_own_transform_relation);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
switch (node->type) {
|
||||
case (GEO_NODE_COLLECTION_INFO): {
|
||||
const NodeGeometryCollectionInfo &storage =
|
||||
*reinterpret_cast<const NodeGeometryCollectionInfo *>(node->storage);
|
||||
const bool own_transform_relation = storage.transform_space ==
|
||||
GEO_NODE_TRANSFORM_SPACE_RELATIVE;
|
||||
bNodeSocket *collection_socket = nodeFindSocket(node, SOCK_IN, "Collection");
|
||||
Collection *collection =
|
||||
collection_socket->default_value_typed<bNodeSocketValueCollection>()->value;
|
||||
if (collection == nullptr) {
|
||||
break;
|
||||
}
|
||||
eNodeModifierIDRelation &id_relation = ids.lookup_or_add(&collection->id, NOTHING);
|
||||
id_relation |= COLLECTION;
|
||||
if (own_transform_relation) {
|
||||
r_needs_own_transform_relation = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (GEO_NODE_OBJECT_INFO): {
|
||||
const NodeGeometryObjectInfo &storage = *reinterpret_cast<const NodeGeometryObjectInfo *>(
|
||||
node->storage);
|
||||
const bool own_transform_relation = storage.transform_space ==
|
||||
GEO_NODE_TRANSFORM_SPACE_RELATIVE;
|
||||
bNodeSocket *object_socket = nodeFindSocket(node, SOCK_IN, "Object");
|
||||
Object *object = object_socket->default_value_typed<bNodeSocketValueObject>()->value;
|
||||
if (object == nullptr) {
|
||||
break;
|
||||
}
|
||||
eNodeModifierIDRelation &id_relation = ids.lookup_or_add(&object->id, NOTHING);
|
||||
id_relation |= GEOMETRY | TRANSFORM;
|
||||
if (own_transform_relation) {
|
||||
r_needs_own_transform_relation = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (GEO_NODE_SELF_OBJECT): {
|
||||
r_needs_own_transform_relation = true;
|
||||
add_used_ids_from_sockets(node->inputs, ids);
|
||||
add_used_ids_from_sockets(node->outputs, ids);
|
||||
break;
|
||||
}
|
||||
case (GEO_NODE_DEFORM_CURVES_ON_SURFACE): {
|
||||
r_needs_own_transform_relation = true;
|
||||
add_used_ids_from_sockets(node->inputs, ids);
|
||||
add_used_ids_from_sockets(node->outputs, ids);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
add_used_ids_from_sockets(node->inputs, ids);
|
||||
add_used_ids_from_sockets(node->outputs, ids);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void find_used_ids_from_settings(const NodesModifierSettings &settings, Set<ID *> &ids)
|
||||
static void find_used_ids_from_settings(const NodesModifierSettings &settings,
|
||||
Map<ID *, eNodeModifierIDRelation> &ids)
|
||||
{
|
||||
IDP_foreach_property(
|
||||
settings.properties,
|
||||
IDP_TYPE_FILTER_ID,
|
||||
[](IDProperty *property, void *user_data) {
|
||||
Set<ID *> *ids = (Set<ID *> *)user_data;
|
||||
Map<ID *, eNodeModifierIDRelation> *ids = (Map<ID *, eNodeModifierIDRelation> *)user_data;
|
||||
ID *id = IDP_Id(property);
|
||||
if (id != nullptr) {
|
||||
ids->add(id);
|
||||
ids->lookup_or_add(id, NOTHING) |= ALL;
|
||||
}
|
||||
},
|
||||
&ids);
|
||||
|
@ -222,20 +279,36 @@ static const CustomData_MeshMasks dependency_data_mask{CD_MASK_PROP_ALL | CD_MAS
|
|||
CD_MASK_PROP_ALL};
|
||||
|
||||
static void add_collection_relation(const ModifierUpdateDepsgraphContext *ctx,
|
||||
Collection &collection)
|
||||
const eNodeModifierIDRelation & /*relation*/,
|
||||
ID *collection_id)
|
||||
{
|
||||
DEG_add_collection_geometry_relation(ctx->node, &collection, "Nodes Modifier");
|
||||
DEG_add_collection_geometry_customdata_mask(ctx->node, &collection, &dependency_data_mask);
|
||||
Collection *collection = reinterpret_cast<Collection *>(collection_id);
|
||||
DEG_add_collection_geometry_relation(ctx->node, collection, "Nodes Modifier");
|
||||
DEG_add_collection_geometry_customdata_mask(ctx->node, collection, &dependency_data_mask);
|
||||
}
|
||||
|
||||
static void add_object_relation(const ModifierUpdateDepsgraphContext *ctx, Object &object)
|
||||
static void add_object_relation(const ModifierUpdateDepsgraphContext *ctx,
|
||||
const eNodeModifierIDRelation &relation,
|
||||
ID *object_id)
|
||||
{
|
||||
DEG_add_object_relation(ctx->node, &object, DEG_OB_COMP_TRANSFORM, "Nodes Modifier");
|
||||
if (&(ID &)object != &ctx->object->id) {
|
||||
Object &object = *reinterpret_cast<Object *>(object_id);
|
||||
|
||||
if (object_id == &ctx->object->id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (relation & TRANSFORM) {
|
||||
DEG_add_object_relation(ctx->node, &object, DEG_OB_COMP_TRANSFORM, "Nodes Modifier");
|
||||
}
|
||||
|
||||
if (relation & COLLECTION) {
|
||||
if (object.type == OB_EMPTY && object.instance_collection != nullptr) {
|
||||
add_collection_relation(ctx, *object.instance_collection);
|
||||
add_collection_relation(ctx, relation, reinterpret_cast<ID *>(object.instance_collection));
|
||||
}
|
||||
else if (DEG_object_has_geometry_component(&object)) {
|
||||
}
|
||||
|
||||
if (relation & GEOMETRY) {
|
||||
if (DEG_object_has_geometry_component(&object)) {
|
||||
DEG_add_object_relation(ctx->node, &object, DEG_OB_COMP_GEOMETRY, "Nodes Modifier");
|
||||
DEG_add_customdata_mask(ctx->node, &object, &dependency_data_mask);
|
||||
}
|
||||
|
@ -252,29 +325,27 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
|
|||
DEG_add_node_tree_output_relation(ctx->node, nmd->node_group, "Nodes Modifier");
|
||||
|
||||
bool needs_own_transform_relation = false;
|
||||
Set<ID *> used_ids;
|
||||
Map<ID *, eNodeModifierIDRelation> used_ids;
|
||||
find_used_ids_from_settings(nmd->settings, used_ids);
|
||||
Set<const bNodeTree *> checked_groups;
|
||||
process_nodes_for_depsgraph(
|
||||
*nmd->node_group, used_ids, needs_own_transform_relation, checked_groups);
|
||||
*nmd->node_group, used_ids, checked_groups, needs_own_transform_relation);
|
||||
|
||||
if (ctx->object->type == OB_CURVES) {
|
||||
Curves *curves_id = static_cast<Curves *>(ctx->object->data);
|
||||
if (curves_id->surface != nullptr) {
|
||||
used_ids.add(&curves_id->surface->id);
|
||||
used_ids.lookup_or_add(&curves_id->surface->id, NOTHING) |= CURVES;
|
||||
}
|
||||
}
|
||||
|
||||
for (ID *id : used_ids) {
|
||||
for (auto [id, relation] : used_ids.items()) {
|
||||
switch ((ID_Type)GS(id->name)) {
|
||||
case ID_OB: {
|
||||
Object *object = reinterpret_cast<Object *>(id);
|
||||
add_object_relation(ctx, *object);
|
||||
add_object_relation(ctx, relation, id);
|
||||
break;
|
||||
}
|
||||
case ID_GR: {
|
||||
Collection *collection = reinterpret_cast<Collection *>(id);
|
||||
add_collection_relation(ctx, *collection);
|
||||
add_collection_relation(ctx, relation, id);
|
||||
break;
|
||||
}
|
||||
case ID_IM:
|
||||
|
|
Loading…
Reference in New Issue