diff options
author | Jacques Lucke <jacques@blender.org> | 2021-01-21 12:32:42 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-01-21 12:32:42 +0300 |
commit | 793547e7d1401ad545e0450b80c7bafd521c60e1 (patch) | |
tree | 74ebdf40005711eb545fd1889bcf8226dd5bcafd /source/blender/nodes | |
parent | 985bc08688b7fb58a910171c63a1417580cffece (diff) |
Geometry Nodes: initial support for volumes
For the most part, this just adds boilerplate code for volume support in geometry nodes:
* Add `VolumeComponent` next to `MeshComponent`, etc.
* Support `VolumeComponent` in depsgraph object iterator.
Furthermore, I added initial volume support in a few nodes:
* The Object Info node outputs an object instance when the input is a volume object
(that will be the same for mesh objects soonish, to avoid copies).
* Support transforming a `VolumeComponent` in the Transform node.
* Support the `VolumeComponent` in Join Geometry nodes, but only when just one of the
inputs has a volume component for now.
Right now, there is no way to create a `VolumeComponent`, because the Object Info node
outputs an object instance. The `VolumeComponent` will be necessary for upcoming nodes,
which will generate volumes on the fly.
Viewport selection does not work correctly with `VolumeComponent`s currently. I don't
know why that is. That can be figured out a bit later, once we can actually create
new volumes in geometry nodes.
Ref T84604.
Differential Revision: https://developer.blender.org/D10147
Diffstat (limited to 'source/blender/nodes')
4 files changed, 77 insertions, 0 deletions
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index ed4d658eb4f..9057e4c6be8 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -366,4 +366,11 @@ if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) endif() +if(WITH_OPENVDB) + list(APPEND INC_SYS + ${OPENVDB_INCLUDE_DIRS} + ) + add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS}) +endif() + blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 75736ae714a..b9c9e5bd02a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -228,6 +228,14 @@ static void join_components(Span<const InstancesComponent *> src_components, Geo } } +static void join_components(Span<const VolumeComponent *> src_components, GeometrySet &result) +{ + /* Not yet supported. Joining volume grids with the same name requires resampling of at least one + * of the grids. The cell size of the resulting volume has to be determined somehow. */ + VolumeComponent &dst_component = result.get_component_for_write<VolumeComponent>(); + UNUSED_VARS(src_components, dst_component); +} + template<typename Component> static void join_component_type(Span<const GeometrySet *> src_geometry_sets, GeometrySet &result) { @@ -260,6 +268,7 @@ static void geo_node_join_geometry_exec(GeoNodeExecParams params) join_component_type<MeshComponent>(src_geometry_sets, geometry_set_result); join_component_type<PointCloudComponent>(src_geometry_sets, geometry_set_result); join_component_type<InstancesComponent>(src_geometry_sets, geometry_set_result); + join_component_type<VolumeComponent>(src_geometry_sets, geometry_set_result); params.set_output("Geometry", std::move(geometry_set_result)); } 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 ab5e4f8964a..fe0303a5f1c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc @@ -19,6 +19,7 @@ #include "BKE_mesh.h" #include "BKE_mesh_wrapper.h" #include "BKE_modifier.h" +#include "BKE_volume.h" #include "BLI_math_matrix.h" @@ -86,6 +87,16 @@ static void geo_node_object_info_exec(GeoNodeExecParams params) mesh_component.copy_vertex_group_names_from_object(*object); } } + if (object->type == OB_VOLUME) { + InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>(); + + if (transform_space_relative) { + instances.add_instance(object, location, rotation, scale); + } + else { + instances.add_instance(object, {0, 0, 0}); + } + } } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc index 4fe61dff72d..251fa0866ad 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -14,11 +14,19 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +#endif + #include "BLI_math_matrix.h" #include "DNA_pointcloud_types.h" +#include "DNA_volume_types.h" #include "BKE_mesh.h" +#include "BKE_volume.h" + +#include "DEG_depsgraph_query.h" #include "node_geometry_util.hh" @@ -116,6 +124,43 @@ static void transform_instances(InstancesComponent &instances, } } +static void transform_volume(Volume *volume, + const float3 translation, + const float3 rotation, + const float3 scale, + GeoNodeExecParams ¶ms) +{ +#ifdef WITH_OPENVDB + /* Scaling an axis to zero is not supported for volumes. */ + const float3 limited_scale = { + (scale.x == 0.0f) ? FLT_EPSILON : scale.x, + (scale.y == 0.0f) ? FLT_EPSILON : scale.y, + (scale.z == 0.0f) ? FLT_EPSILON : scale.z, + }; + + Main *bmain = DEG_get_bmain(params.depsgraph()); + BKE_volume_load(volume, bmain); + + float matrix[4][4]; + loc_eul_size_to_mat4(matrix, translation, rotation, limited_scale); + + openvdb::Mat4s vdb_matrix; + memcpy(vdb_matrix.asPointer(), matrix, sizeof(float[4][4])); + openvdb::Mat4d vdb_matrix_d{vdb_matrix}; + + const int num_grids = BKE_volume_num_grids(volume); + for (const int i : IndexRange(num_grids)) { + VolumeGrid *volume_grid = BKE_volume_grid_get(volume, i); + + openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(volume, volume_grid, false); + openvdb::math::Transform &grid_transform = grid->transform(); + grid_transform.postMult(vdb_matrix_d); + } +#else + UNUSED_VARS(volume, translation, rotation, scale, params); +#endif +} + static void geo_node_transform_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); @@ -138,6 +183,11 @@ static void geo_node_transform_exec(GeoNodeExecParams params) transform_instances(instances, translation, rotation, scale); } + if (geometry_set.has_volume()) { + Volume *volume = geometry_set.get_volume_for_write(); + transform_volume(volume, translation, rotation, scale, params); + } + params.set_output("Geometry", std::move(geometry_set)); } } // namespace blender::nodes |