Geometry Nodes: reduce code duplication with new GeometyrFieldInput

Most of our field inputs are currently specific to geometry. This patch introduces
a new `GeometryFieldInput` that reduces the overhead of adding new geometry
field input.

Differential Revision: https://developer.blender.org/D13489
This commit is contained in:
2021-12-06 19:05:29 +01:00
parent 2814740f5b
commit 2d4c7fa896
16 changed files with 278 additions and 374 deletions

View File

@@ -744,13 +744,26 @@ class GeometryComponentFieldContext : public fn::FieldContext {
} }
}; };
class AttributeFieldInput : public fn::FieldInput { class GeometryFieldInput : public fn::FieldInput {
public:
using fn::FieldInput::FieldInput;
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
virtual GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask mask) const = 0;
};
class AttributeFieldInput : public GeometryFieldInput {
private: private:
std::string name_; std::string name_;
public: public:
AttributeFieldInput(std::string name, const CPPType &type) AttributeFieldInput(std::string name, const CPPType &type)
: fn::FieldInput(type, name), name_(std::move(name)) : GeometryFieldInput(type, name), name_(std::move(name))
{ {
category_ = Category::NamedAttribute; category_ = Category::NamedAttribute;
} }
@@ -767,9 +780,9 @@ class AttributeFieldInput : public fn::FieldInput {
return name_; return name_;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &scope) const override; IndexMask mask) const override;
std::string socket_inspection_name() const override; std::string socket_inspection_name() const override;
@@ -777,16 +790,16 @@ class AttributeFieldInput : public fn::FieldInput {
bool is_equal_to(const fn::FieldNode &other) const override; bool is_equal_to(const fn::FieldNode &other) const override;
}; };
class IDAttributeFieldInput : public fn::FieldInput { class IDAttributeFieldInput : public GeometryFieldInput {
public: public:
IDAttributeFieldInput() : fn::FieldInput(CPPType::get<int>()) IDAttributeFieldInput() : GeometryFieldInput(CPPType::get<int>())
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &scope) const override; IndexMask mask) const override;
std::string socket_inspection_name() const override; std::string socket_inspection_name() const override;
@@ -794,7 +807,7 @@ class IDAttributeFieldInput : public fn::FieldInput {
bool is_equal_to(const fn::FieldNode &other) const override; bool is_equal_to(const fn::FieldNode &other) const override;
}; };
class AnonymousAttributeFieldInput : public fn::FieldInput { class AnonymousAttributeFieldInput : public GeometryFieldInput {
private: private:
/** /**
* A strong reference is required to make sure that the referenced attribute is not removed * A strong reference is required to make sure that the referenced attribute is not removed
@@ -807,7 +820,7 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id, AnonymousAttributeFieldInput(StrongAnonymousAttributeID anonymous_id,
const CPPType &type, const CPPType &type,
std::string producer_name) std::string producer_name)
: fn::FieldInput(type, anonymous_id.debug_name()), : GeometryFieldInput(type, anonymous_id.debug_name()),
anonymous_id_(std::move(anonymous_id)), anonymous_id_(std::move(anonymous_id)),
producer_name_(producer_name) producer_name_(producer_name)
{ {
@@ -823,9 +836,9 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
return fn::Field<T>{field_input}; return fn::Field<T>{field_input};
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &scope) const override; IndexMask mask) const override;
std::string socket_inspection_name() const override; std::string socket_inspection_name() const override;

View File

@@ -1421,23 +1421,27 @@ OutputAttribute GeometryComponent::attribute_try_get_for_output_only(
namespace blender::bke { namespace blender::bke {
GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask), IndexMask mask,
ResourceScope &UNUSED(scope)) const ResourceScope &UNUSED(scope)) const
{ {
if (const GeometryComponentFieldContext *geometry_context = if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component(); const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain(); const AttributeDomain domain = geometry_context->domain();
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_); return this->get_varray_for_context(component, domain, mask);
GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type);
if (attribute) {
return attribute;
}
} }
return {}; return {};
} }
GVArray AttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask UNUSED(mask)) const
{
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
return component.attribute_try_get_for_read(name_, domain, data_type);
}
std::string AttributeFieldInput::socket_inspection_name() const std::string AttributeFieldInput::socket_inspection_name() const
{ {
std::stringstream ss; std::stringstream ss;
@@ -1469,25 +1473,20 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain)
} }
} }
GVArray IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, GVArray IDAttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &scope) const IndexMask mask) const
{ {
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
const StringRef name = get_random_id_attribute_name(domain);
GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
if (attribute) {
BLI_assert(attribute.size() == component.attribute_domain_size(domain));
return attribute;
}
/* Use the index as the fallback if no random ID attribute exists. */ const StringRef name = get_random_id_attribute_name(domain);
return fn::IndexFieldInput::get_index_varray(mask, scope); GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32);
if (attribute) {
BLI_assert(attribute.size() == component.attribute_domain_size(domain));
return attribute;
} }
return {};
/* Use the index as the fallback if no random ID attribute exists. */
return fn::IndexFieldInput::get_index_varray(mask);
} }
std::string IDAttributeFieldInput::socket_inspection_name() const std::string IDAttributeFieldInput::socket_inspection_name() const
@@ -1507,20 +1506,12 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr; return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
} }
GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const IndexMask UNUSED(mask)) const
{ {
if (const GeometryComponentFieldContext *geometry_context = const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { return component.attribute_try_get_for_read(anonymous_id_.get(), domain, data_type);
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
GVArray attribute = component.attribute_try_get_for_read(
anonymous_id_.get(), domain, data_type);
return attribute;
}
return {};
} }
std::string AnonymousAttributeFieldInput::socket_inspection_name() const std::string AnonymousAttributeFieldInput::socket_inspection_name() const

View File

@@ -440,7 +440,7 @@ class IndexFieldInput final : public FieldInput {
public: public:
IndexFieldInput(); IndexFieldInput();
static GVArray get_index_varray(IndexMask mask, ResourceScope &scope); static GVArray get_index_varray(IndexMask mask);
GVArray get_varray_for_context(const FieldContext &context, GVArray get_varray_for_context(const FieldContext &context,
IndexMask mask, IndexMask mask,

View File

@@ -531,7 +531,7 @@ IndexFieldInput::IndexFieldInput() : FieldInput(CPPType::get<int>(), "Index")
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &UNUSED(scope)) GVArray IndexFieldInput::get_index_varray(IndexMask mask)
{ {
auto index_func = [](int i) { return i; }; auto index_func = [](int i) { return i; };
return VArray<int>::ForFunc(mask.min_array_size(), index_func); return VArray<int>::ForFunc(mask.min_array_size(), index_func);
@@ -539,10 +539,10 @@ GVArray IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &UNUSED(
GVArray IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context), GVArray IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context),
IndexMask mask, IndexMask mask,
ResourceScope &scope) const ResourceScope &UNUSED(scope)) const
{ {
/* TODO: Investigate a similar method to IndexRange::as_span() */ /* TODO: Investigate a similar method to IndexRange::as_span() */
return get_index_varray(mask, scope); return get_index_varray(mask);
} }
uint64_t IndexFieldInput::hash() const uint64_t IndexFieldInput::hash() const

View File

@@ -38,6 +38,7 @@ using bke::AttributeFieldInput;
using bke::AttributeIDRef; using bke::AttributeIDRef;
using bke::geometry_set_realize_instances; using bke::geometry_set_realize_instances;
using bke::GeometryComponentFieldContext; using bke::GeometryComponentFieldContext;
using bke::GeometryFieldInput;
using bke::OutputAttribute; using bke::OutputAttribute;
using bke::OutputAttribute_Typed; using bke::OutputAttribute_Typed;
using bke::ReadAttributeLookup; using bke::ReadAttributeLookup;

View File

@@ -51,69 +51,61 @@ static void select_by_spline(const int start, const int end, MutableSpan<bool> r
r_selection.slice(size - end_use, end_use).fill(true); r_selection.slice(size - end_use, end_use).fill(true);
} }
class EndpointFieldInput final : public fn::FieldInput { class EndpointFieldInput final : public GeometryFieldInput {
Field<int> start_size_; Field<int> start_size_;
Field<int> end_size_; Field<int> end_size_;
public: public:
EndpointFieldInput(Field<int> start_size, Field<int> end_size) EndpointFieldInput(Field<int> start_size, Field<int> end_size)
: FieldInput(CPPType::get<bool>(), "Endpoint Selection node"), : GeometryFieldInput(CPPType::get<bool>(), "Endpoint Selection node"),
start_size_(start_size), start_size_(start_size),
end_size_(end_size) end_size_(end_size)
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() != GEO_COMPONENT_TYPE_CURVE || domain != ATTR_DOMAIN_POINT) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { return nullptr;
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() != GEO_COMPONENT_TYPE_CURVE || domain != ATTR_DOMAIN_POINT) {
return nullptr;
}
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
Array<int> control_point_offsets = curve->control_point_offsets();
if (curve == nullptr || control_point_offsets.last() == 0) {
return nullptr;
}
GeometryComponentFieldContext size_context{curve_component, ATTR_DOMAIN_CURVE};
fn::FieldEvaluator evaluator{size_context, curve->splines().size()};
evaluator.add(start_size_);
evaluator.add(end_size_);
evaluator.evaluate();
const VArray<int> &start_size = evaluator.get_evaluated<int>(0);
const VArray<int> &end_size = evaluator.get_evaluated<int>(1);
const int point_size = control_point_offsets.last();
Array<bool> selection(point_size, false);
int current_point = 0;
MutableSpan<bool> selection_span = selection.as_mutable_span();
for (int i : IndexRange(curve->splines().size())) {
const SplinePtr &spline = curve->splines()[i];
if (start_size[i] <= 0 && end_size[i] <= 0) {
selection_span.slice(current_point, spline->size()).fill(false);
}
else {
int start_use = std::max(start_size[i], 0);
int end_use = std::max(end_size[i], 0);
select_by_spline(
start_use, end_use, selection_span.slice(current_point, spline->size()));
}
current_point += spline->size();
}
return VArray<bool>::ForContainer(std::move(selection));
} }
return {};
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
Array<int> control_point_offsets = curve->control_point_offsets();
if (curve == nullptr || control_point_offsets.last() == 0) {
return nullptr;
}
GeometryComponentFieldContext size_context{curve_component, ATTR_DOMAIN_CURVE};
fn::FieldEvaluator evaluator{size_context, curve->splines().size()};
evaluator.add(start_size_);
evaluator.add(end_size_);
evaluator.evaluate();
const VArray<int> &start_size = evaluator.get_evaluated<int>(0);
const VArray<int> &end_size = evaluator.get_evaluated<int>(1);
const int point_size = control_point_offsets.last();
Array<bool> selection(point_size, false);
int current_point = 0;
MutableSpan<bool> selection_span = selection.as_mutable_span();
for (int i : IndexRange(curve->splines().size())) {
const SplinePtr &spline = curve->splines()[i];
if (start_size[i] <= 0 && end_size[i] <= 0) {
selection_span.slice(current_point, spline->size()).fill(false);
}
else {
int start_use = std::max(start_size[i], 0);
int end_use = std::max(end_size[i], 0);
select_by_spline(start_use, end_use, selection_span.slice(current_point, spline->size()));
}
current_point += spline->size();
}
return VArray<bool>::ForContainer(std::move(selection));
}; };
uint64_t hash() const override uint64_t hash() const override

