Blender  V3.3
node_geo_input_mesh_face_is_planar.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "DNA_mesh_types.h"
4 #include "DNA_meshdata_types.h"
5 
6 #include "BKE_mesh.h"
7 
8 #include "node_geometry_util.hh"
9 
11 
13 {
14  b.add_input<decl::Float>("Threshold")
15  .field_source()
16  .default_value(0.01f)
17  .subtype(PROP_DISTANCE)
18  .supports_field()
19  .description(N_("The distance a point can be from the surface before the face is no longer "
20  "considered planar"))
21  .min(0.0f);
22  b.add_output<decl::Bool>("Planar").field_source();
23 }
24 
26  private:
27  Field<float> threshold_;
28 
29  public:
31  : GeometryFieldInput(CPPType::get<bool>(), "Planar"), threshold_(threshold)
32  {
34  }
35 
37  const eAttrDomain domain,
38  [[maybe_unused]] IndexMask mask) const final
39  {
40  if (component.type() != GEO_COMPONENT_TYPE_MESH) {
41  return {};
42  }
43 
44  const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
45  const Mesh *mesh = mesh_component.get_for_read();
46  if (mesh == nullptr) {
47  return {};
48  }
49 
52  evaluator.add(threshold_);
53  evaluator.evaluate();
54  const VArray<float> thresholds = evaluator.get_evaluated<float>(0);
55 
57 
58  auto planar_fn = [mesh, thresholds, poly_normals](const int i_poly) -> bool {
59  if (mesh->mpoly[i_poly].totloop <= 3) {
60  return true;
61  }
62  const int loopstart = mesh->mpoly[i_poly].loopstart;
63  const int loops = mesh->mpoly[i_poly].totloop;
64  Span<MLoop> poly_loops(&mesh->mloop[loopstart], loops);
65  float3 reference_normal = poly_normals[i_poly];
66 
67  float min = FLT_MAX;
68  float max = -FLT_MAX;
69 
70  for (const int i_loop : poly_loops.index_range()) {
71  const float3 vert = mesh->mvert[poly_loops[i_loop].v].co;
72  float dot = math::dot(reference_normal, vert);
73  if (dot > max) {
74  max = dot;
75  }
76  if (dot < min) {
77  min = dot;
78  }
79  }
80  return max - min < thresholds[i_poly] / 2.0f;
81  };
82 
83  return component.attributes()->adapt_domain<bool>(
84  VArray<bool>::ForFunc(mesh->totpoly, planar_fn), ATTR_DOMAIN_FACE, domain);
85  }
86 
87  uint64_t hash() const override
88  {
89  /* Some random constant hash. */
90  return 2356235652;
91  }
92 
93  bool is_equal_to(const fn::FieldNode &other) const override
94  {
95  return dynamic_cast<const PlanarFieldInput *>(&other) != nullptr;
96  }
97 };
98 
100 {
101  Field<float> threshold = params.extract_input<Field<float>>("Threshold");
102  Field<bool> planar_field{std::make_shared<PlanarFieldInput>(threshold)};
103  params.set_output("Planar", std::move(planar_field));
104 }
105 
106 } // namespace blender::nodes::node_geo_input_mesh_face_is_planar_cc
107 
109 {
111 
112  static bNodeType ntype;
113 
115  &ntype, GEO_NODE_INPUT_MESH_FACE_IS_PLANAR, "Face is Planar", NODE_CLASS_INPUT);
118  nodeRegisterType(&ntype);
119 }
eAttrDomain
Definition: BKE_attribute.h:25
@ ATTR_DOMAIN_FACE
Definition: BKE_attribute.h:29
@ GEO_COMPONENT_TYPE_MESH
const float(* BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]
#define GEO_NODE_INPUT_MESH_FACE_IS_PLANAR
Definition: BKE_node.h:1496
#define NODE_CLASS_INPUT
Definition: BKE_node.h:345
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define final(a, b, c)
Definition: BLI_hash.h:21
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:108
@ PROP_DISTANCE
Definition: RNA_types.h:149
const Mesh * get_for_read() const
constexpr IndexRange index_range() const
Definition: BLI_span.hh:401
static VArray ForFunc(const int64_t size, GetFunc get_func)
GVArray get_varray_for_context(const GeometryComponent &component, const eAttrDomain domain, [[maybe_unused]] IndexMask mask) const final
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_gpu_kernel_postfix ccl_global float int int int int float threshold
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void register_node_type_geo_input_mesh_face_is_planar()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
#define min(a, b)
Definition: sort.c:35
unsigned __int64 uint64_t
Definition: stdint.h:90
float co[3]
struct MVert * mvert
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
NodeDeclareFunction declare
Definition: BKE_node.h:324
float max
#define N_(msgid)