37 b.add_input<
decl::Bool>(
N_(
"Selection")).default_value(
true).hide_value().supports_field();
41 .make_available(enable_poisson);
67 uiItemR(layout,
ptr,
"distribute_method", 0,
"", ICON_NONE);
101 const float base_density,
111 for (
const int looptri_index : looptris.index_range()) {
112 const MLoopTri &looptri = looptris[looptri_index];
113 const int v0_loop = looptri.
tri[0];
114 const int v1_loop = looptri.
tri[1];
115 const int v2_loop = looptri.
tri[2];
123 float looptri_density_factor = 1.0f;
125 const float v0_density_factor =
std::max(0.0f, density_factors[v0_loop]);
126 const float v1_density_factor =
std::max(0.0f, density_factors[v1_loop]);
127 const float v2_density_factor =
std::max(0.0f, density_factors[v2_loop]);
128 looptri_density_factor = (v0_density_factor + v1_density_factor + v2_density_factor) / 3.0f;
136 looptri_density_factor);
138 for (
int i = 0; i < point_amount; i++) {
142 r_positions.
append(point_pos);
143 r_bary_coords.
append(bary_coord);
144 r_looptri_indices.
append(looptri_index);
151 KDTree_3d *kdtree = BLI_kdtree_3d_new(
positions.size());
155 BLI_kdtree_3d_insert(kdtree, i_point, position);
159 BLI_kdtree_3d_balance(kdtree);
166 if (minimum_distance <= 0.0f) {
173 for (
const int i :
positions.index_range()) {
174 if (elimination_mask[i]) {
178 struct CallbackData {
181 } callback_data = {i, elimination_mask};
183 BLI_kdtree_3d_range_search_cb(
188 CallbackData &callback_data = *
static_cast<CallbackData *
>(
user_data);
189 if (index != callback_data.index) {
190 callback_data.elimination_mask[index] =
true;
208 if (elimination_mask[i]) {
212 const MLoopTri &looptri = looptris[looptri_indices[i]];
213 const float3 bary_coord = bary_coords[i];
215 const int v0_loop = looptri.
tri[0];
216 const int v1_loop = looptri.
tri[1];
217 const int v2_loop = looptri.
tri[2];
219 const float v0_density_factor =
std::max(0.0f, density_factors[v0_loop]);
220 const float v1_density_factor =
std::max(0.0f, density_factors[v1_loop]);
221 const float v2_density_factor =
std::max(0.0f, density_factors[v2_loop]);
223 const float probablity = v0_density_factor * bary_coord.x + v1_density_factor * bary_coord.y +
224 v2_density_factor * bary_coord.z;
227 if (
hash > probablity) {
228 elimination_mask[i] =
true;
238 for (
int i =
positions.size() - 1; i >= 0; i--) {
239 if (elimination_mask[i]) {
254 switch (source_domain) {
301 if (!source_attribute) {
308 if (!attribute_out) {
323 struct AttributeOutputs {
333 const AttributeOutputs &attribute_outputs)
343 if (attribute_outputs.normal_id) {
347 if (attribute_outputs.rotation_id) {
357 const int looptri_index = looptri_indices[i];
358 const MLoopTri &looptri = looptris[looptri_index];
359 const float3 &bary_coord = bary_coords[i];
374 if (!
normals.span.is_empty()) {
398 const int domain_size =
component.attribute_domain_size(attribute_domain);
404 evaluator.add_with_destination(density_field, densities.
as_mutable_span());
405 evaluator.evaluate();
418 component, density_field, selection_field);
424 const float minimum_distance,
425 const float max_density,
440 mesh_component, density_factor_field, selection_field);
446 elimination_mask.as_span(),
positions, bary_coords, looptri_indices);
453 const AttributeOutputs &attribute_outputs,
479 const float minimum_distance =
params.get_input<
float>(
"Distance Min");
480 const float density_max =
params.get_input<
float>(
"Density Max");
485 density_factors_field,
507 point_radii.span.fill(0.05f);
509 point_radii.finish();
521 attributes.remove(
"position");
524 mesh_component, attributes, point_component, bary_coords, looptri_indices);
527 mesh_component, point_component, bary_coords, looptri_indices, attribute_outputs);
537 const int seed =
params.get_input<
int>(
"Seed") * 5383843;
540 AttributeOutputs attribute_outputs;
541 if (
params.output_is_required(
"Normal")) {
544 if (
params.output_is_required(
"Rotation")) {
550 geometry_set, selection_field, method,
seed, attribute_outputs,
params);
556 params.set_output(
"Points", std::move(geometry_set));
558 if (attribute_outputs.normal_id) {
561 AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.normal_id),
562 params.attribute_producer_name()));
564 if (attribute_outputs.rotation_id) {
567 AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.rotation_id),
568 params.attribute_producer_name()));
582 "Distribute Points on Faces",
@ GEO_COMPONENT_TYPE_MESH
@ GEO_COMPONENT_TYPE_POINT_CLOUD
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth)
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
#define GEO_NODE_DISTRIBUTE_POINTS_ON_FACES
void nodeSetSocketAvailability(struct bNodeTree *ntree, struct bNodeSocket *sock, bool is_available)
#define NODE_CLASS_GEOMETRY
void nodeRegisterType(struct bNodeType *ntype)
General operations for point clouds.
struct PointCloud * BKE_pointcloud_new_nomain(int totpoint)
A KD-tree for nearest neighbor search.
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
void vec_to_quat(float q[4], const float vec[3], short axis, short upflag)
void quat_to_eul(float eul[3], const float quat[4])
void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
#define BLI_SCOPED_DEFER(function_to_defer)
static uint8 component(Color32 c, uint i)
GeometryNodeDistributePointsOnFacesMode
@ GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_RANDOM
@ GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
static unsigned long seed
virtual std::optional< blender::bke::MutableAttributeAccessor > attributes_for_write()
const Mesh * get_for_read() const
std::optional< blender::bke::AttributeAccessor > attributes() const final
std::optional< blender::bke::MutableAttributeAccessor > attributes_for_write() final
MutableSpan< T > as_mutable_span()
ItemIterator items() const
int round_probabilistic(float x)
float3 get_barycentric_coordinates()
constexpr IndexRange index_range() const
constexpr bool is_empty() const
void remove_and_reorder(const int64_t index)
MutableSpan< T > as_mutable_span()
void append(const T &value)
GAttributeReader lookup(const AttributeIDRef &attribute_id) const
void set_selection(Field< bool > selection)
void make_available(bNode &node) const
IconTextureDrawCall normal
void sample_face_attribute(const Mesh &mesh, Span< int > looptri_indices, const GVArray &data_in, const IndexMask mask, GMutableSpan data_out)
void sample_point_attribute(const Mesh &mesh, Span< int > looptri_indices, Span< float3 > bary_coords, const GVArray &data_in, const IndexMask mask, GMutableSpan data_out)
void sample_corner_attribute(const Mesh &mesh, Span< int > looptri_indices, Span< float3 > bary_coords, const GVArray &data_in, const IndexMask mask, GMutableSpan data_out)
AttributeAccessor pointcloud_attributes(const PointCloud &pointcloud)
MutableAttributeAccessor pointcloud_attributes_for_write(PointCloud &pointcloud)
AttributeAccessor mesh_attributes(const Mesh &mesh)
OwnedAnonymousAttributeID< true > StrongAnonymousAttributeID
static void area(int d1, int d2, int e1, int e2, float weights[2])
static BLI_NOINLINE void update_elimination_mask_for_close_points(Span< float3 > positions, const float minimum_distance, MutableSpan< bool > elimination_mask)
static void node_point_distribute_points_on_faces_update(bNodeTree *ntree, bNode *node)
static BLI_NOINLINE void update_elimination_mask_based_on_density_factors(const Mesh &mesh, const Span< float > density_factors, const Span< float3 > bary_coords, const Span< int > looptri_indices, const MutableSpan< bool > elimination_mask)
static void sample_mesh_surface(const Mesh &mesh, const float base_density, const Span< float > density_factors, const int seed, Vector< float3 > &r_positions, Vector< float3 > &r_bary_coords, Vector< int > &r_looptri_indices)
static BLI_NOINLINE void compute_attribute_outputs(const MeshComponent &mesh_component, PointCloudComponent &point_component, const Span< float3 > bary_coords, const Span< int > looptri_indices, const AttributeOutputs &attribute_outputs)
static BLI_NOINLINE KDTree_3d * build_kdtree(Span< float3 > positions)
static void distribute_points_random(const MeshComponent &component, const Field< float > &density_field, const Field< bool > &selection_field, const int seed, Vector< float3 > &positions, Vector< float3 > &bary_coords, Vector< int > &looptri_indices)
static BLI_NOINLINE void propagate_existing_attributes(const MeshComponent &mesh_component, const Map< AttributeIDRef, AttributeKind > &attributes, GeometryComponent &point_component, const Span< float3 > bary_coords, const Span< int > looptri_indices)
static void node_geo_exec(GeoNodeExecParams params)
static float3 normal_to_euler_rotation(const float3 normal)
static BLI_NOINLINE void eliminate_points_based_on_mask(const Span< bool > elimination_mask, Vector< float3 > &positions, Vector< float3 > &bary_coords, Vector< int > &looptri_indices)
static BLI_NOINLINE void interpolate_attribute(const Mesh &mesh, const Span< float3 > bary_coords, const Span< int > looptri_indices, const eAttrDomain source_domain, const GVArray &source_data, GMutableSpan output_data)
static void node_declare(NodeDeclarationBuilder &b)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static Array< float > calc_full_density_factors_with_selection(const MeshComponent &component, const Field< float > &density_field, const Field< bool > &selection_field)
static void distribute_points_poisson_disk(const MeshComponent &mesh_component, const float minimum_distance, const float max_density, const Field< float > &density_factor_field, const Field< bool > &selection_field, const int seed, Vector< float3 > &positions, Vector< float3 > &bary_coords, Vector< int > &looptri_indices)
static void point_distribution_calculate(GeometrySet &geometry_set, const Field< bool > selection_field, const GeometryNodeDistributePointsOnFacesMode method, const int seed, const AttributeOutputs &attribute_outputs, const GeoNodeExecParams ¶ms)
uint32_t hash_float(float kx)
float hash_float_to_float(float k)
uint32_t hash(uint32_t kx)
vec_base< float, 3 > float3
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
MutableSpan< float3 > positions
Map< AttributeIDRef, GMutableSpan > point_attributes
MutableSpan< float3 > rotations
MutableSpan< float3 > normals
StrongAnonymousAttributeID normal_id
void register_node_type_geo_distribute_points_on_faces()
StrongAnonymousAttributeID rotation_id
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
void keep_only_during_modify(const blender::Span< GeometryComponentType > component_types)
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
void gather_attributes_for_propagation(blender::Span< GeometryComponentType > component_types, GeometryComponentType dst_component_type, bool include_instances, blender::Map< blender::bke::AttributeIDRef, blender::bke::AttributeKind > &r_attributes) const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
void replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
struct bNodeSocket * next
NodeGeometryExecFunction geometry_node_execute
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
NodeDeclareFunction declare
MutableVArraySpan< T > span