Geometry Nodes: Remove experimental volume nodes

The new grid socket (#115270) will make these nodes obsolete and
provide more elegant ways of implementing the features. Removing
these nodes now to clean up and make future changes simpler.

Pull Request: https://projects.blender.org/blender/blender/pulls/115567
This commit is contained in:
Lukas Tönne 2023-11-29 16:02:06 +01:00
parent 21712cf746
commit 5bc82b5b7c
12 changed files with 7 additions and 1155 deletions

View File

@ -407,8 +407,6 @@ class NODE_MT_geometry_node_GEO_MESH_OPERATIONS(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeMeshBoolean")
node_add_menu.add_node_type(layout, "GeometryNodeMeshToCurve")
node_add_menu.add_node_type(layout, "GeometryNodeMeshToPoints")
if context.preferences.experimental.use_new_volume_nodes:
node_add_menu.add_node_type(layout, "GeometryNodeMeshToSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodeMeshToVolume")
node_add_menu.add_node_type(layout, "GeometryNodeScaleElements")
node_add_menu.add_node_type(layout, "GeometryNodeSplitEdges")
@ -475,8 +473,6 @@ class NODE_MT_category_GEO_POINT(Menu):
node_add_menu.add_node_type(layout, "GeometryNodePoints")
node_add_menu.add_node_type(layout, "GeometryNodePointsToCurves")
node_add_menu.add_node_type(layout, "GeometryNodePointsToVertices")
if context.preferences.experimental.use_new_volume_nodes:
node_add_menu.add_node_type(layout, "GeometryNodePointsToSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodePointsToVolume")
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeSetPointRadius")
@ -637,13 +633,6 @@ class NODE_MT_category_GEO_VOLUME(Menu):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeVolumeCube")
node_add_menu.add_node_type(layout, "GeometryNodeVolumeToMesh")
if context.preferences.experimental.use_new_volume_nodes:
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeMeanFilterSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodeOffsetSDFVolume")
node_add_menu.add_node_type(layout, "GeometryNodeSampleVolume")
node_add_menu.add_node_type(layout, "GeometryNodeSDFVolumeSphere")
node_add_menu.add_node_type(layout, "GeometryNodeInputSignedDistance")
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)

View File

@ -1291,17 +1291,17 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define GEO_NODE_IMAGE 1191
#define GEO_NODE_INTERPOLATE_CURVES 1192
#define GEO_NODE_EDGES_TO_FACE_GROUPS 1193
#define GEO_NODE_POINTS_TO_SDF_VOLUME 1194
#define GEO_NODE_MESH_TO_SDF_VOLUME 1195
#define GEO_NODE_SDF_VOLUME_SPHERE 1196
#define GEO_NODE_MEAN_FILTER_SDF_VOLUME 1197
#define GEO_NODE_OFFSET_SDF_VOLUME 1198
// #define GEO_NODE_POINTS_TO_SDF_VOLUME 1194
// #define GEO_NODE_MESH_TO_SDF_VOLUME 1195
// #define GEO_NODE_SDF_VOLUME_SPHERE 1196
// #define GEO_NODE_MEAN_FILTER_SDF_VOLUME 1197
// #define GEO_NODE_OFFSET_SDF_VOLUME 1198
#define GEO_NODE_INDEX_OF_NEAREST 1199
/* Function nodes use the range starting at 1200. */
#define GEO_NODE_SIMULATION_INPUT 2100
#define GEO_NODE_SIMULATION_OUTPUT 2101
#define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
#define GEO_NODE_SAMPLE_VOLUME 2103
// #define GEO_NODE_INPUT_SIGNED_DISTANCE 2102
// #define GEO_NODE_SAMPLE_VOLUME 2103
#define GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_EDGE 2104
/* Leaving out two indices to avoid crashes with files that were created during the development of
* the repeat zone. */

View File

@ -1882,13 +1882,6 @@ typedef struct NodeGeometryDistributePointsInVolume {
uint8_t mode;
} NodeGeometryDistributePointsInVolume;
typedef struct NodeGeometrySampleVolume {
/** #eCustomDataType. */
int8_t grid_type;
/** #GeometryNodeSampleVolumeInterpolationMode */
int8_t interpolation_mode;
} NodeGeometrySampleVolume;
typedef struct NodeFunctionCompare {
/** #NodeCompareOperation */
int8_t operation;
@ -2781,12 +2774,6 @@ typedef enum GeometryNodeScaleElementsMode {
GEO_NODE_SCALE_ELEMENTS_SINGLE_AXIS = 1,
} GeometryNodeScaleElementsMode;
typedef enum GeometryNodeSampleVolumeInterpolationMode {
GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_NEAREST = 0,
GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_TRILINEAR = 1,
GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_TRIQUADRATIC = 2,
} GeometryNodeSampleVolumeInterpolationMode;
typedef enum NodeCombSepColorMode {
NODE_COMBSEP_COLOR_RGB = 0,
NODE_COMBSEP_COLOR_HSV = 1,

View File

@ -360,7 +360,6 @@ DefNode(GeometryNode, GEO_NODE_INPUT_RADIUS, 0, "INPUT_RADIUS", InputRadius, "Ra
DefNode(GeometryNode, GEO_NODE_INPUT_SCENE_TIME, 0, "INPUT_SCENE_TIME", InputSceneTime, "Scene Time", "Retrieve the current time in the scene's animation in units of seconds or frames")
DefNode(GeometryNode, GEO_NODE_INPUT_FACE_SMOOTH, 0, "INPUT_SHADE_SMOOTH", InputShadeSmooth, "Is Face Smooth", "Retrieve whether each face is marked for smooth or sharp normals")
DefNode(GeometryNode, GEO_NODE_INPUT_SHORTEST_EDGE_PATHS, 0, "SHORTEST_EDGE_PATHS", InputShortestEdgePaths, "Shortest Edge Paths", "Find the shortest paths along mesh edges to selected end vertices, with customizable cost per edge")
DefNode(GeometryNode, GEO_NODE_INPUT_SIGNED_DISTANCE, 0, "SIGNED_DISTANCE", InputSignedDistance, "Signed Distance", "Retrieve the signed distance field grid called 'distance' from a volume")
DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_CYCLIC, 0, "INPUT_SPLINE_CYCLIC",InputSplineCyclic, "Is Spline Cyclic", "Retrieve whether each spline endpoint connects to the beginning")
DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_LENGTH, 0, "SPLINE_LENGTH", SplineLength, "Spline Length", "Retrieve the total length of each spline, as a distance or as a number of points")
DefNode(GeometryNode, GEO_NODE_INPUT_SPLINE_RESOLUTION, 0, "INPUT_SPLINE_RESOLUTION", InputSplineResolution, "Spline Resolution", "Retrieve the number of evaluated points that will be generated for every control point on curves")
@ -370,7 +369,6 @@ DefNode(GeometryNode, GEO_NODE_INSTANCES_TO_POINTS, 0, "INSTANCES_TO_POINTS",Ins
DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "Retrieve whether the nodes are being evaluated for the viewport rather than the final render")
DefNode(GeometryNode, GEO_NODE_JOIN_GEOMETRY, 0, "JOIN_GEOMETRY", JoinGeometry, "Join Geometry", "Merge separately generated geometries into a single one")
DefNode(GeometryNode, GEO_NODE_MATERIAL_SELECTION, 0, "MATERIAL_SELECTION", MaterialSelection, "Material Selection", "Provide a selection of faces that use the specified material")
DefNode(GeometryNode, GEO_NODE_MEAN_FILTER_SDF_VOLUME, 0, "MEAN_FILTER_SDF_VOLUME", MeanFilterSDFVolume, "Mean Filter SDF Volume", "Smooth the surface of an SDF volume by applying a mean filter")
DefNode(GeometryNode, GEO_NODE_MERGE_BY_DISTANCE, 0, "MERGE_BY_DISTANCE", MergeByDistance, "Merge by Distance", "Merge vertices or points within a given distance")
DefNode(GeometryNode, GEO_NODE_MESH_BOOLEAN, 0, "MESH_BOOLEAN", MeshBoolean, "Mesh Boolean", "Cut, subtract, or join multiple mesh inputs")
DefNode(GeometryNode, GEO_NODE_MESH_FACE_GROUP_BOUNDARIES, 0, "MESH_FACE_SET_BOUNDARIES", MeshFaceSetBoundaries, "Face Group Boundaries", "Find edges on the boundaries between groups of faces with the same ID value")
@ -384,7 +382,6 @@ DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_LINE, 0, "MESH_PRIMITIVE_LINE",Mes
DefNode(GeometryNode, GEO_NODE_MESH_PRIMITIVE_UV_SPHERE, 0, "MESH_PRIMITIVE_UV_SPHERE", MeshUVSphere, "UV Sphere", "Generate a spherical mesh with quads, except for triangles at the top and bottom")
DefNode(GeometryNode, GEO_NODE_MESH_TO_CURVE, 0, "MESH_TO_CURVE", MeshToCurve, "Mesh to Curve", "Generate a curve from a mesh")
DefNode(GeometryNode, GEO_NODE_MESH_TO_POINTS, 0, "MESH_TO_POINTS", MeshToPoints, "Mesh to Points", "Generate a point cloud from a mesh's vertices")
DefNode(GeometryNode, GEO_NODE_MESH_TO_SDF_VOLUME, 0, "MESH_TO_SDF_VOLUME", MeshToSDFVolume, "Mesh to SDF Volume", "Create an SDF volume with the shape of the input mesh's surface")
DefNode(GeometryNode, GEO_NODE_MESH_TO_VOLUME, 0, "MESH_TO_VOLUME", MeshToVolume, "Mesh to Volume", "Create a fog volume with the shape of the input mesh's surface")
DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_EDGE, 0, "CORNERS_OF_EDGE", CornersOfEdge, "Corners of Edge", "Retrieve face corners connected to edges")
DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_CORNERS_OF_FACE, 0, "CORNERS_OF_FACE", CornersOfFace, "Corners of Face", "Retrieve corners that make up a face")
@ -396,13 +393,11 @@ DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_OFFSET_CORNER_IN_FACE, 0, "OFFSET_C
DefNode(GeometryNode, GEO_NODE_MESH_TOPOLOGY_VERTEX_OF_CORNER, 0, "VERTEX_OF_CORNER", VertexOfCorner, "Vertex of Corner", "Retrieve the vertex each face corner is attached to")
DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "Retrieve information from an object")
DefNode(GeometryNode, GEO_NODE_OFFSET_POINT_IN_CURVE, 0, "OFFSET_POINT_IN_CURVE", OffsetPointInCurve, "Offset Point in Curve", "Offset a control point index within its curve")
DefNode(GeometryNode, GEO_NODE_OFFSET_SDF_VOLUME, 0, "OFFSET_SDF_VOLUME", OffsetSDFVolume, "Offset SDF Volume", "Move the surface of an SDF volume inwards or outwards")
DefNode(GeometryNode, GEO_NODE_TOOL_FACE_SET, 0, "TOOL_FACE_SET", ToolFaceSet, "Face Set", "Each face's sculpt face set value")
DefNode(GeometryNode, GEO_NODE_TOOL_3D_CURSOR, 0, "TOOL_3D_CURSOR", Tool3DCursor, "3D Cursor", "The scene's 3D cursor location and rotation")
DefNode(GeometryNode, GEO_NODE_TOOL_SELECTION, 0, "TOOL_SELECTION", ToolSelection, "Selection", "User selection of the edited geometry, for tool execution")
DefNode(GeometryNode, GEO_NODE_TOOL_SET_SELECTION, 0, "TOOL_SELECTION_SET", ToolSetSelection, "Set Selection", "Set selection of the edited geometry, for tool execution")
DefNode(GeometryNode, GEO_NODE_TOOL_SET_FACE_SET, 0, "TOOL_SET_FACE_SET", ToolSetFaceSet, "Set Face Set", "Set sculpt face set values for faces")
DefNode(GeometryNode, GEO_NODE_POINTS_TO_SDF_VOLUME, 0, "POINTS_TO_SDF_VOLUME", PointsToSDFVolume, "Points to SDF Volume", "Generate an SDF volume sphere around every point")
DefNode(GeometryNode, GEO_NODE_POINTS_TO_VERTICES, 0, "POINTS_TO_VERTICES", PointsToVertices, "Points to Vertices", "Generate a mesh vertex for each point cloud point")
DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, 0, "POINTS_TO_VOLUME", PointsToVolume, "Points to Volume", "Generate a fog volume sphere around every point")
DefNode(GeometryNode, GEO_NODE_POINTS, 0, "POINTS", Points, "Points", "Generate a point cloud with positions and radii defined by fields")
@ -421,10 +416,8 @@ DefNode(GeometryNode, GEO_NODE_SAMPLE_INDEX, def_geo_sample_index, "SAMPLE_INDEX
DefNode(GeometryNode, GEO_NODE_SAMPLE_NEAREST_SURFACE, 0, "SAMPLE_NEAREST_SURFACE", SampleNearestSurface, "Sample Nearest Surface", "Calculate the interpolated value of a mesh attribute on the closest point of its surface")
DefNode(GeometryNode, GEO_NODE_SAMPLE_NEAREST, 0, "SAMPLE_NEAREST", SampleNearest, "Sample Nearest", "Find the element of a geometry closest to a position. Similar to the \"Index of Nearest\" node")
DefNode(GeometryNode, GEO_NODE_SAMPLE_UV_SURFACE, 0, "SAMPLE_UV_SURFACE", SampleUVSurface, "Sample UV Surface", "Calculate the interpolated values of a mesh attribute at a UV coordinate")
DefNode(GeometryNode, GEO_NODE_SAMPLE_VOLUME, 0, "SAMPLE_VOLUME", SampleVolume, "Sample Volume", "Calculate the interpolated values of a Volume grid at the specified position")
DefNode(GeometryNode, GEO_NODE_SCALE_ELEMENTS, 0, "SCALE_ELEMENTS", ScaleElements, "Scale Elements", "Scale groups of connected edges and faces")
DefNode(GeometryNode, GEO_NODE_SCALE_INSTANCES, 0, "SCALE_INSTANCES", ScaleInstances, "Scale Instances", "Scale geometry instances in local or global space")
DefNode(GeometryNode, GEO_NODE_SDF_VOLUME_SPHERE, 0, "SDF_VOLUME_SPHERE", SDFVolumeSphere, "SDF Volume Sphere", "Generate an SDF Volume Sphere")
DefNode(GeometryNode, GEO_NODE_SELF_OBJECT, 0, "SELF_OBJECT", SelfObject, "Self Object", "Retrieve the object that contains the geometry nodes modifier currently being executed")
DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS",SeparateComponents, "Separate Components", "Split a geometry into a separate output for each type of data in the geometry")
DefNode(GeometryNode, GEO_NODE_SEPARATE_GEOMETRY, 0, "SEPARATE_GEOMETRY", SeparateGeometry, "Separate Geometry", "Split a geometry into two geometry outputs based on a selection")

View File

@ -105,7 +105,6 @@ set(SRC
nodes/node_geo_input_radius.cc
nodes/node_geo_input_scene_time.cc
nodes/node_geo_input_shortest_edge_paths.cc
nodes/node_geo_input_signed_distance.cc
nodes/node_geo_input_spline_cyclic.cc
nodes/node_geo_input_spline_length.cc
nodes/node_geo_input_spline_resolution.cc
@ -117,7 +116,6 @@ set(SRC
nodes/node_geo_join_geometry.cc
nodes/node_geo_material_replace.cc
nodes/node_geo_material_selection.cc
nodes/node_geo_mean_filter_sdf_volume.cc
nodes/node_geo_merge_by_distance.cc
nodes/node_geo_mesh_face_group_boundaries.cc
nodes/node_geo_mesh_primitive_circle.cc
@ -131,7 +129,6 @@ set(SRC
nodes/node_geo_mesh_subdivide.cc
nodes/node_geo_mesh_to_curve.cc
nodes/node_geo_mesh_to_points.cc
nodes/node_geo_mesh_to_sdf_volume.cc
nodes/node_geo_mesh_to_volume.cc
nodes/node_geo_mesh_topology_corners_of_edge.cc
nodes/node_geo_mesh_topology_corners_of_face.cc
@ -143,10 +140,8 @@ set(SRC
nodes/node_geo_mesh_topology_vertex_of_corner.cc
nodes/node_geo_object_info.cc
nodes/node_geo_offset_point_in_curve.cc
nodes/node_geo_offset_sdf_volume.cc
nodes/node_geo_points.cc
nodes/node_geo_points_to_curves.cc
nodes/node_geo_points_to_sdf_volume.cc
nodes/node_geo_points_to_vertices.cc
nodes/node_geo_points_to_volume.cc
nodes/node_geo_proximity.cc
@ -160,10 +155,8 @@ set(SRC
nodes/node_geo_sample_nearest.cc
nodes/node_geo_sample_nearest_surface.cc
nodes/node_geo_sample_uv_surface.cc
nodes/node_geo_sample_volume.cc
nodes/node_geo_scale_elements.cc
nodes/node_geo_scale_instances.cc
nodes/node_geo_sdf_volume_sphere.cc
nodes/node_geo_self_object.cc
nodes/node_geo_separate_components.cc
nodes/node_geo_separate_geometry.cc

View File

@ -1,41 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "NOD_socket_search_link.hh"
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_input_signed_distance_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Float>("Signed Distance").field_source();
}
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (U.experimental.use_new_volume_nodes) {
nodes::search_link_ops_for_basic_node(params);
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
Field<float> signed_distance_field{AttributeFieldInput::Create<float>("distance")};
params.set_output("Signed Distance", std::move(signed_distance_field));
}
static void node_register()
{
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_INPUT_SIGNED_DISTANCE, "Signed Distance", NODE_CLASS_INPUT);
ntype.geometry_node_execute = node_geo_exec;
ntype.declare = node_declare;
ntype.gather_link_search_ops = search_link_ops;
nodeRegisterType(&ntype);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_input_signed_distance_cc

View File

@ -1,100 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DEG_depsgraph_query.hh"
#ifdef WITH_OPENVDB
# include <openvdb/tools/LevelSetFilter.h>
#endif
#include "node_geometry_util.hh"
#include "BKE_volume.hh"
#include "BKE_volume_openvdb.hh"
#include "DNA_node_types.h"
#include "NOD_socket_search_link.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
namespace blender::nodes::node_geo_mean_filter_sdf_volume_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>("Volume")
.supported_type(GeometryComponent::Type::Volume)
.translation_context(BLT_I18NCONTEXT_ID_ID);
b.add_input<decl::Int>("Iterations").min(1).max(256).default_value(1);
b.add_input<decl::Int>("Width").min(0).default_value(1);
b.add_output<decl::Geometry>("Volume").translation_context(BLT_I18NCONTEXT_ID_ID);
}
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (U.experimental.use_new_volume_nodes) {
blender::nodes::search_link_ops_for_basic_node(params);
}
}
#ifdef WITH_OPENVDB
static void sdf_volume_mean_filter(Volume &volume, const GeoNodeExecParams &params)
{
VolumeGrid *volume_grid = BKE_volume_grid_find_for_write(&volume, "distance");
if (volume_grid == nullptr) {
return;
}
openvdb::GridBase::Ptr base_grid = BKE_volume_grid_openvdb_for_write(
&volume, volume_grid, false);
if (!base_grid->isType<openvdb::FloatGrid>()) {
return;
}
openvdb::FloatGrid::Ptr levelset_grid = openvdb::gridPtrCast<openvdb::FloatGrid>(base_grid);
openvdb::tools::LevelSetFilter<openvdb::FloatGrid> filter(*levelset_grid);
int iterations = params.get_input<int>("Iterations");
for (int i = 0; i < iterations; i++) {
filter.mean(params.get_input<int>("Width"));
}
}
#endif
static void node_geo_exec(GeoNodeExecParams params)
{
#ifdef WITH_OPENVDB
GeometrySet geometry_set = params.extract_input<GeometrySet>("Volume");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (!geometry_set.has_volume()) {
return;
}
VolumeComponent &component = geometry_set.get_component_for_write<VolumeComponent>();
Volume *volume = component.get_for_write();
BKE_volume_load(volume, DEG_get_bmain(params.depsgraph()));
sdf_volume_mean_filter(*volume, params);
});
params.set_output("Volume", std::move(geometry_set));
#else
params.set_default_remaining_outputs();
params.error_message_add(NodeWarningType::Error,
TIP_("Disabled, Blender was compiled without OpenVDB"));
#endif
}
static void node_register()
{
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_MEAN_FILTER_SDF_VOLUME, "Mean Filter SDF Volume", NODE_CLASS_GEOMETRY);
blender::bke::node_type_size(&ntype, 160, 120, 700);
ntype.declare = node_declare;
ntype.geometry_node_execute = node_geo_exec;
ntype.gather_link_search_ops = search_link_ops;
nodeRegisterType(&ntype);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_mean_filter_sdf_volume_cc

View File

@ -1,200 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DEG_depsgraph_query.hh"
#include "node_geometry_util.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.hh"
#include "BKE_mesh_wrapper.hh"
#include "BKE_object.hh"
#include "BKE_volume.hh"
#include "GEO_mesh_to_volume.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "NOD_socket_search_link.hh"
#include "NOD_rna_define.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
namespace blender::nodes::node_geo_mesh_to_sdf_volume_cc {
NODE_STORAGE_FUNCS(NodeGeometryMeshToVolume)
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>("Mesh").supported_type(GeometryComponent::Type::Mesh);
b.add_input<decl::Float>("Voxel Size")
.default_value(0.3f)
.min(0.01f)
.max(FLT_MAX)
.subtype(PROP_DISTANCE);
b.add_input<decl::Float>("Voxel Amount").default_value(64.0f).min(0.0f).max(FLT_MAX);
b.add_input<decl::Float>("Half-Band Width")
.default_value(3.0f)
.min(1.01f)
.max(10.0f)
.description("Half the width of the narrow band in voxel units");
b.add_output<decl::Geometry>("Volume").translation_context(BLT_I18NCONTEXT_ID_ID);
}
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (U.experimental.use_new_volume_nodes) {
nodes::search_link_ops_for_basic_node(params);
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "resolution_mode", UI_ITEM_NONE, IFACE_("Resolution"), ICON_NONE);
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
NodeGeometryMeshToVolume *data = MEM_cnew<NodeGeometryMeshToVolume>(__func__);
data->resolution_mode = MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT;
node->storage = data;
}
static void node_update(bNodeTree *ntree, bNode *node)
{
NodeGeometryMeshToVolume &data = node_storage(*node);
bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size");
bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount");
bke::nodeSetSocketAvailability(ntree,
voxel_amount_socket,
data.resolution_mode ==
MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT);
bke::nodeSetSocketAvailability(
ntree, voxel_size_socket, data.resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE);
}
#ifdef WITH_OPENVDB
static Volume *create_volume_from_mesh(const Mesh &mesh, GeoNodeExecParams &params)
{
const NodeGeometryMeshToVolume &storage = node_storage(params.node());
const float half_band_width = params.get_input<float>("Half-Band Width");
geometry::MeshToVolumeResolution resolution;
resolution.mode = (MeshToVolumeModifierResolutionMode)storage.resolution_mode;
if (resolution.mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) {
resolution.settings.voxel_amount = params.get_input<float>("Voxel Amount");
if (resolution.settings.voxel_amount <= 0.0f) {
return nullptr;
}
}
else if (resolution.mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE) {
resolution.settings.voxel_size = params.get_input<float>("Voxel Size");
if (resolution.settings.voxel_size <= 0.0f) {
return nullptr;
}
}
if (mesh.faces_num == 0) {
return nullptr;
}
const float4x4 mesh_to_volume_space_transform = float4x4::identity();
const float voxel_size = geometry::volume_compute_voxel_size(
params.depsgraph(),
[&]() { return *mesh.bounds_min_max(); },
resolution,
half_band_width,
mesh_to_volume_space_transform);
if (voxel_size < 1e-5f) {
/* The voxel size is too small. */
return nullptr;
}
Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr));
/* Convert mesh to grid and add to volume. */
geometry::sdf_volume_grid_add_from_mesh(volume, "distance", mesh, voxel_size, half_band_width);
return volume;
}
#endif /* WITH_OPENVDB */
static void node_geo_exec(GeoNodeExecParams params)
{
#ifdef WITH_OPENVDB
GeometrySet geometry_set(params.extract_input<GeometrySet>("Mesh"));
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (geometry_set.has_mesh()) {
Volume *volume = create_volume_from_mesh(*geometry_set.get_mesh(), params);
geometry_set.replace_volume(volume);
geometry_set.keep_only_during_modify({GeometryComponent::Type::Volume});
}
});
params.set_output("Volume", std::move(geometry_set));
#else
params.set_default_remaining_outputs();
params.error_message_add(NodeWarningType::Error,
TIP_("Disabled, Blender was compiled without OpenVDB"));
return;
#endif
}
static void node_rna(StructRNA *srna)
{
static EnumPropertyItem resolution_mode_items[] = {
{MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT,
"VOXEL_AMOUNT",
0,
"Amount",
"Desired number of voxels along one axis"},
{MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE,
"VOXEL_SIZE",
0,
"Size",
"Desired voxel side length"},
{0, nullptr, 0, nullptr, nullptr},
};
RNA_def_node_enum(srna,
"resolution_mode",
"Resolution Mode",
"How the voxel size is specified",
resolution_mode_items,
NOD_storage_enum_accessors(resolution_mode),
MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT);
}
static void node_register()
{
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_MESH_TO_SDF_VOLUME, "Mesh to SDF Volume", NODE_CLASS_GEOMETRY);
ntype.declare = node_declare;
blender::bke::node_type_size(&ntype, 180, 120, 300);
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
ntype.geometry_node_execute = node_geo_exec;
ntype.draw_buttons = node_layout;
ntype.gather_link_search_ops = search_link_ops;
node_type_storage(
&ntype, "NodeGeometryMeshToVolume", node_free_standard_storage, node_copy_standard_storage);
nodeRegisterType(&ntype);
node_rna(ntype.rna_ext.srna);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_mesh_to_sdf_volume_cc

