Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-10-15 22:20:53 +0300
committerHans Goudey <h.goudey@me.com>2021-10-15 22:20:53 +0300
commit19bab2a5360708242a5f6ea11b6e2ff03568a679 (patch)
tree50c4a4862ed08ca62809b462e273a3925649c9d8 /source/blender/nodes
parent76f386a37a9cf14ac729be048230f81a0a397fc8 (diff)
Geometry Nodes: Object info node optional instance output
The object info node output an instance as a performance optimization. Before that optimization was (almost) invisible to the user, but now that we aren't automatically realizing instances, it isn't intuitive for a single object to become an instance. I refactored the transform node so its ability to translate/transform an entire geometry set was more usable from elsewhere and exposed the function to get a geometry set from an object. Differential Revision: https://developer.blender.org/D12833
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.hh6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_object_info.cc32
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transform.cc186
5 files changed, 132 insertions, 98 deletions
diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh
index 21404525748..f382ff6c132 100644
--- a/source/blender/nodes/geometry/node_geometry_util.hh
+++ b/source/blender/nodes/geometry/node_geometry_util.hh
@@ -50,11 +50,15 @@ void update_attribute_input_socket_availabilities(bNode &node,
Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &component,
const AttributeDomain domain);
-void transform_mesh(Mesh *mesh,
+void transform_mesh(Mesh &mesh,
const float3 translation,
const float3 rotation,
const float3 scale);
+void transform_geometry_set(GeometrySet &geometry,
+ const float4x4 &transform,
+ const Depsgraph &depsgraph);
+
Mesh *create_line_mesh(const float3 start, const float3 delta, const int count);
Mesh *create_grid_mesh(const int verts_x,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
index fdc6b12095c..8b90595a641 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_bounding_box.cc
@@ -153,7 +153,7 @@ static void geo_node_bounding_box_exec(GeoNodeExecParams params)
const float3 scale = max - min;
const float3 center = min + scale / 2.0f;
Mesh *mesh = create_cuboid_mesh(scale, 2, 2, 2);
- transform_mesh(mesh, center, float3(0), float3(1));
+ transform_mesh(*mesh, center, float3(0), float3(1));
params.set_output("Bounding Box", GeometrySet::create_with_mesh(mesh));
params.set_output("Min", min);
params.set_output("Max", max);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
index af8ce02b3c1..5a520d36296 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc
@@ -456,12 +456,12 @@ static Mesh *create_cube_mesh(const float3 size,
}
if (verts_y == 1) { /* XZ plane. */
Mesh *mesh = create_grid_mesh(verts_x, verts_z, size.x, size.z);
- transform_mesh(mesh, float3(0), float3(M_PI_2, 0.0f, 0.0f), float3(1));
+ transform_mesh(*mesh, float3(0), float3(M_PI_2, 0.0f, 0.0f), float3(1));
return mesh;
}
/* YZ plane. */
Mesh *mesh = create_grid_mesh(verts_z, verts_y, size.z, size.y);
- transform_mesh(mesh, float3(0), float3(0.0f, M_PI_2, 0.0f), float3(1));
+ transform_mesh(*mesh, float3(0), float3(0.0f, M_PI_2, 0.0f), float3(1));
return mesh;
}
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 389acc40f0f..e61709ed86a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc
@@ -26,6 +26,10 @@ namespace blender::nodes {
static void geo_node_object_info_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Object>("Object").hide_label();
+ b.add_input<decl::Bool>("As Instance")
+ .description(
+ "Output the entire object as single instance. "
+ "This allows instancing non-geometry object types");
b.add_output<decl::Vector>("Location");
b.add_output<decl::Vector>("Rotation");
b.add_output<decl::Vector>("Scale");
@@ -54,12 +58,11 @@ static void geo_node_object_info_exec(GeoNodeExecParams params)
const Object *self_object = params.self_object();
if (object != nullptr) {
- float transform[4][4];
- mul_m4_m4m4(transform, self_object->imat, object->obmat);
+ const float4x4 transform = float4x4(self_object->imat) * float4x4(object->obmat);
float quaternion[4];
if (transform_space_relative) {
- mat4_decompose(location, quaternion, scale, transform);
+ mat4_decompose(location, quaternion, scale, transform.values);
}
else {
mat4_decompose(location, quaternion, scale, object->obmat);
@@ -67,16 +70,23 @@ static void geo_node_object_info_exec(GeoNodeExecParams params)
quat_to_eul(rotation, quaternion);
if (object != self_object) {
- InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
- const int handle = instances.add_reference(*object);
-
- if (transform_space_relative) {
- instances.add_instance(handle, transform);
+ if (params.get_input<bool>("As Instance")) {
+ InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
+ const int handle = instances.add_reference(*object);
+ if (transform_space_relative) {
+ instances.add_instance(handle, transform);
+ }
+ else {
+ float unit_transform[4][4];
+ unit_m4(unit_transform);
+ instances.add_instance(handle, unit_transform);
+ }
}
else {
- float unit_transform[4][4];
- unit_m4(unit_transform);
- instances.add_instance(handle, unit_transform);
+ geometry_set = bke::object_get_evaluated_geometry_set(*object);
+ if (transform_space_relative) {
+ transform_geometry_set(geometry_set, transform, *params.depsgraph());
+ }
}
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
index d5eb067cad0..005714a9580 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
@@ -25,6 +25,7 @@
#include "DNA_volume_types.h"
#include "BKE_mesh.h"
+#include "BKE_pointcloud.h"
#include "BKE_spline.hh"
#include "BKE_volume.h"
@@ -55,112 +56,142 @@ static bool use_translate(const float3 rotation, const float3 scale)
return true;
}
-void transform_mesh(Mesh *mesh,
+static void translate_mesh(Mesh &mesh, const float3 translation)
+{
+ if (!translation.is_zero()) {
+ BKE_mesh_translate(&mesh, translation, false);
+ }
+}
+
+static void transform_mesh(Mesh &mesh, const float4x4 &transform)
+{
+ BKE_mesh_transform(&mesh, transform.values, false);
+ BKE_mesh_normals_tag_dirty(&mesh);
+}
+
+void transform_mesh(Mesh &mesh,
const float3 translation,
const float3 rotation,
const float3 scale)
{
- /* Use only translation if rotation and scale are zero. */
- if (use_translate(rotation, scale)) {
- if (!translation.is_zero()) {
- BKE_mesh_translate(mesh, translation, false);
- }
- }
- else {
- const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
- BKE_mesh_transform(mesh, matrix.values, false);
- BKE_mesh_normals_tag_dirty(mesh);
- }
+ const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
+ transform_mesh(mesh, matrix);
}
-static void transform_pointcloud(PointCloud *pointcloud,
- const float3 translation,
- const float3 rotation,
- const float3 scale)
+static void translate_pointcloud(PointCloud &pointcloud, const float3 translation)
{
- /* Use only translation if rotation and scale don't apply. */
- if (use_translate(rotation, scale)) {
- for (const int i : IndexRange(pointcloud->totpoint)) {
- add_v3_v3(pointcloud->co[i], translation);
- }
+ CustomData_duplicate_referenced_layer(&pointcloud.pdata, CD_PROP_FLOAT3, pointcloud.totpoint);
+ BKE_pointcloud_update_customdata_pointers(&pointcloud);
+ for (const int i : IndexRange(pointcloud.totpoint)) {
+ add_v3_v3(pointcloud.co[i], translation);
}
- else {
- const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
- for (const int i : IndexRange(pointcloud->totpoint)) {
- float3 &co = *(float3 *)pointcloud->co[i];
- co = matrix * co;
- }
+}
+
+static void transform_pointcloud(PointCloud &pointcloud, const float4x4 &transform)
+{
+ CustomData_duplicate_referenced_layer(&pointcloud.pdata, CD_PROP_FLOAT3, pointcloud.totpoint);
+ BKE_pointcloud_update_customdata_pointers(&pointcloud);
+ for (const int i : IndexRange(pointcloud.totpoint)) {
+ float3 &co = *(float3 *)pointcloud.co[i];
+ co = transform * co;
}
}
-static void transform_instances(InstancesComponent &instances,
- const float3 translation,
- const float3 rotation,
- const float3 scale)
+static void translate_instances(InstancesComponent &instances, const float3 translation)
{
MutableSpan<float4x4> transforms = instances.instance_transforms();
-
- /* Use only translation if rotation and scale don't apply. */
- if (use_translate(rotation, scale)) {
- for (float4x4 &transform : transforms) {
- add_v3_v3(transform.ptr()[3], translation);
- }
+ for (float4x4 &transform : transforms) {
+ add_v3_v3(transform.ptr()[3], translation);
}
- else {
- const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
- for (float4x4 &transform : transforms) {
- transform = matrix * transform;
- }
+}
+
+static void transform_instances(InstancesComponent &instances, const float4x4 &transform)
+{
+ MutableSpan<float4x4> instance_transforms = instances.instance_transforms();
+ for (float4x4 &instance_transform : instance_transforms) {
+ instance_transform = transform * instance_transform;
}
}
-static void transform_volume(Volume *volume,
- const float3 translation,
- const float3 rotation,
- const float3 scale,
- GeoNodeExecParams &params)
+static void transform_volume(Volume &volume, const float4x4 &transform, const Depsgraph &depsgraph)
{
#ifdef WITH_OPENVDB
/* Scaling an axis to zero is not supported for volumes. */
+ const float3 translation = transform.translation();
+ const float3 rotation = transform.to_euler();
+ const float3 scale = transform.scale();
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,
};
+ const float4x4 scale_limited_transform = float4x4::from_loc_eul_scale(
+ translation, rotation, limited_scale);
- const Main *bmain = DEG_get_bmain(params.depsgraph());
- BKE_volume_load(volume, bmain);
-
- const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, limited_scale);
+ const Main *bmain = DEG_get_bmain(&depsgraph);
+ BKE_volume_load(&volume, bmain);
openvdb::Mat4s vdb_matrix;
- memcpy(vdb_matrix.asPointer(), matrix, sizeof(float[4][4]));
+ memcpy(vdb_matrix.asPointer(), &scale_limited_transform, sizeof(float[4][4]));
openvdb::Mat4d vdb_matrix_d{vdb_matrix};
- const int num_grids = BKE_volume_num_grids(volume);
+ const int num_grids = BKE_volume_num_grids(&volume);
for (const int i : IndexRange(num_grids)) {
- VolumeGrid *volume_grid = BKE_volume_grid_get_for_write(volume, i);
+ VolumeGrid *volume_grid = BKE_volume_grid_get_for_write(&volume, i);
- openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(volume, volume_grid, false);
+ 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);
+ UNUSED_VARS(volume, transform, depsgraph);
#endif
}
-static void transform_curve(CurveEval &curve,
- const float3 translation,
- const float3 rotation,
- const float3 scale)
+static void translate_volume(Volume &volume, const float3 translation, const Depsgraph &depsgraph)
{
- if (use_translate(rotation, scale)) {
- curve.translate(translation);
+ transform_volume(volume, float4x4::from_location(translation), depsgraph);
+}
+
+void transform_geometry_set(GeometrySet &geometry,
+ const float4x4 &transform,
+ const Depsgraph &depsgraph)
+{
+ if (CurveEval *curve = geometry.get_curve_for_write()) {
+ curve->transform(transform);
}
- else {
- const float4x4 matrix = float4x4::from_loc_eul_scale(translation, rotation, scale);
- curve.transform(matrix);
+ if (Mesh *mesh = geometry.get_mesh_for_write()) {
+ transform_mesh(*mesh, transform);
+ }
+ if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) {
+ transform_pointcloud(*pointcloud, transform);
+ }
+ if (Volume *volume = geometry.get_volume_for_write()) {
+ transform_volume(*volume, transform, depsgraph);
+ }
+ if (geometry.has_instances()) {
+ transform_instances(geometry.get_component_for_write<InstancesComponent>(), transform);
+ }
+}
+
+static void translate_geometry_set(GeometrySet &geometry,
+ const float3 translation,
+ const Depsgraph &depsgraph)
+{
+ if (CurveEval *curve = geometry.get_curve_for_write()) {
+ curve->translate(translation);
+ }
+ if (Mesh *mesh = geometry.get_mesh_for_write()) {
+ translate_mesh(*mesh, translation);
+ }
+ if (PointCloud *pointcloud = geometry.get_pointcloud_for_write()) {
+ translate_pointcloud(*pointcloud, translation);
+ }
+ if (Volume *volume = geometry.get_volume_for_write()) {
+ translate_volume(*volume, translation, depsgraph);
+ }
+ if (geometry.has_instances()) {
+ translate_instances(geometry.get_component_for_write<InstancesComponent>(), translation);
}
}
@@ -171,25 +202,14 @@ static void geo_node_transform_exec(GeoNodeExecParams params)
const float3 rotation = params.extract_input<float3>("Rotation");
const float3 scale = params.extract_input<float3>("Scale");
- if (geometry_set.has_mesh()) {
- Mesh *mesh = geometry_set.get_mesh_for_write();
- transform_mesh(mesh, translation, rotation, scale);
- }
- if (geometry_set.has_pointcloud()) {
- PointCloud *pointcloud = geometry_set.get_pointcloud_for_write();
- transform_pointcloud(pointcloud, translation, rotation, scale);
- }
- if (geometry_set.has_instances()) {
- InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>();
- 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);
+ /* Use only translation if rotation and scale don't apply. */
+ if (use_translate(rotation, scale)) {
+ translate_geometry_set(geometry_set, translation, *params.depsgraph());
}
- if (geometry_set.has_curve()) {
- CurveEval *curve = geometry_set.get_curve_for_write();
- transform_curve(*curve, translation, rotation, scale);
+ else {
+ transform_geometry_set(geometry_set,
+ float4x4::from_loc_eul_scale(translation, rotation, scale),
+ *params.depsgraph());
}
params.set_output("Geometry", std::move(geometry_set));