42 uiItemR(layout,
ptr,
"mode", 0,
"", ICON_NONE);
70 for (const int i : range) {
72 float4x4::from_normalized_axis_data({0, 0, 0}, normals[i], tangents[i]).to_euler();
93 if (
splines[i]->evaluated_points_num() > 0) {
102 const float resolution =
std::max(
params.get_input<
float>(
"Length"), 0.0001f);
107 if (
splines[i]->evaluated_points_num() > 0) {
115 return curve.evaluated_point_offsets();
148 struct AnonymousAttributeIDs {
154 struct ResultAttributes {
168 const AnonymousAttributeIDs &attributes)
172 outputs.positions = ensure_point_attribute<float3>(points,
"position");
173 outputs.radii = ensure_point_attribute<float>(points,
"radius");
175 if (attributes.tangent_id) {
176 outputs.tangents = ensure_point_attribute<float3>(points, attributes.tangent_id.get());
178 if (attributes.normal_id) {
179 outputs.normals = ensure_point_attribute<float3>(points, attributes.normal_id.get());
181 if (attributes.rotation_id) {
182 outputs.rotations = ensure_point_attribute<float3>(points, attributes.rotation_id.get());
188 curve.splines().first()->attributes.foreach_attribute(
190 if (
id.should_be_kept()) {
191 outputs.point_attributes.add_new(
207 ResultAttributes &
data)
210 for (const int i : range) {
211 const Spline &spline = *splines[i];
212 const int offset = offsets[i];
213 const int size = offsets[i + 1] - offsets[i];
215 data.positions.slice(offset, size).copy_from(spline.evaluated_positions());
216 spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size));
218 for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
219 const AttributeIDRef attribute_id = item.key;
220 const GMutableSpan dst = item.value;
222 BLI_assert(spline.attributes.get_for_read(attribute_id));
223 GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
225 spline.interpolate_to_evaluated(spline_span).materialize(dst.slice(offset, size).data());
228 if (!data.tangents.is_empty()) {
229 data.tangents.slice(offset, size).copy_from(spline.evaluated_tangents());
231 if (!data.normals.is_empty()) {
232 data.normals.slice(offset, size).copy_from(spline.evaluated_normals());
240 ResultAttributes &
data)
243 for (const int i : range) {
244 const Spline &spline = *splines[i];
245 const int offset = offsets[i];
246 const int num = offsets[i + 1] - offsets[i];
251 const Array<float> uniform_samples = spline.sample_uniform_index_factors(num);
253 spline.sample_with_index_factors<float3>(
254 spline.evaluated_positions(), uniform_samples, data.positions.slice(offset, num));
255 spline.sample_with_index_factors<float>(spline.interpolate_to_evaluated(spline.radii()),
257 data.radii.slice(offset, num));
259 for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) {
260 const AttributeIDRef attribute_id = item.key;
261 const GMutableSpan dst = item.value;
263 BLI_assert(spline.attributes.get_for_read(attribute_id));
264 GSpan spline_span = *spline.attributes.get_for_read(attribute_id);
266 spline.sample_with_index_factors(
267 spline.interpolate_to_evaluated(spline_span), uniform_samples, dst.slice(offset, num));
270 if (!data.tangents.is_empty()) {
271 Span<float3> src_tangents = spline.evaluated_tangents();
272 MutableSpan<float3> sampled_tangents = data.tangents.slice(offset, num);
273 spline.sample_with_index_factors<float3>(src_tangents, uniform_samples, sampled_tangents);
274 for (float3 &vector : sampled_tangents) {
275 vector = math::normalize(vector);
279 if (!data.normals.is_empty()) {
280 Span<float3> src_normals = spline.evaluated_normals();
281 MutableSpan<float3> sampled_normals = data.normals.slice(offset, num);
282 spline.sample_with_index_factors<float3>(src_normals, uniform_samples, sampled_normals);
283 for (float3 &vector : sampled_normals) {
284 vector = math::normalize(vector);
295 curve.attributes.foreach_attribute(
297 const GSpan curve_attribute = *
curve.attributes.get_for_read(attribute_id);
301 for (
const int i :
curve.splines().index_range()) {
302 const int offset = offsets[i];
303 const int num = offsets[i + 1] - offsets[i];
304 type.fill_assign_n(curve_attribute[i], dst[
offset], num);
318 AnonymousAttributeIDs attribute_outputs;
325 geometry_set.modify_geometry_sets([&](
GeometrySet &geometry_set) {
327 geometry_set.remove_geometry_during_modify();
333 curve->assert_valid_point_attributes();
336 const int total_num = offsets.
last();
337 if (total_num == 0) {
345 points, *
curve, attribute_outputs);
367 params.set_output(
"Points", std::move(geometry_set));
368 if (attribute_outputs.tangent_id) {
371 AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.tangent_id),
372 params.attribute_producer_name()));
374 if (attribute_outputs.normal_id) {
377 AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.normal_id),
378 params.attribute_producer_name()));
380 if (attribute_outputs.rotation_id) {
383 AnonymousAttributeFieldInput::Create<float3>(std::move(attribute_outputs.rotation_id),
384 params.attribute_producer_name()));
@ GEO_COMPONENT_TYPE_POINT_CLOUD
@ GEO_COMPONENT_TYPE_CURVE
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
#define NODE_STORAGE_FUNCS(StorageT)
void nodeSetSocketAvailability(struct bNodeTree *ntree, struct bNodeSocket *sock, bool is_available)
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
#define NODE_CLASS_GEOMETRY
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
#define GEO_NODE_CURVE_TO_POINTS
void nodeRegisterType(struct bNodeType *ntype)
General operations for point clouds.
struct PointCloud * BKE_pointcloud_new_nomain(int totpoint)
std::unique_ptr< CurveEval > curves_to_curve_eval(const Curves &curves)
#define BLI_assert_unreachable()
GeometryNodeCurveResampleMode
@ GEO_NODE_CURVE_RESAMPLE_LENGTH
@ GEO_NODE_CURVE_RESAMPLE_EVALUATED
@ GEO_NODE_CURVE_RESAMPLE_COUNT
_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 type
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static void remember_deformed_curve_positions_if_necessary(GeometrySet &geometry)
std::optional< blender::bke::MutableAttributeAccessor > attributes_for_write() final
const T & last(const int64_t n=0) const
const CPPType & type() const
void make_available(bNode &node) const
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
OwnedAnonymousAttributeID< true > StrongAnonymousAttributeID
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static void copy_evaluated_point_attributes(const Span< SplinePtr > splines, const Span< int > offsets, ResultAttributes &data)
static MutableSpan< T > ensure_point_attribute(PointCloudComponent &points, const AttributeIDRef &attribute_id)
static void curve_create_default_rotation_attribute(Span< float3 > tangents, Span< float3 > normals, MutableSpan< float3 > rotations)
static void copy_spline_domain_attributes(const CurveEval &curve, const Span< int > offsets, PointCloudComponent &points)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void node_init(bNodeTree *UNUSED(tree), bNode *node)
static void copy_uniform_sample_point_attributes(const Span< SplinePtr > splines, const Span< int > offsets, ResultAttributes &data)
static ResultAttributes create_attributes_for_transfer(PointCloudComponent &points, const CurveEval &curve, const AnonymousAttributeIDs &attributes)
static Array< int > calculate_spline_point_offsets(GeoNodeExecParams ¶ms, const GeometryNodeCurveResampleMode mode, const CurveEval &curve, const Span< SplinePtr > splines)
static void node_update(bNodeTree *ntree, bNode *node)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
MutableSpan< float3 > positions
void register_node_type_geo_curve_to_points()
Map< AttributeIDRef, GMutableSpan > point_attributes
StrongAnonymousAttributeID normal_id
StrongAnonymousAttributeID tangent_id
MutableSpan< float > radii
MutableSpan< float3 > tangents
StrongAnonymousAttributeID rotation_id
MutableSpan< float3 > rotations
MutableSpan< float3 > normals
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
static bNodeSocketTemplate outputs[]
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
void node_free_standard_storage(bNode *node)
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
void keep_only_during_modify(const blender::Span< GeometryComponentType > component_types)
const Curves * get_curves_for_read() const
void remove_geometry_during_modify()
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