View File

@ -1,94 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DEG_depsgraph_query.hh"
#ifdef WITH_OPENVDB
# include <openvdb/tools/LevelSetFilter.h>
#endif
#include "node_geometry_util.hh"
#include "BKE_volume.hh"
#include "BKE_volume_openvdb.hh"
#include "DNA_node_types.h"
#include "NOD_socket_search_link.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
namespace blender::nodes::node_geo_offset_sdf_volume_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>("Volume")
.supported_type(GeometryComponent::Type::Volume)
.translation_context(BLT_I18NCONTEXT_ID_ID);
b.add_input<decl::Float>("Distance").default_value(0.1f).subtype(PROP_DISTANCE);
b.add_output<decl::Geometry>("Volume").translation_context(BLT_I18NCONTEXT_ID_ID);
}
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (U.experimental.use_new_volume_nodes) {
nodes::search_link_ops_for_basic_node(params);
}
}
#ifdef WITH_OPENVDB
static void sdf_volume_offset(Volume &volume, const GeoNodeExecParams &params)
{
VolumeGrid *volume_grid = BKE_volume_grid_find_for_write(&volume, "distance");
if (volume_grid == nullptr) {
return;
}
openvdb::GridBase::Ptr base_grid = BKE_volume_grid_openvdb_for_write(
&volume, volume_grid, false);
if (!base_grid->isType<openvdb::FloatGrid>()) {
return;
}
openvdb::FloatGrid::Ptr levelset_grid = openvdb::gridPtrCast<openvdb::FloatGrid>(base_grid);
openvdb::tools::LevelSetFilter<openvdb::FloatGrid> filter(*levelset_grid);
filter.offset(-params.get_input<float>("Distance"));
}
#endif
static void node_geo_exec(GeoNodeExecParams params)
{
#ifdef WITH_OPENVDB
GeometrySet geometry_set = params.extract_input<GeometrySet>("Volume");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (!geometry_set.has_volume()) {
return;
}
VolumeComponent &component = geometry_set.get_component_for_write<VolumeComponent>();
Volume *volume = component.get_for_write();
BKE_volume_load(volume, DEG_get_bmain(params.depsgraph()));
sdf_volume_offset(*volume, params);
});
params.set_output("Volume", std::move(geometry_set));
#else
params.set_default_remaining_outputs();
params.error_message_add(NodeWarningType::Error,
TIP_("Disabled, Blender was compiled without OpenVDB"));
#endif
}
static void node_register()
{
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_OFFSET_SDF_VOLUME, "Offset SDF Volume", NODE_CLASS_GEOMETRY);
ntype.declare = node_declare;
ntype.geometry_node_execute = node_geo_exec;
ntype.gather_link_search_ops = search_link_ops;
nodeRegisterType(&ntype);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_offset_sdf_volume_cc