View File

@@ -83,44 +83,40 @@ static void select_by_handle_type(const CurveEval &curve,
} }
} }
class HandleTypeFieldInput final : public fn::FieldInput { class HandleTypeFieldInput final : public GeometryFieldInput {
BezierSpline::HandleType type_; BezierSpline::HandleType type_;
GeometryNodeCurveHandleMode mode_; GeometryNodeCurveHandleMode mode_;
public: public:
HandleTypeFieldInput(BezierSpline::HandleType type, GeometryNodeCurveHandleMode mode) HandleTypeFieldInput(BezierSpline::HandleType type, GeometryNodeCurveHandleMode mode)
: FieldInput(CPPType::get<bool>(), "Handle Type Selection node"), type_(type), mode_(mode) : GeometryFieldInput(CPPType::get<bool>(), "Handle Type Selection node"),
type_(type),
mode_(mode)
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask mask) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() != GEO_COMPONENT_TYPE_CURVE) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { return {};
}
const GeometryComponent &component = geometry_context->geometry_component(); const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const AttributeDomain domain = geometry_context->domain(); const CurveEval *curve = curve_component.get_for_read();
if (component.type() != GEO_COMPONENT_TYPE_CURVE) { if (curve == nullptr) {
return {}; return {};
} }
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); if (domain == ATTR_DOMAIN_POINT) {
const CurveEval *curve = curve_component.get_for_read(); Array<bool> selection(mask.min_array_size());
if (curve == nullptr) { select_by_handle_type(*curve, type_, mode_, selection);
return {}; return VArray<bool>::ForContainer(std::move(selection));
}
if (domain == ATTR_DOMAIN_POINT) {
Array<bool> selection(mask.min_array_size());
select_by_handle_type(*curve, type_, mode_, selection);
return VArray<bool>::ForContainer(std::move(selection));
}
} }
return {}; return {};
}; }
uint64_t hash() const override uint64_t hash() const override
{ {

View File

@@ -202,29 +202,22 @@ static VArray<int> construct_index_on_spline_varray(const CurveEval &curve,
return {}; return {};
} }
class CurveParameterFieldInput final : public fn::FieldInput { class CurveParameterFieldInput final : public GeometryFieldInput {
public: public:
CurveParameterFieldInput() : fn::FieldInput(CPPType::get<float>(), "Curve Parameter node") CurveParameterFieldInput() : GeometryFieldInput(CPPType::get<float>(), "Curve Parameter node")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask mask) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
const GeometryComponent &component = geometry_context->geometry_component(); if (curve) {
const AttributeDomain domain = geometry_context->domain(); return construct_curve_parameter_varray(*curve, mask, domain);
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
if (curve) {
return construct_curve_parameter_varray(*curve, mask, domain);
}
} }
} }
return {}; return {};
@@ -242,28 +235,22 @@ class CurveParameterFieldInput final : public fn::FieldInput {
} }
}; };
class CurveLengthFieldInput final : public fn::FieldInput { class CurveLengthFieldInput final : public GeometryFieldInput {
public: public:
CurveLengthFieldInput() : fn::FieldInput(CPPType::get<float>(), "Curve Length node") CurveLengthFieldInput() : GeometryFieldInput(CPPType::get<float>(), "Curve Length node")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask mask) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
const GeometryComponent &component = geometry_context->geometry_component(); if (curve) {
const AttributeDomain domain = geometry_context->domain(); return construct_curve_length_varray(*curve, mask, domain);
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
if (curve) {
return construct_curve_length_varray(*curve, mask, domain);
}
} }
} }
return {}; return {};
@@ -281,28 +268,22 @@ class CurveLengthFieldInput final : public fn::FieldInput {
} }
}; };
class IndexOnSplineFieldInput final : public fn::FieldInput { class IndexOnSplineFieldInput final : public GeometryFieldInput {
public: public:
IndexOnSplineFieldInput() : fn::FieldInput(CPPType::get<int>(), "Spline Index") IndexOnSplineFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Spline Index")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask mask) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
const GeometryComponent &component = geometry_context->geometry_component(); if (curve) {
const AttributeDomain domain = geometry_context->domain(); return construct_index_on_spline_varray(*curve, mask, domain);
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
if (curve) {
return construct_index_on_spline_varray(*curve, mask, domain);
}
} }
} }
return {}; return {};

