46 {
SOCK_INT,
N_(
"Seed"), 0, 0, 0, 0, -10000, 10000},
59 uiItemR(layout,
ptr,
"distribute_method", 0,
"", ICON_NONE);
88 return {looptris, looptris_len};
93 const float base_density,
102 for (
const int looptri_index : looptris.
index_range()) {
103 const MLoopTri &looptri = looptris[looptri_index];
104 const int v0_loop = looptri.
tri[0];
105 const int v1_loop = looptri.
tri[1];
106 const int v2_loop = looptri.
tri[2];
114 float looptri_density_factor = 1.0f;
115 if (density_factors !=
nullptr) {
116 const float v0_density_factor =
std::max(0.0f, (*density_factors)[v0_loop]);
117 const float v1_density_factor =
std::max(0.0f, (*density_factors)[v1_loop]);
118 const float v2_density_factor =
std::max(0.0f, (*density_factors)[v2_loop]);
119 looptri_density_factor = (v0_density_factor + v1_density_factor + v2_density_factor) / 3.0f;
126 const float points_amount_fl =
area * base_density * looptri_density_factor;
127 const float add_point_probability =
fractf(points_amount_fl);
129 const int point_amount = (int)points_amount_fl + (
int)
add_point;
131 for (
int i = 0; i < point_amount; i++) {
135 r_positions.
append(point_pos);
136 r_bary_coords.
append(bary_coord);
137 r_looptri_indices.
append(looptri_index);
143 const int initial_points_len)
145 KDTree_3d *kdtree = BLI_kdtree_3d_new(initial_points_len);
149 for (
const float3 position : positions) {
150 BLI_kdtree_3d_insert(kdtree, i_point, position);
154 BLI_kdtree_3d_balance(kdtree);
161 const float minimum_distance,
163 const int initial_points_len)
165 if (minimum_distance <= 0.0f) {
169 KDTree_3d *kdtree =
build_kdtree(positions_all, initial_points_len);
173 for (
const int i_instance : positions_all.index_range()) {
175 const int offset = instance_start_offsets[i_instance];
178 if (elimination_mask[offset + i]) {
182 struct CallbackData {
185 } callback_data = {offset + i, elimination_mask};
187 BLI_kdtree_3d_range_search_cb(
192 CallbackData &callback_data = *
static_cast<CallbackData *
>(
user_data);
193 if (index != callback_data.index) {
194 callback_data.elimination_mask[index] =
true;
201 BLI_kdtree_3d_free(kdtree);
213 if (elimination_mask[i]) {
217 const MLoopTri &looptri = looptris[looptri_indices[i]];
218 const float3 bary_coord = bary_coords[i];
220 const int v0_loop = looptri.
tri[0];
221 const int v1_loop = looptri.
tri[1];
222 const int v2_loop = looptri.
tri[2];
224 const float v0_density_factor =
std::max(0.0f, density_factors[v0_loop]);
225 const float v1_density_factor =
std::max(0.0f, density_factors[v1_loop]);
226 const float v2_density_factor =
std::max(0.0f, density_factors[v2_loop]);
228 const float probablity = v0_density_factor * bary_coord.
x + v1_density_factor * bary_coord.
y +
229 v2_density_factor * bary_coord.
z;
232 if (
hash > probablity) {
233 elimination_mask[i] =
true;
243 for (
int i = positions.
size() - 1; i >= 0; i--) {
244 if (elimination_mask[i]) {
263 const int looptri_index = looptri_indices[i];
264 const MLoopTri &looptri = looptris[looptri_index];
265 const float3 &bary_coord = bary_coords[i];
271 const T &v0 = data_in[v0_index];
272 const T &
v1 = data_in[v1_index];
273 const T &
v2 = data_in[v2_index];
276 data_out[i] = interpolated_value;
291 const int looptri_index = looptri_indices[i];
292 const MLoopTri &looptri = looptris[looptri_index];
293 const float3 &bary_coord = bary_coords[i];
295 const int loop_index_0 = looptri.
tri[0];
296 const int loop_index_1 = looptri.
tri[1];
297 const int loop_index_2 = looptri.
tri[2];
299 const T &v0 = data_in[loop_index_0];
300 const T &
v1 = data_in[loop_index_1];
301 const T &
v2 = data_in[loop_index_2];
304 data_out[i] = interpolated_value;
318 const int looptri_index = looptri_indices[i];
319 const MLoopTri &looptri = looptris[looptri_index];
320 const int poly_index = looptri.
poly;
321 data_out[i] = data_in[poly_index];
333 switch (source_domain) {
335 interpolate_attribute_point<T>(
mesh, bary_coords, looptri_indices, source_span, output_span);
339 interpolate_attribute_corner<T>(
340 mesh, bary_coords, looptri_indices, source_span, output_span);
344 interpolate_attribute_face<T>(
mesh, looptri_indices, source_span, output_span);
368 if (!attribute_out) {
385 if (!dummy_attribute) {
386 i_instance += set_group.transforms.size();
392 attribute_name, source_domain, output_data_type,
nullptr);
393 if (!source_attribute) {
394 i_instance += set_group.transforms.size();
397 fn::GSpan source_span = source_attribute->get_span();
400 using T = decltype(dummy);
402 for (
const int UNUSED(i_set_instance) : set_group.transforms.index_range()) {
403 const int offset = instance_start_offsets[i_instance];
404 Span<float3> bary_coords = bary_coords_array[i_instance];
405 Span<int> looptri_indices = looptri_indices_array[i_instance];
408 interpolate_attribute<T>(
mesh,
449 const int offset = instance_start_offsets[i_instance];
451 Span<float3> bary_coords = bary_coords_array[i_instance];
452 Span<int> looptri_indices = looptri_indices_array[i_instance];
458 float rotation_matrix[3][3];
462 const int looptri_index = looptri_indices[i];
463 const MLoopTri &looptri = looptris[looptri_index];
464 const float3 &bary_coord = bary_coords[i];
473 ids[i] = (int)(bary_coord.
hash() + (
uint64_t)looptri_index);
497 instance_start_offsets,
501 looptri_indices_array);
503 set_groups, instance_start_offsets,
component, bary_coords_array, looptri_indices_array);
517 const bool use_one_default = density_attribute_name.
is_empty();
529 Vector<int> &looptri_indices = looptri_indices_all[i_instance];
547 const float minimum_distance,
552 Array<int> instance_start_offsets(positions_all.size());
553 int initial_points_len = 0;
562 Vector<int> &looptri_indices = looptri_indices_all[i_instance];
564 mesh,
transform, density,
nullptr,
seed, positions, bary_coords, looptri_indices);
566 instance_start_offsets[i_instance] = initial_points_len;
567 initial_points_len += positions.
size();
575 const bool use_one_default = density_attribute_name.
is_empty();
580 Array<bool> elimination_mask(initial_points_len,
false);
582 instance_start_offsets,
595 for (
const int UNUSED(i_set_instance) : set_group.transforms.index_range()) {
598 Vector<int> &looptri_indices = looptri_indices_all[i_instance];
600 const int offset = instance_start_offsets[i_instance];
625 const int seed =
params.get_input<
int>(
"Seed") * 5383843;
626 const float density =
params.extract_input<
float>(
"Density Max");
627 const std::string density_attribute_name =
params.extract_input<std::string>(
628 "Density Attribute");
630 if (density <= 0.0f) {
643 for (
int i = set_groups.
size() - 1; i >= 0; i--) {
644 const GeometrySet &set = set_groups[i].geometry_set;
656 int instances_len = 0;
658 instances_len += set_group.transforms.size();
668 switch (distribute_method) {
671 density_attribute_name,
676 looptri_indices_all);
680 const float minimum_distance =
params.extract_input<
float>(
"Distance Min");
682 density_attribute_name,
688 looptri_indices_all);
693 int final_points_len = 0;
697 instance_start_offsets[i] = final_points_len;
698 final_points_len += positions.
size();
702 for (
const int instance_index : positions_all.
index_range()) {
703 const int offset = instance_start_offsets[instance_index];
705 memcpy(pointcloud->
co + offset, positions.
data(),
sizeof(
float3) * positions.
size());
718 instance_start_offsets,
722 looptri_indices_all);
724 params.set_output(
"Geometry", std::move(geometry_set_out));
@ GEO_COMPONENT_TYPE_MESH
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(struct Mesh *mesh)
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available)
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
#define NODE_CLASS_GEOMETRY
void nodeRegisterType(struct bNodeType *ntype)
General operations for point-clouds.
struct PointCloud * BKE_pointcloud_new_nomain(const int totpoint)
BLI_INLINE float BLI_hash_int_01(unsigned int k)
BLI_INLINE unsigned int BLI_hash_int(unsigned int k)
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 mul_m3_v3(const float M[3][3], float r[3])
void mat4_to_rot(float rot[3][3], const float wmat[4][4])
void quat_to_eul(float eul[3], const float quat[4])
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
static uint8 component(Color32 c, uint i)
GeometryNodePointDistributeMode
@ GEO_NODE_POINT_DISTRIBUTE_POISSON
@ GEO_NODE_POINT_DISTRIBUTE_RANDOM
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave Voronoi Brick Texture Vector Combine Vertex Separate Vector White RGB Map Separate Set Z Dilate Combine Combine Color Channel Split ID Combine Luminance Directional Alpha Distance Hue Movie Ellipse Bokeh View Corner Anti Mix RGB Hue Separate TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC Boolean Random Edge Subdivision GEO_NODE_POINT_DISTRIBUTE
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static unsigned long seed
blender::bke::ReadAttributePtr attribute_try_get_for_read(const blender::StringRef attribute_name) const
blender::bke::ReadAttributePtr attribute_get_for_read(const blender::StringRef attribute_name, const AttributeDomain domain, const CustomDataType data_type, const void *default_value) const
const Mesh * get_for_read() const
void apply_span_and_save()
IndexRange index_range() const
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
ItemIterator items() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr IndexRange index_range() const
float3 get_barycentric_coordinates()
constexpr const T * data() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
void remove_and_reorder(const int64_t index)
void append(const T &value)
fn::GMutableSpan get_span_for_write_only()
MutableSpan< T > typed() const
static float normals[][3]
static void add_point(bGPDstroke *gps, float scale, const int32_t offset[2], float x, float y)
IconTextureDrawCall normal
MINLINE float fractf(float a)
T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2)
void convert_to_static_type(const CustomDataType data_type, const Func &func)
TypedReadAttribute< float > FloatReadAttribute
void geometry_set_gather_instances(const GeometrySet &geometry_set, Vector< GeometryInstanceGroup > &r_instance_groups)
void geometry_set_gather_instances_attribute_info(Span< GeometryInstanceGroup > set_groups, Span< GeometryComponentType > component_types, const Set< std::string > &ignored_attributes, Map< std::string, AttributeKind > &r_attributes)
std::unique_ptr< ReadAttribute > ReadAttributePtr
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< Vector< float3 >> positions_all, Span< int > instance_start_offsets, const float minimum_distance, MutableSpan< bool > elimination_mask, const int initial_points_len)
static void sample_mesh_surface(const Mesh &mesh, const float4x4 &transform, const float base_density, const FloatReadAttribute *density_factors, const int seed, Vector< float3 > &r_positions, Vector< float3 > &r_bary_coords, Vector< int > &r_looptri_indices)
static float3 normal_to_euler_rotation(const float3 normal)
static BLI_NOINLINE void interpolate_attribute(const Mesh &mesh, Span< float3 > bary_coords, Span< int > looptri_indices, const AttributeDomain source_domain, Span< T > source_span, MutableSpan< T > output_span)
static BLI_NOINLINE void add_remaining_point_attributes(Span< GeometryInstanceGroup > set_groups, Span< int > instance_start_offsets, const Map< std::string, AttributeKind > &attributes, GeometryComponent &component, Span< Vector< float3 >> bary_coords_array, Span< Vector< int >> looptri_indices_array)
static void distribute_points_poisson_disk(Span< GeometryInstanceGroup > set_groups, const StringRef density_attribute_name, const float density, const int seed, const float minimum_distance, MutableSpan< Vector< float3 >> positions_all, MutableSpan< Vector< float3 >> bary_coords_all, MutableSpan< Vector< int >> looptri_indices_all)
static void geo_node_point_distribute_exec(GeoNodeExecParams params)
static Span< MLoopTri > get_mesh_looptris(const Mesh &mesh)
static BLI_NOINLINE void compute_special_attributes(Span< GeometryInstanceGroup > sets, Span< int > instance_start_offsets, GeometryComponent &component, Span< Vector< float3 >> bary_coords_array, Span< Vector< int >> looptri_indices_array)
static BLI_NOINLINE KDTree_3d * build_kdtree(Span< Vector< float3 >> positions_all, const int initial_points_len)
static BLI_NOINLINE void eliminate_points_based_on_mask(Span< bool > elimination_mask, Vector< float3 > &positions, Vector< float3 > &bary_coords, Vector< int > &looptri_indices)
static BLI_NOINLINE void interpolate_attribute_point(const Mesh &mesh, const Span< float3 > bary_coords, const Span< int > looptri_indices, const Span< T > data_in, MutableSpan< T > data_out)
static void distribute_points_random(Span< GeometryInstanceGroup > set_groups, const StringRef density_attribute_name, const float density, const int seed, MutableSpan< Vector< float3 >> positions_all, MutableSpan< Vector< float3 >> bary_coords_all, MutableSpan< Vector< int >> looptri_indices_all)
static BLI_NOINLINE void interpolate_attribute_face(const Mesh &mesh, const Span< int > looptri_indices, const Span< T > data_in, MutableSpan< T > data_out)
static BLI_NOINLINE void interpolate_attribute_corner(const Mesh &mesh, const Span< float3 > bary_coords, const Span< int > looptri_indices, const Span< T > data_in, MutableSpan< T > data_out)
static BLI_NOINLINE void interpolate_existing_attributes(Span< GeometryInstanceGroup > set_groups, Span< int > instance_start_offsets, const Map< std::string, AttributeKind > &attributes, GeometryComponent &component, Span< Vector< float3 >> bary_coords_array, Span< Vector< int >> looptri_indices_array)
static BLI_NOINLINE void update_elimination_mask_based_on_density_factors(const Mesh &mesh, const FloatReadAttribute &density_factors, Span< float3 > bary_coords, Span< int > looptri_indices, MutableSpan< bool > elimination_mask)
void uninitialized_fill_n(T *dst, int64_t n, const T &value)
static void geo_node_point_distribute_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
void register_node_type_geo_point_distribute()
static bNodeSocketTemplate geo_node_point_distribute_in[]
static void node_point_distribute_update(bNodeTree *UNUSED(ntree), bNode *node)
static bNodeSocketTemplate geo_node_point_distribute_out[]
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
unsigned __int64 uint64_t
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
const GeometryComponent * get_component_for_read(GeometryComponentType component_type) const
static GeometrySet create_with_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Compact definition of a node socket.
NodeGeometryExecFunction geometry_node_execute
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)