Merge branch 'blender-v5.0-release'
This commit is contained in:
@@ -46,11 +46,34 @@ template<typename T> constexpr bool is_GeoNodesMultiInput_v<GeoNodesMultiInput<T
|
||||
*/
|
||||
[[nodiscard]] bool execute_multi_function_on_value_variant(
|
||||
const mf::MultiFunction &fn,
|
||||
const std::shared_ptr<mf::MultiFunction> &owned_fn,
|
||||
Span<bke::SocketValueVariant *> input_values,
|
||||
Span<bke::SocketValueVariant *> output_values,
|
||||
GeoNodesUserData *user_data,
|
||||
std::string &r_error_message);
|
||||
|
||||
[[nodiscard]] inline bool execute_multi_function_on_value_variant(
|
||||
const std::shared_ptr<mf::MultiFunction> &owned_fn,
|
||||
const Span<bke::SocketValueVariant *> input_values,
|
||||
const Span<bke::SocketValueVariant *> output_values,
|
||||
GeoNodesUserData *user_data,
|
||||
std::string &r_error_message);
|
||||
std::string &r_error_message)
|
||||
{
|
||||
const mf::MultiFunction &fn = *owned_fn;
|
||||
return execute_multi_function_on_value_variant(
|
||||
fn, std::move(owned_fn), input_values, output_values, user_data, r_error_message);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool execute_multi_function_on_value_variant(
|
||||
const mf::MultiFunction &fn,
|
||||
const Span<bke::SocketValueVariant *> input_values,
|
||||
const Span<bke::SocketValueVariant *> output_values,
|
||||
GeoNodesUserData *user_data,
|
||||
std::string &r_error_message)
|
||||
{
|
||||
return execute_multi_function_on_value_variant(
|
||||
fn, {}, input_values, output_values, user_data, r_error_message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs implicit conversion between socket types. Returns false if the conversion is not
|
||||
|
||||
@@ -39,6 +39,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
.max(1.0f)
|
||||
.subtype(PROP_FACTOR)
|
||||
.supports_field()
|
||||
.structure_type(StructureType::Dynamic)
|
||||
.make_available([](bNode &node) {
|
||||
node_storage(node).mode = GEO_NODE_CURVE_SAMPLE_FACTOR;
|
||||
});
|
||||
@@ -46,13 +47,15 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
.min(0.0f)
|
||||
.subtype(PROP_DISTANCE)
|
||||
.supports_field()
|
||||
.structure_type(StructureType::Dynamic)
|
||||
.make_available([](bNode &node) {
|
||||
node_storage(node).mode = GEO_NODE_CURVE_SAMPLE_LENGTH;
|
||||
});
|
||||
auto &index =
|
||||
b.add_input<decl::Int>("Curve Index").supports_field().make_available([](bNode &node) {
|
||||
node_storage(node).use_all_curves = false;
|
||||
});
|
||||
auto &index = b.add_input<decl::Int>("Curve Index")
|
||||
.supports_field()
|
||||
.structure_type(StructureType::Dynamic)
|
||||
.make_available(
|
||||
[](bNode &node) { node_storage(node).use_all_curves = false; });
|
||||
|
||||
if (const bNode *node = b.node_or_null()) {
|
||||
const NodeGeometryCurveSample &storage = node_storage(*node);
|
||||
@@ -480,43 +483,83 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
const NodeGeometryCurveSample &storage = node_storage(params.node());
|
||||
const GeometryNodeCurveSampleMode mode = GeometryNodeCurveSampleMode(storage.mode);
|
||||
|
||||
Field<float> length_field = params.extract_input<Field<float>>(
|
||||
mode == GEO_NODE_CURVE_SAMPLE_FACTOR ? "Factor" : "Length");
|
||||
const StringRef length_input_name = mode == GEO_NODE_CURVE_SAMPLE_FACTOR ? "Factor" : "Length";
|
||||
auto sample_length = params.extract_input<bke::SocketValueVariant>(length_input_name);
|
||||
|
||||
GField src_values_field = params.extract_input<GField>("Value");
|
||||
|
||||
std::string error_message;
|
||||
|
||||
bke::SocketValueVariant position;
|
||||
bke::SocketValueVariant tangent;
|
||||
bke::SocketValueVariant normal;
|
||||
bke::SocketValueVariant value;
|
||||
std::shared_ptr<FieldOperation> sample_op;
|
||||
if (curves.curves_num() == 1) {
|
||||
sample_op = FieldOperation::from(
|
||||
std::make_unique<SampleCurveFunction>(
|
||||
std::move(geometry_set), mode, std::move(src_values_field)),
|
||||
{fn::make_constant_field<int>(0), std::move(length_field)});
|
||||
auto curve_index = bke::SocketValueVariant::From(fn::make_constant_field<int>(0));
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_unique<SampleCurveFunction>(
|
||||
std::move(geometry_set), mode, std::move(src_values_field)),
|
||||
{&curve_index, &sample_length},
|
||||
{&position, &tangent, &normal, &value},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (storage.use_all_curves) {
|
||||
auto index_fn = std::make_unique<SampleFloatSegmentsFunction>(
|
||||
curve_accumulated_lengths(curves), mode);
|
||||
auto index_op = FieldOperation::from(std::move(index_fn), {std::move(length_field)});
|
||||
Field<int> curve_index = Field<int>(index_op, 0);
|
||||
Field<float> length_in_curve = Field<float>(index_op, 1);
|
||||
sample_op = FieldOperation::from(
|
||||
std::make_unique<SampleCurveFunction>(
|
||||
std::move(geometry_set), GEO_NODE_CURVE_SAMPLE_LENGTH, std::move(src_values_field)),
|
||||
{std::move(curve_index), std::move(length_in_curve)});
|
||||
bke::SocketValueVariant curve_index;
|
||||
bke::SocketValueVariant length_in_curve;
|
||||
if (!execute_multi_function_on_value_variant(std::make_unique<SampleFloatSegmentsFunction>(
|
||||
curve_accumulated_lengths(curves), mode),
|
||||
{&sample_length},
|
||||
{&curve_index, &length_in_curve},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<SampleCurveFunction>(std::move(geometry_set),
|
||||
GEO_NODE_CURVE_SAMPLE_LENGTH,
|
||||
std::move(src_values_field)),
|
||||
{&curve_index, &length_in_curve},
|
||||
{&position, &tangent, &normal, &value},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Field<int> curve_index = params.extract_input<Field<int>>("Curve Index");
|
||||
Field<float> length_in_curve = std::move(length_field);
|
||||
sample_op = FieldOperation::from(
|
||||
std::make_unique<SampleCurveFunction>(
|
||||
std::move(geometry_set), mode, std::move(src_values_field)),
|
||||
{std::move(curve_index), std::move(length_in_curve)});
|
||||
auto curve_index = params.extract_input<bke::SocketValueVariant>("Curve Index");
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<SampleCurveFunction>(
|
||||
std::move(geometry_set), mode, std::move(src_values_field)),
|
||||
{&curve_index, &sample_length},
|
||||
{&position, &tangent, &normal, &value},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.set_output("Position", Field<float3>(sample_op, 0));
|
||||
params.set_output("Tangent", Field<float3>(sample_op, 1));
|
||||
params.set_output("Normal", Field<float3>(sample_op, 2));
|
||||
params.set_output("Value", GField(sample_op, 3));
|
||||
params.set_output("Position", std::move(position));
|
||||
params.set_output("Tangent", std::move(tangent));
|
||||
params.set_output("Normal", std::move(normal));
|
||||
params.set_output("Value", std::move(value));
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
|
||||
@@ -407,12 +407,21 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
return;
|
||||
}
|
||||
|
||||
Field<float3> vector_field = params.extract_input<Field<float3>>("Vector");
|
||||
auto sample_uv = params.extract_input<bke::SocketValueVariant>("Vector");
|
||||
|
||||
auto image_op = FieldOperation::from(std::move(image_fn), {std::move(vector_field)});
|
||||
std::string error_message;
|
||||
bke::SocketValueVariant color;
|
||||
bke::SocketValueVariant alpha;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::move(image_fn), {&sample_uv}, {&color, &alpha}, params.user_data(), error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Color", Field<ColorGeometry4f>(image_op, 0));
|
||||
params.set_output("Alpha", Field<float>(image_op, 1));
|
||||
params.set_output("Color", std::move(color));
|
||||
params.set_output("Alpha", std::move(alpha));
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
|
||||
@@ -124,14 +124,15 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
return;
|
||||
}
|
||||
|
||||
auto fn_ptr = std::make_shared<SampleIndexFunction>(std::move(list));
|
||||
const mf::MultiFunction &fn = *fn_ptr;
|
||||
|
||||
bke::SocketValueVariant output_value;
|
||||
std::string error_message;
|
||||
const bool success = execute_multi_function_on_value_variant(
|
||||
fn, std::move(fn_ptr), {&index}, {&output_value}, params.user_data(), error_message);
|
||||
if (!success) {
|
||||
bke::SocketValueVariant output_value;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<SampleIndexFunction>(std::move(list)),
|
||||
{&index},
|
||||
{&output_value},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
|
||||
@@ -270,18 +270,32 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
}
|
||||
|
||||
const NodeGeometryProximity &storage = node_storage(params.node());
|
||||
const auto target_type = GeometryNodeProximityTargetType(storage.target_element);
|
||||
|
||||
Field<int> group_id_field = params.extract_input<Field<int>>("Group ID");
|
||||
Field<float3> position_field = params.extract_input<Field<float3>>("Source Position");
|
||||
Field<int> sample_id_field = params.extract_input<Field<int>>("Sample Group ID");
|
||||
auto sample_position = params.extract_input<bke::SocketValueVariant>("Source Position");
|
||||
auto sample_group_id = params.extract_input<bke::SocketValueVariant>("Sample Group ID");
|
||||
|
||||
auto proximity_fn = std::make_unique<ProximityFunction>(
|
||||
std::move(target), GeometryNodeProximityTargetType(storage.target_element), group_id_field);
|
||||
auto proximity_op = FieldOperation::from(
|
||||
std::move(proximity_fn), {std::move(position_field), std::move(sample_id_field)});
|
||||
std::string error_message;
|
||||
bke::SocketValueVariant position;
|
||||
bke::SocketValueVariant distance;
|
||||
bke::SocketValueVariant is_valid;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<ProximityFunction>(
|
||||
std::move(target), target_type, std::move(group_id_field)),
|
||||
{&sample_position, &sample_group_id},
|
||||
{&position, &distance, &is_valid},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Position", Field<float3>(proximity_op, 0));
|
||||
params.set_output("Distance", Field<float>(proximity_op, 1));
|
||||
params.set_output("Is Valid", Field<bool>(proximity_op, 2));
|
||||
params.set_output("Position", std::move(position));
|
||||
params.set_output("Distance", std::move(distance));
|
||||
params.set_output("Is Valid", std::move(is_valid));
|
||||
}
|
||||
|
||||
static void node_rna(StructRNA *srna)
|
||||
|
||||
@@ -244,48 +244,105 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
return;
|
||||
}
|
||||
|
||||
static auto normalize_fn = mf::build::SI1_SO<float3, float3>(
|
||||
"Normalize",
|
||||
[](const float3 &v) { return math::normalize(v); },
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
auto direction_op = FieldOperation::from(normalize_fn,
|
||||
{params.extract_input<Field<float3>>("Ray Direction")});
|
||||
std::string error_message;
|
||||
|
||||
auto op = FieldOperation::from(std::make_unique<RaycastFunction>(target),
|
||||
{params.extract_input<Field<float3>>("Source Position"),
|
||||
Field<float3>(direction_op),
|
||||
params.extract_input<Field<float>>("Ray Length")});
|
||||
bke::SocketValueVariant normalized_direction;
|
||||
{
|
||||
auto ray_direction = params.extract_input<bke::SocketValueVariant>("Ray Direction");
|
||||
|
||||
Field<float3> hit_position(op, 1);
|
||||
params.set_output("Is Hit", Field<bool>(op, 0));
|
||||
static auto normalize_fn = mf::build::SI1_SO<float3, float3>(
|
||||
"Normalize",
|
||||
[](const float3 &v) { return math::normalize(v); },
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
|
||||
if (!execute_multi_function_on_value_variant(normalize_fn,
|
||||
{&ray_direction},
|
||||
{&normalized_direction},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto position = params.extract_input<bke::SocketValueVariant>("Source Position");
|
||||
auto ray_length = params.extract_input<bke::SocketValueVariant>("Ray Length");
|
||||
|
||||
bke::SocketValueVariant is_hit;
|
||||
bke::SocketValueVariant hit_position;
|
||||
bke::SocketValueVariant hit_normal;
|
||||
bke::SocketValueVariant hit_distance;
|
||||
bke::SocketValueVariant triangle_index;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_unique<RaycastFunction>(target),
|
||||
{&position, &normalized_direction, &ray_length},
|
||||
{&is_hit, &hit_position, &hit_normal, &hit_distance, &triangle_index},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Is Hit", std::move(is_hit));
|
||||
params.set_output("Hit Position", hit_position);
|
||||
params.set_output("Hit Normal", Field<float3>(op, 2));
|
||||
params.set_output("Hit Distance", Field<float>(op, 3));
|
||||
params.set_output("Hit Normal", std::move(hit_normal));
|
||||
params.set_output("Hit Distance", std::move(hit_distance));
|
||||
|
||||
if (!params.output_is_required("Attribute")) {
|
||||
return;
|
||||
}
|
||||
|
||||
GField field = params.extract_input<GField>("Attribute");
|
||||
Field<int> triangle_index(op, 4);
|
||||
Field<float3> bary_weights;
|
||||
bke::SocketValueVariant bary_weights;
|
||||
bke::SocketValueVariant triangle_index_copy = triangle_index;
|
||||
switch (mapping) {
|
||||
case GEO_NODE_RAYCAST_INTERPOLATED:
|
||||
bary_weights = Field<float3>(FieldOperation::from(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightFromPositionFn>(target),
|
||||
{hit_position, triangle_index}));
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightFromPositionFn>(target),
|
||||
{&hit_position, &triangle_index_copy},
|
||||
{&bary_weights},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GEO_NODE_RAYCAST_NEAREST:
|
||||
bary_weights = Field<float3>(FieldOperation::from(
|
||||
std::make_shared<bke::mesh_surface_sample::CornerBaryWeightFromPositionFn>(target),
|
||||
{hit_position, triangle_index}));
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<bke::mesh_surface_sample::CornerBaryWeightFromPositionFn>(target),
|
||||
{&hit_position, &triangle_index_copy},
|
||||
{&bary_weights},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
auto sample_op = FieldOperation::from(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightSampleFn>(std::move(target),
|
||||
std::move(field)),
|
||||
{triangle_index, bary_weights});
|
||||
params.set_output("Attribute", GField(sample_op));
|
||||
|
||||
bke::SocketValueVariant sampled_atribute;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightSampleFn>(std::move(target),
|
||||
std::move(field)),
|
||||
{&triangle_index, &bary_weights},
|
||||
{&sampled_atribute},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Attribute", std::move(sampled_atribute));
|
||||
}
|
||||
|
||||
static void node_rna(StructRNA *srna)
|
||||
|
||||
@@ -227,24 +227,30 @@ class SampleGridFunction : public mf::MultiFunction {
|
||||
static void node_geo_exec(GeoNodeExecParams params)
|
||||
{
|
||||
#ifdef WITH_OPENVDB
|
||||
const bNode &node = params.node();
|
||||
const eNodeSocketDatatype data_type = eNodeSocketDatatype(node.custom1);
|
||||
const auto interpolation = params.get_input<InterpolationMode>("Interpolation");
|
||||
|
||||
bke::GVolumeGrid grid = params.extract_input<bke::GVolumeGrid>("Grid");
|
||||
if (!grid) {
|
||||
params.set_default_remaining_outputs();
|
||||
return;
|
||||
}
|
||||
|
||||
auto fn = std::make_shared<SampleGridFunction>(std::move(grid), interpolation);
|
||||
auto op = FieldOperation::from(std::move(fn), {params.extract_input<Field<float3>>("Position")});
|
||||
const auto interpolation = params.get_input<InterpolationMode>("Interpolation");
|
||||
bke::SocketValueVariant position = params.extract_input<bke::SocketValueVariant>("Position");
|
||||
|
||||
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
|
||||
const CPPType &output_type = *bke::socket_type_to_geo_nodes_base_cpp_type(data_type);
|
||||
const GField output_field = conversions.try_convert(fn::GField(std::move(op)), output_type);
|
||||
params.set_output("Value", std::move(output_field));
|
||||
std::string error_message;
|
||||
bke::SocketValueVariant output_value;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<SampleGridFunction>(std::move(grid), interpolation),
|
||||
{&position},
|
||||
{&output_value},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Value", std::move(output_value));
|
||||
#else
|
||||
node_geo_exec_with_missing_openvdb(params);
|
||||
#endif
|
||||
|
||||
@@ -194,26 +194,31 @@ class SampleGridIndexFunction : public mf::MultiFunction {
|
||||
static void node_geo_exec(GeoNodeExecParams params)
|
||||
{
|
||||
#ifdef WITH_OPENVDB
|
||||
const bNode &node = params.node();
|
||||
const eNodeSocketDatatype data_type = eNodeSocketDatatype(node.custom1);
|
||||
|
||||
bke::GVolumeGrid grid = params.extract_input<bke::GVolumeGrid>("Grid");
|
||||
if (!grid) {
|
||||
params.set_default_remaining_outputs();
|
||||
return;
|
||||
}
|
||||
|
||||
auto fn = std::make_shared<SampleGridIndexFunction>(std::move(grid));
|
||||
auto op = FieldOperation::from(std::move(fn),
|
||||
{params.extract_input<Field<int>>("X"),
|
||||
params.extract_input<Field<int>>("Y"),
|
||||
params.extract_input<Field<int>>("Z")});
|
||||
auto x = params.extract_input<bke::SocketValueVariant>("X");
|
||||
auto y = params.extract_input<bke::SocketValueVariant>("Y");
|
||||
auto z = params.extract_input<bke::SocketValueVariant>("Z");
|
||||
|
||||
const bke::DataTypeConversions &conversions = bke::get_implicit_type_conversions();
|
||||
const CPPType &output_type = *bke::socket_type_to_geo_nodes_base_cpp_type(data_type);
|
||||
const GField output_field = conversions.try_convert(fn::GField(std::move(op)), output_type);
|
||||
params.set_output("Value", std::move(output_field));
|
||||
std::string error_message;
|
||||
bke::SocketValueVariant output_value;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<SampleGridIndexFunction>(std::move(grid)),
|
||||
{&x, &y, &z},
|
||||
{&output_value},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Value", std::move(output_value));
|
||||
#else
|
||||
node_geo_exec_with_missing_openvdb(params);
|
||||
#endif
|
||||
|
||||
@@ -206,14 +206,12 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
SocketValueVariant index_value_variant = params.extract_input<SocketValueVariant>("Index");
|
||||
const CPPType &cpp_type = value_field.cpp_type();
|
||||
|
||||
if (index_value_variant.is_context_dependent_field()) {
|
||||
/* If the index is a field, the output has to be a field that still depends on the input. */
|
||||
auto fn = std::make_shared<SampleIndexFunction>(
|
||||
std::move(geometry), std::move(value_field), domain, use_clamp);
|
||||
auto op = FieldOperation::from(std::move(fn), {index_value_variant.extract<Field<int>>()});
|
||||
params.set_output("Value", GField(std::move(op)));
|
||||
}
|
||||
else if (const GeometryComponent *component = find_source_component(geometry, domain)) {
|
||||
if (index_value_variant.is_single()) {
|
||||
const GeometryComponent *component = find_source_component(geometry, domain);
|
||||
if (!component) {
|
||||
params.set_default_remaining_outputs();
|
||||
return;
|
||||
}
|
||||
/* Optimization for the case when the index is a single value. Here only that one index has to
|
||||
* be evaluated. */
|
||||
const int domain_size = component->attribute_domain_size(domain);
|
||||
@@ -236,11 +234,25 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
else {
|
||||
params.set_output("Value", fn::make_constant_field(cpp_type, cpp_type.default_value()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* Output default value if there is no geometry. */
|
||||
params.set_output("Value", fn::make_constant_field(cpp_type, cpp_type.default_value()));
|
||||
|
||||
bke::SocketValueVariant output_value;
|
||||
std::string error_message;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<SampleIndexFunction>(
|
||||
std::move(geometry), std::move(value_field), domain, use_clamp),
|
||||
{&index_value_variant},
|
||||
{&output_value},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Value", std::move(output_value));
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
|
||||
@@ -311,10 +311,23 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
return;
|
||||
}
|
||||
|
||||
Field<float3> positions = params.extract_input<Field<float3>>("Sample Position");
|
||||
auto fn = std::make_shared<SampleNearestFunction>(std::move(geometry), domain);
|
||||
auto op = FieldOperation::from(std::move(fn), {std::move(positions)});
|
||||
params.set_output<Field<int>>("Index", Field<int>(std::move(op)));
|
||||
auto sample_position = params.extract_input<bke::SocketValueVariant>("Sample Position");
|
||||
|
||||
std::string error_message;
|
||||
bke::SocketValueVariant index;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<SampleNearestFunction>(std::move(geometry), domain),
|
||||
{&sample_position},
|
||||
{&index},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Index", std::move(index));
|
||||
}
|
||||
|
||||
static void node_rna(StructRNA *srna)
|
||||
|
||||
@@ -203,26 +203,58 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
return;
|
||||
}
|
||||
|
||||
auto nearest_op = FieldOperation::from(
|
||||
std::make_shared<SampleNearestSurfaceFunction>(geometry,
|
||||
params.extract_input<Field<int>>("Group ID")),
|
||||
{params.extract_input<Field<float3>>("Sample Position"),
|
||||
params.extract_input<Field<int>>("Sample Group ID")});
|
||||
Field<int> triangle_indices(nearest_op, 0);
|
||||
Field<float3> nearest_positions(nearest_op, 1);
|
||||
Field<bool> is_valid(nearest_op, 2);
|
||||
GField value = params.extract_input<GField>("Value");
|
||||
Field<int> group_id_field = params.extract_input<Field<int>>("Group ID");
|
||||
auto sample_position = params.extract_input<bke::SocketValueVariant>("Sample Position");
|
||||
auto sample_group_id = params.extract_input<bke::SocketValueVariant>("Sample Group ID");
|
||||
|
||||
Field<float3> bary_weights = Field<float3>(FieldOperation::from(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightFromPositionFn>(geometry),
|
||||
{nearest_positions, triangle_indices}));
|
||||
std::string error_message;
|
||||
|
||||
GField field = params.extract_input<GField>("Value");
|
||||
auto sample_op = FieldOperation::from(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightSampleFn>(geometry, std::move(field)),
|
||||
{triangle_indices, bary_weights});
|
||||
bke::SocketValueVariant triangle_index;
|
||||
bke::SocketValueVariant nearest_positions;
|
||||
bke::SocketValueVariant is_valid;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<SampleNearestSurfaceFunction>(geometry, group_id_field),
|
||||
{&sample_position, &sample_group_id},
|
||||
{&triangle_index, &nearest_positions, &is_valid},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Value", GField(sample_op));
|
||||
params.set_output("Is Valid", is_valid);
|
||||
bke::SocketValueVariant bary_weights;
|
||||
bke::SocketValueVariant triangle_index_copy = triangle_index;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightFromPositionFn>(geometry),
|
||||
{&nearest_positions, &triangle_index_copy},
|
||||
{&bary_weights},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
bke::SocketValueVariant sample_value;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
std::make_shared<bke::mesh_surface_sample::BaryWeightSampleFn>(geometry,
|
||||
std::move(value)),
|
||||
{&triangle_index, &bary_weights},
|
||||
{&sample_value},
|
||||
params.user_data(),
|
||||
error_message))
|
||||
{
|
||||
params.set_default_remaining_outputs();
|
||||
params.error_message_add(NodeWarningType::Error, std::move(error_message));
|
||||
return;
|
||||
}
|
||||
|
||||
params.set_output("Value", std::move(sample_value));
|
||||
params.set_output("Is Valid", std::move(is_valid));
|
||||
}
|
||||
|
||||
static void node_rna(StructRNA *srna)
|
||||
|
||||
@@ -166,8 +166,19 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
const CPPType &float2_type = CPPType::get<float2>();
|
||||
Field<float2> source_uv_map = conversions.try_convert(
|
||||
params.extract_input<Field<float3>>("Source UV Map"), float2_type);
|
||||
Field<float2> sample_uvs = conversions.try_convert(
|
||||
params.extract_input<Field<float3>>("Sample UV"), float2_type);
|
||||
|
||||
auto sample_uv_value = params.extract_input<bke::SocketValueVariant>("Sample UV");
|
||||
if (sample_uv_value.is_list()) {
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
"Lists are not supported for \"Sample UV\" input");
|
||||
}
|
||||
if (sample_uv_value.is_volume_grid()) {
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
"Volume grids are not supported for \"Sample UV\" input");
|
||||
}
|
||||
Field<float2> sample_uvs = conversions.try_convert(sample_uv_value.extract<Field<float3>>(),
|
||||
float2_type);
|
||||
|
||||
auto uv_op = FieldOperation::from(
|
||||
std::make_shared<ReverseUVSampleFunction>(geometry, std::move(source_uv_map)),
|
||||
{std::move(sample_uvs)});
|
||||
|
||||
@@ -557,7 +557,7 @@ std::optional<SocketValueVariant> implicitly_convert_socket_value(
|
||||
SocketValueVariant output_variant;
|
||||
std::string error_message;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
multi_fn, {}, {&input_variant}, {&output_variant}, nullptr, error_message))
|
||||
multi_fn, {&input_variant}, {&output_variant}, nullptr, error_message))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -588,7 +588,7 @@ class LazyFunctionForImplicitConversion : public LazyFunction {
|
||||
BLI_assert(to_value != nullptr);
|
||||
std::string error_message;
|
||||
if (!execute_multi_function_on_value_variant(
|
||||
fn_, {}, {from_value}, {to_value}, nullptr, error_message))
|
||||
fn_, {from_value}, {to_value}, nullptr, error_message))
|
||||
{
|
||||
std::destroy_at(to_value);
|
||||
construct_socket_default_value(dst_type_, to_value);
|
||||
|
||||
Reference in New Issue
Block a user