View File

@@ -61,29 +61,24 @@ static VArray<int> construct_edge_vertices_gvarray(const MeshComponent &componen
return {}; return {};
} }
class EdgeVerticesFieldInput final : public fn::FieldInput { class EdgeVerticesFieldInput final : public GeometryFieldInput {
private: private:
VertexNumber vertex_; VertexNumber vertex_;
public: public:
EdgeVerticesFieldInput(VertexNumber vertex) EdgeVerticesFieldInput(VertexNumber vertex)
: fn::FieldInput(CPPType::get<int>(), "Edge Vertices Field"), vertex_(vertex) : GeometryFieldInput(CPPType::get<int>(), "Edge Vertices Field"), vertex_(vertex)
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const GeometryComponent &component = geometry_context->geometry_component(); return construct_edge_vertices_gvarray(mesh_component, vertex_, domain);
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_MESH) {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
return construct_edge_vertices_gvarray(mesh_component, vertex_, domain);
}
} }
return {}; return {};
} }
@@ -128,29 +123,24 @@ static VArray<float3> construct_edge_positions_gvarray(const MeshComponent &comp
domain); domain);
} }
class EdgePositionFieldInput final : public fn::FieldInput { class EdgePositionFieldInput final : public GeometryFieldInput {
private: private:
VertexNumber vertex_; VertexNumber vertex_;
public: public:
EdgePositionFieldInput(VertexNumber vertex) EdgePositionFieldInput(VertexNumber vertex)
: fn::FieldInput(CPPType::get<float3>(), "Edge Position Field"), vertex_(vertex) : GeometryFieldInput(CPPType::get<float3>(), "Edge Position Field"), vertex_(vertex)
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const GeometryComponent &component = geometry_context->geometry_component(); return construct_edge_positions_gvarray(mesh_component, vertex_, domain);
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_MESH) {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
return construct_edge_positions_gvarray(mesh_component, vertex_, domain);
}
} }
return {}; return {};
} }

