[Bf-blender-cvs] [7ef0e7ded75] geometry-nodes-level-set-nodes: Add incomplete support for level sets in the raycast node
Hans Goudey
noreply at git.blender.org
Sat Aug 14 06:44:08 CEST 2021
Commit: 7ef0e7ded751fa48991e844c5d4f1202fb51b1c1
Author: Hans Goudey
Date: Fri Aug 13 23:43:47 2021 -0500
Branches: geometry-nodes-level-set-nodes
https://developer.blender.org/rB7ef0e7ded751fa48991e844c5d4f1202fb51b1c1
Add incomplete support for level sets in the raycast node
===================================================================
M source/blender/nodes/geometry/nodes/node_geo_raycast.cc
===================================================================
diff --git a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
index 88e3bf17d43..eb00fffce9b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_raycast.cc
@@ -16,8 +16,14 @@
#include "DNA_mesh_types.h"
+#ifdef WITH_OPENVDB
+# include <openvdb/tools/RayIntersector.h>
+# include <openvdb/tools/VolumeToMesh.h>
+#endif
+
#include "BKE_bvhutils.h"
#include "BKE_mesh_sample.hh"
+#include "BKE_volume.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -76,6 +82,38 @@ static void geo_node_raycast_update(bNodeTree *UNUSED(ntree), bNode *node)
*node, "Ray Length", (GeometryNodeAttributeInputMode)node_storage->input_type_ray_length);
}
+#ifdef WITH_OPENVDB
+static void raycast_to_level_set(const openvdb::FloatGrid &level_set,
+ const VArray<float3> &ray_origins,
+ const VArray<float3> &ray_directions,
+ const VArray<float> &ray_lengths,
+ const MutableSpan<bool> r_hit,
+ const MutableSpan<float3> r_hit_positions,
+ const MutableSpan<float3> r_hit_normals,
+ const MutableSpan<float> r_hit_distances)
+{
+ openvdb::tools::LevelSetRayIntersector intersector(level_set);
+
+ for (const int i : ray_origins.index_range()) {
+ const openvdb::math::Vec3s origin(ray_origins[i].x, ray_origins[i].y, ray_origins[i].z);
+ const openvdb::math::Vec3s dir(ray_directions[i].x, ray_directions[i].y, ray_directions[i].z);
+ const openvdb::math::Ray<double> ray(origin, dir);
+
+ openvdb::math::Vec3d hit_position(0);
+ openvdb::math::Vec3d hit_normal(0);
+ if (!r_hit.is_empty()) {
+ r_hit[i] = intersector.intersectsWS(ray, hit_position, hit_normal);
+ }
+ if (!r_hit_positions.is_empty()) {
+ r_hit_positions[i] = float3(hit_position.x(), hit_position.y(), hit_position.z());
+ }
+ if (!r_hit_normals.is_empty()) {
+ r_hit_normals[i] = float3(hit_normal.x(), hit_normal.y(), hit_normal.z());
+ }
+ }
+}
+#endif
+
static void raycast_to_mesh(const Mesh &mesh,
const VArray<float3> &ray_origins,
const VArray<float3> &ray_directions,
@@ -167,6 +205,33 @@ static bke::mesh_surface_sample::eAttributeMapMode get_map_mode(
}
}
+static bool level_set_available(const GeometrySet &target_geometry,
+ const GeoNodeExecParams ¶ms,
+ const bool has_mesh)
+{
+ const Volume *volume = target_geometry.get_volume_for_read();
+ if (volume == nullptr) {
+ return false;
+ }
+ const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, 0);
+ if (volume_grid == nullptr) {
+ return false;
+ }
+
+ openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
+ if (grid->empty()) {
+ return false;
+ }
+ if (grid->getGridClass() != openvdb::GridClass::GRID_LEVEL_SET) {
+ if (!has_mesh) {
+ params.error_message_add(NodeWarningType::Error, TIP_("Volume is not a level set"));
+ }
+ return false;
+ }
+
+ return true;
+}
+
static void raycast_from_points(const GeoNodeExecParams ¶ms,
const GeometrySet &target_geometry,
GeometryComponent &dst_component,
@@ -181,15 +246,18 @@ static void raycast_from_points(const GeoNodeExecParams ¶ms,
const MeshComponent *src_mesh_component =
target_geometry.get_component_for_read<MeshComponent>();
- if (src_mesh_component == nullptr) {
- return;
- }
- const Mesh *src_mesh = src_mesh_component->get_for_read();
- if (src_mesh == nullptr) {
- return;
- }
- if (src_mesh->totpoly == 0) {
- return;
+
+ const Mesh *src_mesh = src_mesh_component == nullptr ? nullptr :
+ src_mesh_component->get_for_read();
+
+ const bool can_use_level_set = level_set_available(target_geometry, params, src_mesh == nullptr);
+ if (!can_use_level_set) {
+ if (src_mesh == nullptr) {
+ return;
+ }
+ if (src_mesh->totpoly == 0) {
+ return;
+ }
}
const NodeGeometryRaycast &storage = *(const NodeGeometryRaycast *)params.node().storage;
@@ -213,58 +281,71 @@ static void raycast_from_points(const GeoNodeExecParams ¶ms,
OutputAttribute_Typed<float> hit_distance_attribute =
dst_component.attribute_try_get_for_output_only<float>(hit_distance_name, result_domain);
- /* Positions and looptri indices are always needed for interpolation,
- * so create temporary arrays if no output attribute is given. */
- Array<int> hit_indices;
- Array<float3> hit_positions_internal;
- if (!hit_attribute_names.is_empty()) {
- hit_indices.reinitialize(ray_origins->size());
+ if (src_mesh == nullptr) {
+ BLI_assert(can_use_level_set);
+ const Volume *volume = target_geometry.get_volume_for_read();
+ const VolumeGrid *volume_grid = BKE_volume_grid_get_for_read(volume, 0);
+ openvdb::GridBase::ConstPtr grid_base = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
+
+ raycast_to_level_set(
+ *openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid_base),
+ ray_origins,
+ ray_directions,
+ ray_lengths,
+ hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>(),
+ hit_position_attribute ? hit_position_attribute.as_span() : MutableSpan<float3>(),
+ hit_normal_attribute ? hit_normal_attribute.as_span() : MutableSpan<float3>(),
+ hit_distance_attribute ? hit_distance_attribute.as_span() : MutableSpan<float>());
+ }
+ else {
+ /* Positions and looptri indices are always needed for interpolation,
+ * so create temporary arrays if no output attribute is given. */
+ Array<int> hit_indices;
+ Array<float3> hit_positions_internal;
+ if (!hit_attribute_names.is_empty()) {
+ hit_indices.reinitialize(ray_origins->size());
+
+ if (!hit_position_attribute) {
+ hit_positions_internal.reinitialize(ray_origins->size());
+ }
+ }
- if (!hit_position_attribute) {
- hit_positions_internal.reinitialize(ray_origins->size());
+ MutableSpan<float3> hit_positions = hit_position_attribute ? hit_position_attribute.as_span() :
+ hit_positions_internal;
+ raycast_to_mesh(*src_mesh,
+ ray_origins,
+ ray_directions,
+ ray_lengths,
+ hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>(),
+ hit_indices,
+ hit_positions,
+ hit_normal_attribute ? hit_normal_attribute.as_span() : MutableSpan<float3>(),
+ hit_distance_attribute ? hit_distance_attribute.as_span() :
+ MutableSpan<float>());
+
+ /* Custom interpolated attributes */
+ bke::mesh_surface_sample::MeshAttributeInterpolator interp(
+ src_mesh, hit_positions, hit_indices);
+ for (const int i : hit_attribute_names.index_range()) {
+ const std::optional<AttributeMetaData> meta_data =
+ src_mesh_component->attribute_get_meta_data(hit_attribute_names[i]);
+ if (meta_data) {
+ ReadAttributeLookup hit_attribute = src_mesh_component->attribute_try_get_for_read(
+ hit_attribute_names[i]);
+ OutputAttribute hit_attribute_output = dst_component.attribute_try_get_for_output_only(
+ hit_attribute_output_names[i], result_domain, meta_data->data_type);
+
+ interp.sample_attribute(hit_attribute, hit_attribute_output, map_mode);
+
+ hit_attribute_output.save();
+ }
}
}
- const MutableSpan<bool> is_hit = hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>();
- const MutableSpan<float3> hit_positions = hit_position_attribute ?
- hit_position_attribute.as_span() :
- hit_positions_internal;
- const MutableSpan<float3> hit_normals = hit_normal_attribute ? hit_normal_attribute.as_span() :
- MutableSpan<float3>();
- const MutableSpan<float> hit_distances = hit_distance_attribute ?
- hit_distance_attribute.as_span() :
- MutableSpan<float>();
-
- raycast_to_mesh(*src_mesh,
- ray_origins,
- ray_directions,
- ray_lengths,
- is_hit,
- hit_indices,
- hit_positions,
- hit_normals,
- hit_distances);
hit_attribute.save();
hit_position_attribute.save();
hit_normal_attribute.save();
hit_distance_attribute.save();
-
- /* Custom interpolated attributes */
- bke::mesh_surface_sample::MeshAttributeInterpolator interp(src_mesh, hit_positions, hit_indices);
- for (const int i : hit_attribute_names.index_range()) {
- const std::optional<AttributeMetaData> meta_data = src_mesh_component->attribute_get_meta_data(
- hit_attribute_names[i]);
- if (meta_data) {
- ReadAttributeLookup hit_attribute = src_mesh_component->attribute_try_get_for_read(
- hit_attribute_names[i]);
- OutputAttribute hit_attribute_output = dst_component.attribute_try_get_for_output_only(
- hit_attribute_output_names[i], result_domain, meta_data->data_type);
-
- interp.sample_attribute(hit_attribute, hit_attribute_output, map_mode);
-
- hit_attribute_output.save();
- }
- }
}
static void geo_node_raycast_exec(GeoNodeExecParams params)
More information about the Bf-blender-cvs
mailing list