Geometry Nodes: Sample Materials #106666

Open
Iliya Katushenock wants to merge 5 commits from mod_moder/blender:sample_material into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 83 additions and 0 deletions
Showing only changes of commit c2c6abd5a7 - Show all commits

View File

@ -307,6 +307,7 @@ class NODE_MT_geometry_node_GEO_MATERIAL(Menu):
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeReplaceMaterial")
node_add_menu.add_node_type(layout, "GeometryNodeSampleMaterial")
layout.separator()
node_add_menu.add_node_type(layout, "GeometryNodeInputMaterialIndex")
node_add_menu.add_node_type(layout, "GeometryNodeMaterialSelection")

View File

@ -1575,6 +1575,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#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_SAMPLE_MATERIAL 1199
/** \} */

View File

@ -397,6 +397,7 @@ DefNode(GeometryNode, GEO_NODE_REVERSE_CURVE, 0, "REVERSE_CURVE", ReverseCurve,
DefNode(GeometryNode, GEO_NODE_ROTATE_INSTANCES, 0, "ROTATE_INSTANCES", RotateInstances, "Rotate Instances", "Rotate geometry instances in local or global space")
DefNode(GeometryNode, GEO_NODE_SAMPLE_CURVE, def_geo_curve_sample, "SAMPLE_CURVE", SampleCurve, "Sample Curve", "Retrieve data from a point on a curve at a certain distance from its start")
DefNode(GeometryNode, GEO_NODE_SAMPLE_INDEX, def_geo_sample_index, "SAMPLE_INDEX", SampleIndex, "Sample Index", "Retrieve values from specific geometry elements")
DefNode(GeometryNode, GEO_NODE_SAMPLE_MATERIAL, 0, "SAMPLE_MATERIAL", SampleMaterial, "Sample Material", "")
DefNode(GeometryNode, GEO_NODE_SAMPLE_NEAREST_SURFACE, def_geo_sample_nearest_surface, "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, def_geo_sample_nearest, "SAMPLE_NEAREST", SampleNearest, "Sample Nearest", "Find the element of a geometry closest to a position")
DefNode(GeometryNode, GEO_NODE_SAMPLE_UV_SURFACE, def_geo_sample_uv_surface, "SAMPLE_UV_SURFACE", SampleUVSurface, "Sample UV Surface", "Calculate the interpolated values of a mesh attribute at a UV coordinate")

View File

@ -148,6 +148,7 @@ set(SRC
nodes/node_geo_remove_attribute.cc
nodes/node_geo_rotate_instances.cc
nodes/node_geo_sample_index.cc
nodes/node_geo_sample_material.cc
nodes/node_geo_sample_nearest.cc
nodes/node_geo_sample_nearest_surface.cc
nodes/node_geo_sample_uv_surface.cc

View File

@ -132,6 +132,7 @@ void register_geometry_nodes()
register_node_type_geo_remove_attribute();
register_node_type_geo_rotate_instances();
register_node_type_geo_sample_index();
register_node_type_geo_sample_material();
register_node_type_geo_sample_nearest_surface();
register_node_type_geo_sample_nearest();
register_node_type_geo_sample_uv_surface();

View File

@ -129,6 +129,7 @@ void register_node_type_geo_realize_instances();
void register_node_type_geo_remove_attribute();
void register_node_type_geo_rotate_instances();
void register_node_type_geo_sample_index();
void register_node_type_geo_sample_material();
void register_node_type_geo_sample_nearest_surface();
void register_node_type_geo_sample_nearest();
void register_node_type_geo_sample_uv_surface();

View File

@ -0,0 +1,77 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "DEG_depsgraph_query.h"
#include "BLI_task.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_curves.hh"
#include "BKE_mesh.hh"
#include "node_geometry_util.hh"
namespace blender::nodes::node_geo_sample_material_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Geometry"));
b.add_input<decl::Geometry>(N_("Material Source"));
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().field_on({0});
b.add_input<decl::Int>(N_("Material Index")).default_value(1).field_on({0});
/* TODO: It's possible to avoid propagation from second geometry input? Or i miss something? */
b.add_output<decl::Geometry>(N_("Geometry")).propagate_all();
}
static void node_geo_exec(GeoNodeExecParams params)
{
GeometrySet geometry = params.extract_input<GeometrySet>("Geometry");
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
Field<int> index_field = params.extract_input<Field<int>>("Material Index");
geometry.modify_geometry_sets([&](GeometrySet &geometry_set) {
const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>();
Mesh *mesh = geometry_set.get_mesh_for_write();
if (!mesh) {
return;
}
bke::GeometryFieldContext field_context{*component, ATTR_DOMAIN_FACE};
fn::FieldEvaluator evaluator{field_context, mesh->totpoly};
evaluator.set_selection(selection_field);
evaluator.add(index_field);
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
if (selection.is_empty()) {
return;
}
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter<int> dst_indices_attribute = attributes.lookup_or_add_for_write_only_span<int>("material_index", ATTR_DOMAIN_FACE);
MutableSpan<int> dst_indices = dst_indices_attribute.span;
const VArray<int> &indices = evaluator.get_evaluated<int>(0);
indices.materialize(selection, dst_indices);
dst_indices_attribute.finish();
});
params.set_output("Geometry", std::move(geometry));
}
} // namespace blender::nodes::node_geo_sample_material_cc
void register_node_type_geo_sample_material()
{
namespace file_ns = blender::nodes::node_geo_sample_material_cc;
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_SAMPLE_MATERIAL, "Sample Material", NODE_CLASS_GEOMETRY);
ntype.geometry_node_execute = file_ns::node_geo_exec;
ntype.declare = file_ns::node_declare;
nodeRegisterType(&ntype);
}