View File

@@ -47,25 +47,20 @@ static VArray<float> construct_face_area_gvarray(const MeshComponent &component,
VArray<float>::ForFunc(mesh->totpoly, area_fn), ATTR_DOMAIN_FACE, domain); VArray<float>::ForFunc(mesh->totpoly, area_fn), ATTR_DOMAIN_FACE, domain);
} }
class FaceAreaFieldInput final : public fn::FieldInput { class FaceAreaFieldInput final : public GeometryFieldInput {
public: public:
FaceAreaFieldInput() : fn::FieldInput(CPPType::get<float>(), "Face Area Field") FaceAreaFieldInput() : GeometryFieldInput(CPPType::get<float>(), "Face Area Field")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const GeometryComponent &component = geometry_context->geometry_component(); return construct_face_area_gvarray(mesh_component, domain);
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_MESH) {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
return construct_face_area_gvarray(mesh_component, domain);
}
} }
return {}; return {};
} }

View File

@@ -58,25 +58,21 @@ static VArray<int> construct_neighbor_count_gvarray(const MeshComponent &compone
VArray<int>::ForContainer(std::move(poly_count)), ATTR_DOMAIN_FACE, domain); VArray<int>::ForContainer(std::move(poly_count)), ATTR_DOMAIN_FACE, domain);
} }
class FaceNeighborCountFieldInput final : public fn::FieldInput { class FaceNeighborCountFieldInput final : public GeometryFieldInput {
public: public:
FaceNeighborCountFieldInput() : fn::FieldInput(CPPType::get<int>(), "Face Neighbor Count Field") FaceNeighborCountFieldInput()
: GeometryFieldInput(CPPType::get<int>(), "Face Neighbor Count Field")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const GeometryComponent &component = geometry_context->geometry_component(); return construct_neighbor_count_gvarray(mesh_component, domain);
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_MESH) {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
return construct_neighbor_count_gvarray(mesh_component, domain);
}
} }
return {}; return {};
} }
@@ -108,25 +104,20 @@ static VArray<int> construct_vertex_count_gvarray(const MeshComponent &component
domain); domain);
} }
class FaceVertexCountFieldInput final : public fn::FieldInput { class FaceVertexCountFieldInput final : public GeometryFieldInput {
public: public:
FaceVertexCountFieldInput() : fn::FieldInput(CPPType::get<int>(), "Vertex Count Field") FaceVertexCountFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Vertex Count Field")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const GeometryComponent &component = geometry_context->geometry_component(); return construct_vertex_count_gvarray(mesh_component, domain);
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_MESH) {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
return construct_vertex_count_gvarray(mesh_component, domain);
}
} }
return {}; return {};
} }

