From 8b777ee6d69d4805c64756cf6a33db894160ce29 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 19 Jan 2021 17:30:44 +0100 Subject: [PATCH 1/2] Geometry Nodes - Object Info: option to apply obj transform to the geometry By design the modified object transformations should still work and affect the geometry nodes results. The current behaviour, however, would make the geometry from the object info to not be affected by the modified object transformations. This patch changes that by default. In a similar fashion the Location, Rotation and Scale sockets outputs should be aware of whether the output should be in the global space or in the space of the nodetree. To solve this, the patch introduces a new transformation space "enum" where users can pick "Original" or "Relative" space. Original -------- Output the geometry relative to the input object transform, and the location, rotation and scale relative to the world origin. Relative -------- Bring the input object geometry, location, rotation and scale into the modified object maintaining the relative position between the two objects in the scene. Relative space violates a bit the design of the nodetree. The geometry in this case is transformed so that moving the modified object doesn't interfere with the geometry. This is particularly useful for the boolean node for instance. "Original" is the default space, but old files are set to "Relative" for backwards compatibility. Differential Revision: https://developer.blender.org/D10124 --- .../blender/blenkernel/BKE_blender_version.h | 2 +- .../blenloader/intern/versioning_290.c | 17 +++++++++++ source/blender/editors/space_node/drawnode.c | 8 +++++ source/blender/makesdna/DNA_node_types.h | 12 ++++++++ source/blender/makesrna/intern/rna_nodetree.c | 30 +++++++++++++++++++ source/blender/nodes/NOD_static_types.h | 2 +- .../geometry/nodes/node_geo_object_info.cc | 30 +++++++++++++++++-- 7 files changed, 96 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index a7960b6ce87..4ee96d1ab8d 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -39,7 +39,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 13 +#define BLENDER_FILE_SUBVERSION 14 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 86f18a98654..ec537e6f3d8 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1572,6 +1572,23 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + if (!MAIN_VERSION_ATLEAST(bmain, 292, 14)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type != NTREE_GEOMETRY) { + continue; + } + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == GEO_NODE_OBJECT_INFO && node->storage == NULL) { + NodeGeometryObjectInfo *data = (NodeGeometryObjectInfo *)MEM_callocN( + sizeof(NodeGeometryObjectInfo), __func__); + data->transform_space = GEO_NODE_TRANSFORM_SPACE_RELATIVE; + node->storage = data; + } + } + } + FOREACH_NODETREE_END; + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index ad975196981..df29950bc59 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3284,6 +3284,11 @@ static void node_geometry_buts_point_scale(uiLayout *layout, bContext *UNUSED(C) uiItemR(layout, ptr, "input_type", DEFAULT_FLAGS, IFACE_("Type"), ICON_NONE); } +static void node_geometry_buts_object_info(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE); +} + static void node_geometry_set_butfunc(bNodeType *ntype) { switch (ntype->type) { @@ -3335,6 +3340,9 @@ static void node_geometry_set_butfunc(bNodeType *ntype) case GEO_NODE_POINT_SCALE: ntype->draw_buttons = node_geometry_buts_point_scale; break; + case GEO_NODE_OBJECT_INFO: + ntype->draw_buttons = node_geometry_buts_object_info; + break; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index b6904f6ae5b..7d18ff3ed58 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1167,6 +1167,13 @@ typedef struct NodeGeometryPointTranslate { char _pad[7]; } NodeGeometryPointTranslate; +typedef struct NodeGeometryObjectInfo { + /* GeometryNodeTransformSpace. */ + uint8_t transform_space; + + char _pad[7]; +} NodeGeometryObjectInfo; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 @@ -1608,6 +1615,11 @@ typedef enum GeometryNodeAlignRotationToVectorAxis { GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_Z = 2, } GeometryNodeAlignRotationToVectorAxis; +typedef enum GeometryNodeTransformSpace { + GEO_NODE_TRANSFORM_SPACE_ORIGINAL = 0, + GEO_NODE_TRANSFORM_SPACE_RELATIVE = 1, +} GeometryNodeTransformSpace; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index a01f6b2db5d..6480b80056c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -494,6 +494,22 @@ static const EnumPropertyItem rna_node_geometry_attribute_input_type_items_no_bo {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem rna_node_geometry_object_info_transform_space_items[] = { + {GEO_NODE_TRANSFORM_SPACE_ORIGINAL, + "ORIGINAL", + 0, + "Original", + "Output the geometry relative to the input object transform, and the location, rotation and " + "scale relative to the world origin"}, + {GEO_NODE_TRANSFORM_SPACE_RELATIVE, + "RELATIVE", + 0, + "Relative", + "Bring the input object geometry, location, rotation and scale into the modified object, " + "maintaining the relative position between the two objects in the scene"}, + {0, NULL, 0, NULL, NULL}, +}; + #endif #undef ITEM_ATTRIBUTE @@ -8846,6 +8862,20 @@ static void def_geo_point_translate(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_object_info(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeGeometryObjectInfo", "storage"); + + prop = RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_object_info_transform_space_items); + RNA_def_property_ui_text(prop, + "Transform Space", + "Determine the transformation applied to vector and geometry outputs"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + /* -------------------------------------------------------------------------- */ static void rna_def_shader_node(BlenderRNA *brna) diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index f58dca18325..e91b385a87e 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -275,7 +275,7 @@ DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", Su DefNode(GeometryNode, GEO_NODE_BOOLEAN, def_geo_boolean, "BOOLEAN", Boolean, "Boolean", "") DefNode(GeometryNode, GEO_NODE_POINT_DISTRIBUTE, def_geo_point_distribute, "POINT_DISTRIBUTE", PointDistribute, "Point Distribute", "") DefNode(GeometryNode, GEO_NODE_POINT_INSTANCE, def_geo_point_instance, "POINT_INSTANCE", PointInstance, "Point Instance", "") -DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "") +DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, def_geo_object_info, "OBJECT_INFO", ObjectInfo, "Object Info", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_RANDOMIZE, def_geo_attribute_randomize, "ATTRIBUTE_RANDOMIZE", AttributeRandomize, "Attribute Randomize", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MATH, def_geo_attribute_math, "ATTRIBUTE_MATH", AttributeMath, "Attribute Math", "") DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "") diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc index 07d6858369d..ab5e4f8964a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc @@ -38,6 +38,11 @@ static bNodeSocketTemplate geo_node_object_info_out[] = { namespace blender::nodes { static void geo_node_object_info_exec(GeoNodeExecParams params) { + const bNode &bnode = params.node(); + NodeGeometryObjectInfo *node_storage = (NodeGeometryObjectInfo *)bnode.storage; + const bool transform_space_relative = (node_storage->transform_space == + GEO_NODE_TRANSFORM_SPACE_RELATIVE); + bke::PersistentObjectHandle object_handle = params.extract_input( "Object"); Object *object = params.handle_map().lookup(object_handle); @@ -54,7 +59,12 @@ static void geo_node_object_info_exec(GeoNodeExecParams params) mul_m4_m4m4(transform, self_object->imat, object->obmat); float quaternion[4]; - mat4_decompose(location, quaternion, scale, transform); + if (transform_space_relative) { + mat4_decompose(location, quaternion, scale, transform); + } + else { + mat4_decompose(location, quaternion, scale, object->obmat); + } quat_to_eul(rotation, quaternion); if (object != self_object) { @@ -66,8 +76,10 @@ static void geo_node_object_info_exec(GeoNodeExecParams params) /* Make a copy because the life time of the other mesh might be shorter. */ Mesh *copied_mesh = BKE_mesh_copy_for_eval(mesh, false); - /* Transform into the local space of the object that is being modified. */ - BKE_mesh_transform(copied_mesh, transform, true); + if (transform_space_relative) { + /* Transform into the local space of the object that is being modified. */ + BKE_mesh_transform(copied_mesh, transform, true); + } MeshComponent &mesh_component = geometry_set.get_component_for_write(); mesh_component.replace(copied_mesh); @@ -82,6 +94,15 @@ static void geo_node_object_info_exec(GeoNodeExecParams params) params.set_output("Scale", scale); params.set_output("Geometry", geometry_set); } + +static void geo_node_object_info_node_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryObjectInfo *data = (NodeGeometryObjectInfo *)MEM_callocN( + sizeof(NodeGeometryObjectInfo), __func__); + data->transform_space = GEO_NODE_TRANSFORM_SPACE_ORIGINAL; + node->storage = data; +} + } // namespace blender::nodes void register_node_type_geo_object_info() @@ -90,6 +111,9 @@ void register_node_type_geo_object_info() geo_node_type_base(&ntype, GEO_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0); node_type_socket_templates(&ntype, geo_node_object_info_in, geo_node_object_info_out); + node_type_init(&ntype, blender::nodes::geo_node_object_info_node_init); + node_type_storage( + &ntype, "NodeGeometryObjectInfo", node_free_standard_storage, node_copy_standard_storage); ntype.geometry_node_execute = blender::nodes::geo_node_object_info_exec; nodeRegisterType(&ntype); } From 05179a0ba4898c716a4b9b2d5e169c09b57e84fb Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 19 Jan 2021 18:01:22 +0100 Subject: [PATCH 2/2] Volumes: fix calling BKE_volume_load from multiple threads `BKE_volume_is_loaded` uses `grids.filepath` to determine if the grids are already loaded. The issue was that `grids.filepath` was set before the grids were loaded, resulting in incorrect early returns for other threads. Differential Revision: https://developer.blender.org/D10150 --- source/blender/blenkernel/intern/volume.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index eadb01c43fc..9e7a3736141 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -783,21 +783,22 @@ bool BKE_volume_load(Volume *volume, Main *bmain) /* Get absolute file path at current frame. */ const char *volume_name = volume->id.name + 2; - volume_filepath_get(bmain, volume, grids.filepath); + char filepath[FILE_MAX]; + volume_filepath_get(bmain, volume, filepath); - CLOG_INFO(&LOG, 1, "Volume %s: load %s", volume_name, grids.filepath); + CLOG_INFO(&LOG, 1, "Volume %s: load %s", volume_name, filepath); /* Test if file exists. */ - if (!BLI_exists(grids.filepath)) { + if (!BLI_exists(filepath)) { char filename[FILE_MAX]; - BLI_split_file_part(grids.filepath, filename, sizeof(filename)); + BLI_split_file_part(filepath, filename, sizeof(filename)); grids.error_msg = filename + std::string(" not found"); CLOG_INFO(&LOG, 1, "Volume %s: %s", volume_name, grids.error_msg.c_str()); return false; } /* Open OpenVDB file. */ - openvdb::io::File file(grids.filepath); + openvdb::io::File file(filepath); openvdb::GridPtrVec vdb_grids; try { @@ -814,11 +815,13 @@ bool BKE_volume_load(Volume *volume, Main *bmain) /* Add grids read from file to own vector, filtering out any NULL pointers. */ for (const openvdb::GridBase::Ptr &vdb_grid : vdb_grids) { if (vdb_grid) { - VolumeFileCache::Entry template_entry(grids.filepath, vdb_grid); + VolumeFileCache::Entry template_entry(filepath, vdb_grid); grids.emplace_back(template_entry, volume->runtime.default_simplify_level); } } + BLI_strncpy(grids.filepath, filepath, FILE_MAX); + return grids.error_msg.empty(); #else UNUSED_VARS(bmain, volume);