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:
Jacques Lucke 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:
std::string name_;
public:
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;
}
@ -767,9 +780,9 @@ class AttributeFieldInput : public fn::FieldInput {
return name_;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask mask) 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;
};
class IDAttributeFieldInput : public fn::FieldInput {
class IDAttributeFieldInput : public GeometryFieldInput {
public:
IDAttributeFieldInput() : fn::FieldInput(CPPType::get<int>())
IDAttributeFieldInput() : GeometryFieldInput(CPPType::get<int>())
{
category_ = Category::Generated;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask mask) 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;
};
class AnonymousAttributeFieldInput : public fn::FieldInput {
class AnonymousAttributeFieldInput : public GeometryFieldInput {
private:
/**
* 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,
const CPPType &type,
std::string producer_name)
: fn::FieldInput(type, anonymous_id.debug_name()),
: GeometryFieldInput(type, anonymous_id.debug_name()),
anonymous_id_(std::move(anonymous_id)),
producer_name_(producer_name)
{
@ -823,9 +836,9 @@ class AnonymousAttributeFieldInput : public fn::FieldInput {
return fn::Field<T>{field_input};
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const override;
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask mask) 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 {
GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const
GVArray GeometryFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &UNUSED(scope)) 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 CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type);
if (attribute) {
return attribute;
}
return this->get_varray_for_context(component, domain, mask);
}
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::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,
IndexMask mask,
ResourceScope &scope) const
GVArray IDAttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
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. */
return fn::IndexFieldInput::get_index_varray(mask, scope);
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;
}
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
@ -1507,20 +1506,12 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const
return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr;
}
GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const
GVArray AnonymousAttributeFieldInput::get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask UNUSED(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 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 {};
const CustomDataType data_type = cpp_type_to_custom_data_type(*type_);
return component.attribute_try_get_for_read(anonymous_id_.get(), domain, data_type);
}
std::string AnonymousAttributeFieldInput::socket_inspection_name() const

View File

@ -440,7 +440,7 @@ class IndexFieldInput final : public FieldInput {
public:
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,
IndexMask mask,

View File

@ -531,7 +531,7 @@ IndexFieldInput::IndexFieldInput() : FieldInput(CPPType::get<int>(), "Index")
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; };
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),
IndexMask mask,
ResourceScope &scope) const
ResourceScope &UNUSED(scope)) const
{
/* 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

View File

@ -38,6 +38,7 @@ using bke::AttributeFieldInput;
using bke::AttributeIDRef;
using bke::geometry_set_realize_instances;
using bke::GeometryComponentFieldContext;
using bke::GeometryFieldInput;
using bke::OutputAttribute;
using bke::OutputAttribute_Typed;
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);
}
class EndpointFieldInput final : public fn::FieldInput {
class EndpointFieldInput final : public GeometryFieldInput {
Field<int> start_size_;
Field<int> end_size_;
public:
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),
end_size_(end_size)
{
category_ = Category::Generated;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const final
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask UNUSED(mask)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
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));
if (component.type() != GEO_COMPONENT_TYPE_CURVE || domain != ATTR_DOMAIN_POINT) {
return nullptr;
}
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

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_;
GeometryNodeCurveHandleMode mode_;
public:
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;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &UNUSED(scope)) const final
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask mask) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
if (component.type() != GEO_COMPONENT_TYPE_CURVE) {
return {};
}
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
if (component.type() != GEO_COMPONENT_TYPE_CURVE) {
return {};
}
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
if (curve == nullptr) {
return {};
}
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
const CurveEval *curve = curve_component.get_for_read();
if (curve == nullptr) {
return {};
}
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));
}
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 {};
};
}
uint64_t hash() const override
{

View File

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

View File

@ -61,29 +61,24 @@ static VArray<int> construct_edge_vertices_gvarray(const MeshComponent &componen
return {};
}
class EdgeVerticesFieldInput final : public fn::FieldInput {
class EdgeVerticesFieldInput final : public GeometryFieldInput {
private:
VertexNumber vertex_;
public:
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;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const final
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask UNUSED(mask)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
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);
}
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 {};
}
@ -128,29 +123,24 @@ static VArray<float3> construct_edge_positions_gvarray(const MeshComponent &comp
domain);
}
class EdgePositionFieldInput final : public fn::FieldInput {
class EdgePositionFieldInput final : public GeometryFieldInput {
private:
VertexNumber vertex_;
public:
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;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const final
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask UNUSED(mask)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
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);
}
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 {};
}

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);
}
class FaceAreaFieldInput final : public fn::FieldInput {
class FaceAreaFieldInput final : public GeometryFieldInput {
public:
FaceAreaFieldInput() : fn::FieldInput(CPPType::get<float>(), "Face Area Field")
FaceAreaFieldInput() : GeometryFieldInput(CPPType::get<float>(), "Face Area Field")
{
category_ = Category::Generated;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const final
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask UNUSED(mask)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
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);
}
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 {};
}

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);
}
class FaceNeighborCountFieldInput final : public fn::FieldInput {
class FaceNeighborCountFieldInput final : public GeometryFieldInput {
public:
FaceNeighborCountFieldInput() : fn::FieldInput(CPPType::get<int>(), "Face Neighbor Count Field")
FaceNeighborCountFieldInput()
: GeometryFieldInput(CPPType::get<int>(), "Face Neighbor Count Field")
{
category_ = Category::Generated;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const final
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask UNUSED(mask)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
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);
}
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 {};
}
@ -108,25 +104,20 @@ static VArray<int> construct_vertex_count_gvarray(const MeshComponent &component
domain);
}
class FaceVertexCountFieldInput final : public fn::FieldInput {
class FaceVertexCountFieldInput final : public GeometryFieldInput {
public:
FaceVertexCountFieldInput() : fn::FieldInput(CPPType::get<int>(), "Vertex Count Field")
FaceVertexCountFieldInput() : GeometryFieldInput(CPPType::get<int>(), "Vertex Count Field")
{
category_ = Category::Generated;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask UNUSED(mask),
ResourceScope &UNUSED(scope)) const final
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask UNUSED(mask)) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
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);
}
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 {};
}

View File

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

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,
const Mesh &mesh,
const IndexMask mask,
const AttributeDomain domain,
ResourceScope &UNUSED(scope))
const AttributeDomain domain)
{
Span<MVert> verts{mesh.mvert, mesh.totvert};
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,
const AttributeDomain domain,
ResourceScope &UNUSED(scope))
const AttributeDomain domain)
{
const CurveEval *curve = component.get_for_read();
if (curve == nullptr) {
@ -231,36 +229,29 @@ static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &compo
return nullptr;
}
class NormalFieldInput final : public fn::FieldInput {
class NormalFieldInput final : public GeometryFieldInput {
public:
NormalFieldInput() : fn::FieldInput(CPPType::get<float3>(), "Normal node")
NormalFieldInput() : GeometryFieldInput(CPPType::get<float3>(), "Normal node")
{
category_ = Category::Generated;
}
GVArray get_varray_for_context(const fn::FieldContext &context,
IndexMask mask,
ResourceScope &scope) const final
GVArray get_varray_for_context(const GeometryComponent &component,
const AttributeDomain domain,
IndexMask mask) const final
{
if (const GeometryComponentFieldContext *geometry_context =
dynamic_cast<const GeometryComponentFieldContext *>(&context)) {
const GeometryComponent &component = geometry_context->geometry_component();
const AttributeDomain domain = geometry_context->domain();
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);
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);
}
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 {};
}

View File

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