View File

@@ -52,25 +52,20 @@ static VArray<int> construct_vertex_count_gvarray(const MeshComponent &component
return {}; return {};
} }
class VertexCountFieldInput final : public fn::FieldInput { class VertexCountFieldInput final : public GeometryFieldInput {
public: public:
VertexCountFieldInput() : fn::FieldInput(CPPType::get<int>(), "Vertex Count Field") VertexCountFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Vertex Count Field")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const GeometryComponent &component = geometry_context->geometry_component(); return construct_vertex_count_gvarray(mesh_component, domain);
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_MESH) {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
return construct_vertex_count_gvarray(mesh_component, domain);
}
} }
return {}; return {};
} }
@@ -106,25 +101,20 @@ static VArray<int> construct_face_count_gvarray(const MeshComponent &component,
return {}; return {};
} }
class VertexFaceCountFieldInput final : public fn::FieldInput { class VertexFaceCountFieldInput final : public GeometryFieldInput {
public: public:
VertexFaceCountFieldInput() : fn::FieldInput(CPPType::get<int>(), "Vertex Face Count Field") VertexFaceCountFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Vertex Face Count Field")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const GeometryComponent &component = geometry_context->geometry_component(); return construct_face_count_gvarray(mesh_component, domain);
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_MESH) {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
return construct_face_count_gvarray(mesh_component, domain);
}
} }
return {}; return {};
} }