View File

@ -1,149 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#ifdef WITH_OPENVDB
# include <openvdb/Types.h>
#endif
#include "node_geometry_util.hh"
#include "GEO_points_to_volume.hh"
#include "NOD_socket_search_link.hh"
#include "NOD_rna_define.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
namespace blender::nodes::node_geo_points_to_sdf_volume_cc {
NODE_STORAGE_FUNCS(NodeGeometryPointsToVolume)
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>("Points");
b.add_input<decl::Float>("Voxel Size")
.default_value(0.3f)
.min(0.01f)
.subtype(PROP_DISTANCE)
.make_available([](bNode &node) {
node_storage(node).resolution_mode = GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE;
});
b.add_input<decl::Float>("Voxel Amount")
.default_value(64.0f)
.min(0.0f)
.make_available([](bNode &node) {
node_storage(node).resolution_mode = GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT;
});
b.add_input<decl::Float>("Radius")
.default_value(0.5f)
.min(0.0f)
.subtype(PROP_DISTANCE)
.field_on_all();
b.add_output<decl::Geometry>("Volume").translation_context(BLT_I18NCONTEXT_ID_ID);
}
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (U.experimental.use_new_volume_nodes) {
nodes::search_link_ops_for_basic_node(params);
}
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "resolution_mode", UI_ITEM_NONE, IFACE_("Resolution"), ICON_NONE);
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
NodeGeometryPointsToVolume *data = MEM_cnew<NodeGeometryPointsToVolume>(__func__);
data->resolution_mode = GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT;
node->storage = data;
}
static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometryPointsToVolume &storage = node_storage(*node);
bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size");
bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount");
bke::nodeSetSocketAvailability(ntree,
voxel_amount_socket,
storage.resolution_mode ==
GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT);
bke::nodeSetSocketAvailability(ntree,
voxel_size_socket,
storage.resolution_mode ==
GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE);
}
static void node_geo_exec(GeoNodeExecParams params)
{
#ifdef WITH_OPENVDB
GeometrySet geometry_set = params.extract_input<GeometrySet>("Points");
const NodeGeometryPointsToVolume &storage = node_storage(params.node());
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
initialize_volume_component_from_points(
params, storage, geometry_set, openvdb::GRID_LEVEL_SET);
});
params.set_output("Volume", std::move(geometry_set));
#else
params.set_default_remaining_outputs();
params.error_message_add(NodeWarningType::Error,
TIP_("Disabled, Blender was compiled without OpenVDB"));
#endif
}
static void node_rna(StructRNA *srna)
{
static EnumPropertyItem resolution_mode_items[] = {
{GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT,
"VOXEL_AMOUNT",
0,
"Amount",
"Specify the approximate number of voxels along the diagonal"},
{GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE,
"VOXEL_SIZE",
0,
"Size",
"Specify the voxel side length"},
{0, nullptr, 0, nullptr, nullptr},
};
RNA_def_node_enum(srna,
"resolution_mode",
"Resolution Mode",
"How the voxel size is specified",
resolution_mode_items,
NOD_storage_enum_accessors(resolution_mode),
GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT);
}
static void node_register()
{
static bNodeType ntype;
geo_node_type_base(
&ntype, GEO_NODE_POINTS_TO_SDF_VOLUME, "Points to SDF Volume", NODE_CLASS_GEOMETRY);
node_type_storage(&ntype,
"NodeGeometryPointsToVolume",
node_free_standard_storage,
node_copy_standard_storage);
bke::node_type_size(&ntype, 170, 120, 700);
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
ntype.declare = node_declare;
ntype.geometry_node_execute = node_geo_exec;
ntype.draw_buttons = node_layout;
ntype.gather_link_search_ops = search_link_ops;
nodeRegisterType(&ntype);
node_rna(ntype.rna_ext.srna);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_points_to_sdf_volume_cc

View File

@ -1,431 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DEG_depsgraph_query.hh"
#include "BKE_type_conversions.hh"
#include "BKE_volume.hh"
#include "BKE_volume_openvdb.hh"
#include "BLI_virtual_array.hh"
#include "NOD_socket_search_link.hh"
#include "node_geometry_util.hh"
#include "NOD_rna_define.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
#ifdef WITH_OPENVDB
# include <openvdb/openvdb.h>
# include <openvdb/tools/Interpolation.h>
#endif
namespace blender::nodes::node_geo_sample_volume_cc {
NODE_STORAGE_FUNCS(NodeGeometrySampleVolume)
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(CTX_N_(BLT_I18NCONTEXT_ID_ID, "Volume"))
.supported_type(GeometryComponent::Type::Volume)
.translation_context(BLT_I18NCONTEXT_ID_ID);
std::string grid_socket_description = N_(
"Expects a Named Attribute with the name of a Grid in the Volume");
b.add_input<decl::Vector>("Grid", "Grid_Vector")
.field_on_all()
.hide_value()
.description(grid_socket_description);
b.add_input<decl::Float>("Grid", "Grid_Float")
.field_on_all()
.hide_value()
.description(grid_socket_description);
b.add_input<decl::Bool>("Grid", "Grid_Bool")
.field_on_all()
.hide_value()
.description(grid_socket_description);
b.add_input<decl::Int>("Grid", "Grid_Int")
.field_on_all()
.hide_value()
.description(grid_socket_description);
b.add_input<decl::Vector>("Position").implicit_field(implicit_field_inputs::position);
b.add_output<decl::Vector>("Value", "Value_Vector").dependent_field({5});
b.add_output<decl::Float>("Value", "Value_Float").dependent_field({5});
b.add_output<decl::Bool>("Value", "Value_Bool").dependent_field({5});
b.add_output<decl::Int>("Value", "Value_Int").dependent_field({5});
}
static std::optional<eCustomDataType> other_socket_type_to_grid_type(
const eNodeSocketDatatype type)
{
switch (type) {
case SOCK_FLOAT:
return CD_PROP_FLOAT;
case SOCK_VECTOR:
case SOCK_RGBA:
return CD_PROP_FLOAT3;
case SOCK_BOOLEAN:
return CD_PROP_BOOL;
case SOCK_INT:
return CD_PROP_INT32;
default:
return std::nullopt;
}
}
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (!U.experimental.use_new_volume_nodes) {
return;
}
const NodeDeclaration &declaration = *params.node_type().static_declaration;
search_link_ops_for_declarations(params, declaration.inputs.as_span().take_back(1));
search_link_ops_for_declarations(params, declaration.inputs.as_span().take_front(1));
const std::optional<eCustomDataType> type = other_socket_type_to_grid_type(
eNodeSocketDatatype(params.other_socket().type));
if (!type) {
return;
}
/* The input and output sockets have the same name. */
params.add_item(IFACE_("Grid"), [type](LinkSearchOpParams &params) {
bNode &node = params.add_node("GeometryNodeSampleVolume");
node_storage(node).grid_type = *type;
params.update_and_connect_available_socket(node, "Grid");
});
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, ptr, "grid_type", UI_ITEM_NONE, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation_mode", UI_ITEM_NONE, "", ICON_NONE);
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
NodeGeometrySampleVolume *data = MEM_cnew<NodeGeometrySampleVolume>(__func__);
data->grid_type = CD_PROP_FLOAT;
data->interpolation_mode = GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_TRILINEAR;
node->storage = data;
}
static void node_update(bNodeTree *ntree, bNode *node)
{
const NodeGeometrySampleVolume &storage = node_storage(*node);
const eCustomDataType grid_type = eCustomDataType(storage.grid_type);
bNodeSocket *socket_value_geometry = static_cast<bNodeSocket *>(node->inputs.first);
bNodeSocket *socket_value_vector = socket_value_geometry->next;
bNodeSocket *socket_value_float = socket_value_vector->next;
bNodeSocket *socket_value_boolean = socket_value_float->next;
bNodeSocket *socket_value_int32 = socket_value_boolean->next;
bke::nodeSetSocketAvailability(ntree, socket_value_vector, grid_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, socket_value_float, grid_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, socket_value_boolean, grid_type == CD_PROP_BOOL);
bke::nodeSetSocketAvailability(ntree, socket_value_int32, grid_type == CD_PROP_INT32);
bNodeSocket *out_socket_value_vector = static_cast<bNodeSocket *>(node->outputs.first);
bNodeSocket *out_socket_value_float = out_socket_value_vector->next;
bNodeSocket *out_socket_value_boolean = out_socket_value_float->next;
bNodeSocket *out_socket_value_int32 = out_socket_value_boolean->next;
bke::nodeSetSocketAvailability(ntree, out_socket_value_vector, grid_type == CD_PROP_FLOAT3);
bke::nodeSetSocketAvailability(ntree, out_socket_value_float, grid_type == CD_PROP_FLOAT);
bke::nodeSetSocketAvailability(ntree, out_socket_value_boolean, grid_type == CD_PROP_BOOL);
bke::nodeSetSocketAvailability(ntree, out_socket_value_int32, grid_type == CD_PROP_INT32);
}
#ifdef WITH_OPENVDB
static const StringRefNull get_grid_name(GField &field)
{
if (const auto *attribute_field_input = dynamic_cast<const AttributeFieldInput *>(&field.node()))
{
return attribute_field_input->attribute_name();
}
return "";
}
static const blender::CPPType *vdb_grid_type_to_cpp_type(const VolumeGridType grid_type)
{
switch (grid_type) {
case VOLUME_GRID_FLOAT:
return &CPPType::get<float>();
case VOLUME_GRID_VECTOR_FLOAT:
return &CPPType::get<float3>();
case VOLUME_GRID_INT:
return &CPPType::get<int>();
case VOLUME_GRID_BOOLEAN:
return &CPPType::get<bool>();
default:
break;
}
return nullptr;
}
template<typename GridT>
void sample_grid(openvdb::GridBase::ConstPtr base_grid,
const Span<float3> positions,
const IndexMask &mask,
GMutableSpan dst,
const GeometryNodeSampleVolumeInterpolationMode interpolation_mode)
{
using ValueT = typename GridT::ValueType;
using AccessorT = typename GridT::ConstAccessor;
const typename GridT::ConstPtr grid = openvdb::gridConstPtrCast<GridT>(base_grid);
AccessorT accessor = grid->getConstAccessor();
auto sample_data = [&](auto sampler) {
mask.foreach_index([&](const int64_t i) {
const float3 &pos = positions[i];
ValueT value = sampler.wsSample(openvdb::Vec3R(pos.x, pos.y, pos.z));
/* Special case for vector. */
if constexpr (std::is_same_v<GridT, openvdb::VectorGrid>) {
openvdb::Vec3f vec = static_cast<openvdb::Vec3f>(value);
dst.typed<float3>()[i] = float3(vec.asV());
}
else {
dst.typed<ValueT>()[i] = value;
}
});
};
switch (interpolation_mode) {
case GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_TRILINEAR: {
openvdb::tools::GridSampler<AccessorT, openvdb::tools::BoxSampler> sampler(
accessor, grid->transform());
sample_data(sampler);
break;
}
case GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_TRIQUADRATIC: {
openvdb::tools::GridSampler<AccessorT, openvdb::tools::QuadraticSampler> sampler(
accessor, grid->transform());
sample_data(sampler);
break;
}
case GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_NEAREST:
default: {
openvdb::tools::GridSampler<AccessorT, openvdb::tools::PointSampler> sampler(
accessor, grid->transform());
sample_data(sampler);
break;
}
}
}
class SampleVolumeFunction : public mf::MultiFunction {
openvdb::GridBase::ConstPtr base_grid_;
VolumeGridType grid_type_;
GeometryNodeSampleVolumeInterpolationMode interpolation_mode_;
mf::Signature signature_;
public:
SampleVolumeFunction(openvdb::GridBase::ConstPtr base_grid,
GeometryNodeSampleVolumeInterpolationMode interpolation_mode)
: base_grid_(std::move(base_grid)), interpolation_mode_(interpolation_mode)
{
grid_type_ = BKE_volume_grid_type_openvdb(*base_grid_);
const CPPType *grid_cpp_type = vdb_grid_type_to_cpp_type(grid_type_);
BLI_assert(grid_cpp_type != nullptr);
mf::SignatureBuilder builder{"Sample Volume", signature_};
builder.single_input<float3>("Position");
builder.single_output("Value", *grid_cpp_type);
this->set_signature(&signature_);
}
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
{
const VArraySpan<float3> positions = params.readonly_single_input<float3>(0, "Position");
GMutableSpan dst = params.uninitialized_single_output(1, "Value");
switch (grid_type_) {
case VOLUME_GRID_FLOAT:
sample_grid<openvdb::FloatGrid>(base_grid_, positions, mask, dst, interpolation_mode_);
break;
case VOLUME_GRID_INT:
sample_grid<openvdb::Int32Grid>(base_grid_, positions, mask, dst, interpolation_mode_);
break;
case VOLUME_GRID_BOOLEAN:
sample_grid<openvdb::BoolGrid>(base_grid_, positions, mask, dst, interpolation_mode_);
break;
case VOLUME_GRID_VECTOR_FLOAT:
sample_grid<openvdb::VectorGrid>(base_grid_, positions, mask, dst, interpolation_mode_);
break;
default:
BLI_assert_unreachable();
break;
}
}
};
static GField get_input_attribute_field(GeoNodeExecParams &params, const eCustomDataType data_type)
{
switch (data_type) {
case CD_PROP_FLOAT:
return params.extract_input<Field<float>>("Grid_Float");
case CD_PROP_FLOAT3:
return params.extract_input<Field<float3>>("Grid_Vector");
case CD_PROP_BOOL:
return params.extract_input<Field<bool>>("Grid_Bool");
case CD_PROP_INT32:
return params.extract_input<Field<int>>("Grid_Int");
default:
BLI_assert_unreachable();
}
return {};
}
static void output_attribute_field(GeoNodeExecParams &params, GField field)
{
switch (bke::cpp_type_to_custom_data_type(field.cpp_type())) {
case CD_PROP_FLOAT:
params.set_output("Value_Float", Field<float>(field));
break;
case CD_PROP_FLOAT3:
params.set_output("Value_Vector", Field<float3>(field));
break;
case CD_PROP_BOOL:
params.set_output("Value_Bool", Field<bool>(field));
break;
case CD_PROP_INT32:
params.set_output("Value_Int", Field<int>(field));
break;
default:
break;
}
}
#endif /* WITH_OPENVDB */
static void node_geo_exec(GeoNodeExecParams params)
{
#ifdef WITH_OPENVDB
GeometrySet geometry_set = params.extract_input<GeometrySet>("Volume");
if (!geometry_set.has_volume()) {
params.set_default_remaining_outputs();
return;
}
const NodeGeometrySampleVolume &storage = node_storage(params.node());
const eCustomDataType output_field_type = eCustomDataType(storage.grid_type);
auto interpolation_mode = GeometryNodeSampleVolumeInterpolationMode(storage.interpolation_mode);
GField grid_field = get_input_attribute_field(params, output_field_type);
const StringRefNull grid_name = get_grid_name(grid_field);
if (grid_name == "") {
params.error_message_add(NodeWarningType::Error, TIP_("Grid name needs to be specified"));
params.set_default_remaining_outputs();
return;
}
const VolumeComponent *component = geometry_set.get_component<VolumeComponent>();
const Volume *volume = component->get();
BKE_volume_load(volume, DEG_get_bmain(params.depsgraph()));
const VolumeGrid *volume_grid = BKE_volume_grid_find_for_read(volume, grid_name.c_str());
if (volume_grid == nullptr) {
params.set_default_remaining_outputs();
return;
}
openvdb::GridBase::ConstPtr base_grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(*base_grid);
/* Check that the grid type is supported. */
const CPPType *grid_cpp_type = vdb_grid_type_to_cpp_type(grid_type);
if (grid_cpp_type == nullptr) {
params.set_default_remaining_outputs();
params.error_message_add(NodeWarningType::Error, TIP_("The grid type is unsupported"));
return;
}
/* Use to the Nearest Neighbor sampler for Bool grids (no interpolation). */
if (grid_type == VOLUME_GRID_BOOLEAN &&
interpolation_mode != GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_NEAREST)
{
interpolation_mode = GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_NEAREST;
}
Field<float3> position_field = params.extract_input<Field<float3>>("Position");
auto fn = std::make_shared<SampleVolumeFunction>(std::move(base_grid), interpolation_mode);
auto op = FieldOperation::Create(std::move(fn), {position_field});
GField output_field = GField(std::move(op));
output_field = bke::get_implicit_type_conversions().try_convert(
output_field, *bke::custom_data_type_to_cpp_type(output_field_type));
output_attribute_field(params, std::move(output_field));
#else
params.set_default_remaining_outputs();
params.error_message_add(NodeWarningType::Error,
TIP_("Disabled, Blender was compiled without OpenVDB"));
#endif
}
static void node_rna(StructRNA *srna)
{
static const EnumPropertyItem interpolation_mode_items[] = {
{GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_NEAREST, "NEAREST", 0, "Nearest Neighbor", ""},
{GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_TRILINEAR, "TRILINEAR", 0, "Trilinear", ""},
{GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_TRIQUADRATIC,
"TRIQUADRATIC",
0,
"Triquadratic",
""},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem grid_type_items[] = {
{CD_PROP_FLOAT, "FLOAT", 0, "Float", "Floating-point value"},
{CD_PROP_FLOAT3, "FLOAT_VECTOR", 0, "Vector", "3D vector with floating-point values"},
{CD_PROP_INT32, "INT", 0, "Integer", "32-bit integer"},
{CD_PROP_BOOL, "BOOLEAN", 0, "Boolean", "True or false"},
{0, nullptr, 0, nullptr, nullptr},
};
RNA_def_node_enum(srna,
"grid_type",
"Grid Type",
"Type of grid to sample data from",
grid_type_items,
NOD_storage_enum_accessors(grid_type),
CD_PROP_FLOAT);
RNA_def_node_enum(srna,
"interpolation_mode",
"Interpolation Mode",
"How to interpolate the values from neighboring voxels",
interpolation_mode_items,
NOD_storage_enum_accessors(interpolation_mode),
GEO_NODE_SAMPLE_VOLUME_INTERPOLATION_MODE_TRILINEAR);
}
static void node_register()
{
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SAMPLE_VOLUME, "Sample Volume", NODE_CLASS_CONVERTER);
node_type_storage(
&ntype, "NodeGeometrySampleVolume", node_free_standard_storage, node_copy_standard_storage);
ntype.initfunc = node_init;
ntype.updatefunc = node_update;
ntype.declare = node_declare;
ntype.geometry_node_execute = node_geo_exec;
ntype.draw_buttons = node_layout;
ntype.gather_link_search_ops = search_link_ops;
ntype.geometry_node_execute = node_geo_exec;
nodeRegisterType(&ntype);
node_rna(ntype.rna_ext.srna);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_sample_volume_cc

View File

@ -1,95 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#ifdef WITH_OPENVDB
# include <openvdb/openvdb.h>
# include <openvdb/tools/LevelSetSphere.h>
#endif
#include "node_geometry_util.hh"
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_volume.hh"
#include "BKE_volume_openvdb.hh"
#include "NOD_socket_search_link.hh"
namespace blender::nodes::node_geo_sdf_volume_sphere_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Float>("Radius").default_value(1.0f).min(0.0f).subtype(PROP_DISTANCE);
b.add_input<decl::Float>("Voxel Size").default_value(0.2f).min(0.01f).subtype(PROP_DISTANCE);
b.add_input<decl::Float>("Half-Band Width")
.default_value(3.0f)
.min(1.01f)
.max(10.0f)
.description("Half the width of the narrow band in voxel units");
b.add_output<decl::Geometry>("Volume").translation_context(BLT_I18NCONTEXT_ID_ID);
}
static void search_link_ops(GatherLinkSearchOpParams &params)
{
if (U.experimental.use_new_volume_nodes) {
nodes::search_link_ops_for_basic_node(params);
}
}
static void node_geo_exec(GeoNodeExecParams params)
{
#ifdef WITH_OPENVDB
float radius = params.extract_input<float>("Radius");
float voxel_size = params.extract_input<float>("Voxel Size");
float half_width = params.extract_input<float>("Half-Band Width");
if (radius <= 0.0f) {
params.error_message_add(NodeWarningType::Error, TIP_("Radius must be greater than 0"));
params.set_default_remaining_outputs();
return;
}
if (half_width <= 1.0f) {
params.error_message_add(NodeWarningType::Error,
TIP_("Half-band width must be greater than 1"));
params.set_default_remaining_outputs();
return;
}
openvdb::FloatGrid::Ptr grid;
try {
grid = openvdb::tools::createLevelSetSphere<openvdb::FloatGrid>(
radius, openvdb::Vec3f(0, 0, 0), voxel_size, half_width);
}
catch (openvdb::ArithmeticError &) {
params.error_message_add(NodeWarningType::Error, TIP_("Voxel size is too small"));
params.set_default_remaining_outputs();
return;
}
Volume *volume = reinterpret_cast<Volume *>(BKE_id_new_nomain(ID_VO, nullptr));
BKE_volume_grid_add_vdb(*volume, "distance", std::move(grid));
GeometrySet r_geometry_set = GeometrySet::from_volume(volume);
params.set_output("Volume", r_geometry_set);
#else
params.set_default_remaining_outputs();
params.error_message_add(NodeWarningType::Error,
TIP_("Disabled, Blender was compiled without OpenVDB"));
#endif
}
static void node_register()
{
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SDF_VOLUME_SPHERE, "SDF Volume Sphere", NODE_CLASS_GEOMETRY);
ntype.declare = node_declare;
blender::bke::node_type_size(&ntype, 180, 120, 300);
ntype.geometry_node_execute = node_geo_exec;
ntype.gather_link_search_ops = search_link_ops;
nodeRegisterType(&ntype);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_sdf_volume_sphere_cc