View File

@@ -93,8 +93,7 @@ static VArray<float3> mesh_vertex_normals(const Mesh &mesh,
static VArray<float3> construct_mesh_normals_gvarray(const MeshComponent &mesh_component, static VArray<float3> construct_mesh_normals_gvarray(const MeshComponent &mesh_component,
const Mesh &mesh, const Mesh &mesh,
const IndexMask mask, const IndexMask mask,
const AttributeDomain domain, const AttributeDomain domain)
ResourceScope &UNUSED(scope))
{ {
Span<MVert> verts{mesh.mvert, mesh.totvert}; Span<MVert> verts{mesh.mvert, mesh.totvert};
Span<MEdge> edges{mesh.medge, mesh.totedge}; Span<MEdge> edges{mesh.medge, mesh.totedge};
@@ -199,8 +198,7 @@ static Array<float3> curve_normal_point_domain(const CurveEval &curve)
} }
static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &component, static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &component,
const AttributeDomain domain, const AttributeDomain domain)
ResourceScope &UNUSED(scope))
{ {
const CurveEval *curve = component.get_for_read(); const CurveEval *curve = component.get_for_read();
if (curve == nullptr) { if (curve == nullptr) {
@@ -231,36 +229,29 @@ static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &compo
return nullptr; return nullptr;
} }
class NormalFieldInput final : public fn::FieldInput { class NormalFieldInput final : public GeometryFieldInput {
public: public:
NormalFieldInput() : fn::FieldInput(CPPType::get<float3>(), "Normal node") NormalFieldInput() : GeometryFieldInput(CPPType::get<float3>(), "Normal node")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &scope) const final IndexMask mask) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
const GeometryComponent &component = geometry_context->geometry_component(); if (mesh == nullptr) {
const AttributeDomain domain = geometry_context->domain(); return {};
if (component.type() == GEO_COMPONENT_TYPE_MESH) {
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
if (mesh == nullptr) {
return {};
}
return construct_mesh_normals_gvarray(mesh_component, *mesh, mask, domain, scope);
}
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_curve_normal_gvarray(curve_component, domain, scope);
} }
return construct_mesh_normals_gvarray(mesh_component, *mesh, mask, domain);
}
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_curve_normal_gvarray(curve_component, domain);
} }
return {}; return {};
} }

View File

@@ -31,8 +31,7 @@ static void node_declare(NodeDeclarationBuilder &b)
*/ */
static VArray<float> construct_spline_length_gvarray(const CurveComponent &component, static VArray<float> construct_spline_length_gvarray(const CurveComponent &component,
const AttributeDomain domain, const AttributeDomain domain)
ResourceScope &UNUSED(scope))
{ {
const CurveEval *curve = component.get_for_read(); const CurveEval *curve = component.get_for_read();
if (curve == nullptr) { if (curve == nullptr) {
@@ -54,26 +53,20 @@ static VArray<float> construct_spline_length_gvarray(const CurveComponent &compo
return {}; return {};
} }
class SplineLengthFieldInput final : public fn::FieldInput { class SplineLengthFieldInput final : public GeometryFieldInput {
public: public:
SplineLengthFieldInput() : fn::FieldInput(CPPType::get<float>(), "Spline Length node") SplineLengthFieldInput() : GeometryFieldInput(CPPType::get<float>(), "Spline Length node")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &scope) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_spline_length_gvarray(curve_component, domain);
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_spline_length_gvarray(curve_component, domain, scope);
}
} }
return {}; return {};
} }
@@ -95,8 +88,7 @@ class SplineLengthFieldInput final : public fn::FieldInput {
*/ */
static VArray<int> construct_spline_count_gvarray(const CurveComponent &component, static VArray<int> construct_spline_count_gvarray(const CurveComponent &component,
const AttributeDomain domain, const AttributeDomain domain)
ResourceScope &UNUSED(scope))
{ {
const CurveEval *curve = component.get_for_read(); const CurveEval *curve = component.get_for_read();
if (curve == nullptr) { if (curve == nullptr) {
@@ -118,26 +110,20 @@ static VArray<int> construct_spline_count_gvarray(const CurveComponent &componen
return {}; return {};
} }
class SplineCountFieldInput final : public fn::FieldInput { class SplineCountFieldInput final : public GeometryFieldInput {
public: public:
SplineCountFieldInput() : fn::FieldInput(CPPType::get<int>(), "Spline Point Count") SplineCountFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Spline Point Count")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &scope) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_spline_count_gvarray(curve_component, domain);
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_spline_count_gvarray(curve_component, domain, scope);
}
} }
return {}; return {};
} }

View File

@@ -85,8 +85,7 @@ static Array<float3> curve_tangent_point_domain(const CurveEval &curve)
} }
static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component, static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component,
const AttributeDomain domain, const AttributeDomain domain)
ResourceScope &UNUSED(scope))
{ {
const CurveEval *curve = component.get_for_read(); const CurveEval *curve = component.get_for_read();
if (curve == nullptr) { if (curve == nullptr) {
@@ -118,27 +117,20 @@ static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &comp
return nullptr; return nullptr;
} }
class TangentFieldInput final : public fn::FieldInput { class TangentFieldInput final : public GeometryFieldInput {
public: public:
TangentFieldInput() : fn::FieldInput(CPPType::get<float3>(), "Tangent node") TangentFieldInput() : GeometryFieldInput(CPPType::get<float3>(), "Tangent node")
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask UNUSED(mask), const AttributeDomain domain,
ResourceScope &scope) const final IndexMask UNUSED(mask)) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_curve_tangent_gvarray(curve_component, domain);
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
return construct_curve_tangent_gvarray(curve_component, domain, scope);
}
} }
return {}; return {};
} }

View File

@@ -54,44 +54,39 @@ static void select_mesh_by_material(const Mesh &mesh,
}); });
} }
class MaterialSelectionFieldInput final : public fn::FieldInput { class MaterialSelectionFieldInput final : public GeometryFieldInput {
Material *material_; Material *material_;
public: public:
MaterialSelectionFieldInput(Material *material) MaterialSelectionFieldInput(Material *material)
: fn::FieldInput(CPPType::get<bool>(), "Material Selection node"), material_(material) : GeometryFieldInput(CPPType::get<bool>(), "Material Selection node"), material_(material)
{ {
category_ = Category::Generated; category_ = Category::Generated;
} }
GVArray get_varray_for_context(const fn::FieldContext &context, GVArray get_varray_for_context(const GeometryComponent &component,
IndexMask mask, const AttributeDomain domain,
ResourceScope &UNUSED(scope)) const final IndexMask mask) const final
{ {
if (const GeometryComponentFieldContext *geometry_context = if (component.type() != GEO_COMPONENT_TYPE_MESH) {
dynamic_cast<const GeometryComponentFieldContext *>(&context)) { return {};
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() != GEO_COMPONENT_TYPE_MESH) {
return {};
}
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
if (mesh == nullptr) {
return {};
}
if (domain == ATTR_DOMAIN_FACE) {
Array<bool> selection(mask.min_array_size());
select_mesh_by_material(*mesh, material_, mask, selection);
return VArray<bool>::ForContainer(std::move(selection));
}
Array<bool> selection(mesh->totpoly);
select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection);
return mesh_component.attribute_try_adapt_domain<bool>(
VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_FACE, domain);
} }
const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
const Mesh *mesh = mesh_component.get_for_read();
if (mesh == nullptr) {
return {};
}
if (domain == ATTR_DOMAIN_FACE) {
Array<bool> selection(mask.min_array_size());
select_mesh_by_material(*mesh, material_, mask, selection);
return VArray<bool>::ForContainer(std::move(selection));
}
Array<bool> selection(mesh->totpoly);
select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection);
return mesh_component.attribute_try_adapt_domain<bool>(
VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_FACE, domain);
return nullptr; return nullptr;
} }