23 for (
MEdge &edge : edges) {
29 const int edge_offset,
30 const int poly_offset,
31 const int loop_offset,
32 const int main_point_num,
33 const int profile_point_num,
34 const bool main_cyclic,
35 const bool profile_cyclic,
44 if (profile_point_num == 1) {
45 for (
const int i :
IndexRange(main_point_num - 1)) {
46 MEdge &edge = edges[edge_offset + i];
47 edge.v1 = vert_offset + i;
48 edge.v2 = vert_offset + i + 1;
52 if (main_cyclic && main_segment_num > 1) {
53 MEdge &edge = edges[edge_offset + main_segment_num - 1];
54 edge.v1 = vert_offset + main_point_num - 1;
55 edge.v2 = vert_offset;
62 const int main_edges_start = edge_offset;
63 for (
const int i_profile :
IndexRange(profile_point_num)) {
64 const int profile_edge_offset = main_edges_start + i_profile * main_segment_num;
65 for (
const int i_ring :
IndexRange(main_segment_num)) {
66 const int i_next_ring = (i_ring == main_point_num - 1) ? 0 : i_ring + 1;
68 const int ring_vert_offset = vert_offset + profile_point_num * i_ring;
69 const int next_ring_vert_offset = vert_offset + profile_point_num * i_next_ring;
71 MEdge &edge = edges[profile_edge_offset + i_ring];
72 edge.v1 = ring_vert_offset + i_profile;
73 edge.v2 = next_ring_vert_offset + i_profile;
79 const int profile_edges_start = main_edges_start + profile_point_num * main_segment_num;
80 for (
const int i_ring :
IndexRange(main_point_num)) {
81 const int ring_vert_offset = vert_offset + profile_point_num * i_ring;
83 const int ring_edge_offset = profile_edges_start + i_ring * profile_segment_num;
84 for (
const int i_profile :
IndexRange(profile_segment_num)) {
85 const int i_next_profile = (i_profile == profile_point_num - 1) ? 0 : i_profile + 1;
87 MEdge &edge = edges[ring_edge_offset + i_profile];
88 edge.v1 = ring_vert_offset + i_profile;
89 edge.v2 = ring_vert_offset + i_next_profile;
95 for (
const int i_ring :
IndexRange(main_segment_num)) {
96 const int i_next_ring = (i_ring == main_point_num - 1) ? 0 : i_ring + 1;
98 const int ring_vert_offset = vert_offset + profile_point_num * i_ring;
99 const int next_ring_vert_offset = vert_offset + profile_point_num * i_next_ring;
101 const int ring_edge_start = profile_edges_start + profile_segment_num * i_ring;
102 const int next_ring_edge_offset = profile_edges_start + profile_segment_num * i_next_ring;
104 const int ring_poly_offset = poly_offset + i_ring * profile_segment_num;
105 const int ring_loop_offset = loop_offset + i_ring * profile_segment_num * 4;
107 for (
const int i_profile :
IndexRange(profile_segment_num)) {
108 const int ring_segment_loop_offset = ring_loop_offset + i_profile * 4;
109 const int i_next_profile = (i_profile == profile_point_num - 1) ? 0 : i_profile + 1;
111 const int main_edge_start = main_edges_start + main_segment_num * i_profile;
112 const int next_main_edge_start = main_edges_start + main_segment_num * i_next_profile;
114 MPoly &poly = polys[ring_poly_offset + i_profile];
115 poly.
loopstart = ring_segment_loop_offset;
119 MLoop &loop_a = loops[ring_segment_loop_offset];
120 loop_a.
v = ring_vert_offset + i_profile;
121 loop_a.
e = ring_edge_start + i_profile;
122 MLoop &loop_b = loops[ring_segment_loop_offset + 1];
123 loop_b.
v = ring_vert_offset + i_next_profile;
124 loop_b.
e = next_main_edge_start + i_ring;
125 MLoop &loop_c = loops[ring_segment_loop_offset + 2];
126 loop_c.
v = next_ring_vert_offset + i_next_profile;
127 loop_c.
e = next_ring_edge_offset + i_profile;
128 MLoop &loop_d = loops[ring_segment_loop_offset + 3];
129 loop_d.
v = next_ring_vert_offset + i_profile;
130 loop_d.
e = main_edge_start + i_ring;
134 const bool has_caps = fill_caps && !main_cyclic && profile_cyclic && profile_point_num > 2;
136 const int poly_num = main_segment_num * profile_segment_num;
137 const int cap_loop_offset = loop_offset + poly_num * 4;
138 const int cap_poly_offset = poly_offset + poly_num;
140 MPoly &poly_start = polys[cap_poly_offset];
142 poly_start.
totloop = profile_segment_num;
143 MPoly &poly_end = polys[cap_poly_offset + 1];
144 poly_end.
loopstart = cap_loop_offset + profile_segment_num;
145 poly_end.
totloop = profile_segment_num;
147 const int last_ring_index = main_point_num - 1;
148 const int last_ring_vert_offset = vert_offset + profile_point_num * last_ring_index;
149 const int last_ring_edge_offset = profile_edges_start + profile_segment_num * last_ring_index;
151 for (
const int i :
IndexRange(profile_segment_num)) {
152 const int i_inv = profile_segment_num - i - 1;
153 MLoop &loop_start = loops[cap_loop_offset + i];
154 loop_start.
v = vert_offset + i_inv;
155 loop_start.
e = profile_edges_start +
156 ((i == (profile_segment_num - 1)) ? (profile_segment_num - 1) : (i_inv - 1));
157 MLoop &loop_end = loops[cap_loop_offset + profile_segment_num + i];
158 loop_end.v = last_ring_vert_offset + i;
159 loop_end.e = last_ring_edge_offset + i;
168 const int main_segment_num,
174 const int main_edges_start = 0;
179 for (
const int i :
IndexRange(profile_point_num).drop_front(1)) {
182 main_edges_start + main_segment_num * control_point_offsets[i - 1], main_segment_num));
188 const int profile_point_num,
196 if (profile_point_num == 1) {
197 for (
const int i_ring :
IndexRange(main_point_num)) {
200 if (!
radii.is_empty()) {
204 MVert &vert = mesh_positions[i_ring];
209 for (
const int i_ring :
IndexRange(main_point_num)) {
212 if (!
radii.is_empty()) {
216 const int ring_vert_start = i_ring * profile_point_num;
217 for (
const int i_profile :
IndexRange(profile_point_num)) {
218 MVert &vert = mesh_positions[ring_vert_start + i_profile];
219 copy_v3_v3(vert.
co, point_matrix * profile_positions[i_profile]);
235 return {
main, profile,
main.cyclic(), profile.cyclic()};
277 result.vert[mesh_index] = vert_offset;
278 result.edge[mesh_index] = edge_offset;
279 result.loop[mesh_index] = loop_offset;
280 result.poly[mesh_index] = poly_offset;
282 result.main_indices[mesh_index] = i_main;
283 result.profile_indices[mesh_index] = i_profile;
289 const bool has_caps = fill_caps && !main_cyclic && profile_cyclic && profile_point_num > 2;
290 const int tube_face_num = main_segment_num * profile_segment_num;
292 vert_offset += main_point_num * profile_point_num;
296 edge_offset += main_point_num * profile_segment_num + main_segment_num * profile_point_num;
299 poly_offset += tube_face_num + (has_caps ? 2 : 0);
303 loop_offset += tube_face_num * 4 + (has_caps ? profile_segment_num * 2 : 0);
309 result.vert.last() = vert_offset;
310 result.edge.last() = edge_offset;
311 result.loop.last() = loop_offset;
312 result.poly.last() = poly_offset;
330 return meta_data->domain;
339 if (
id.is_named() &&
id.name() ==
"position") {
346 if (!
id.should_be_kept()) {
354 const std::array<int, CURVE_TYPES_NUM> &type_counts,
358 return src.get_internal_span();
360 buffer.reinitialize(
curves.evaluated_points_num() *
src.type().size());
362 curves.interpolate_to_evaluated(
src.get_internal_span(), eval);
385 template<
typename Fn>
391 for (const int i : range) {
392 const int i_main = offsets.main_indices[i];
393 const int i_profile = offsets.profile_indices[i];
395 const IndexRange main_points = info.main.evaluated_points_for_curve(i_main);
396 const IndexRange profile_points = info.profile.evaluated_points_for_curve(i_profile);
398 const bool main_cyclic = info.main_cyclic[i_main];
399 const bool profile_cyclic = info.profile_cyclic[i_profile];
404 fn(CombinationInfo{i_main,
410 curves::segments_num(main_points.size(), main_cyclic),
411 curves::segments_num(profile_points.size(), profile_cyclic),
412 offsets_to_range(offsets.vert.as_span(), i),
413 offsets_to_range(offsets.edge.as_span(), i),
414 offsets_to_range(offsets.poly.as_span(), i),
415 offsets_to_range(offsets.loop.as_span(), i)});
422 const int profile_point_num,
425 for (
const int i_ring :
src.index_range()) {
426 const int ring_vert_start = i_ring * profile_point_num;
427 dst.
slice(ring_vert_start, profile_point_num).
fill(
src[i_ring]);
433 const int profile_point_num,
434 const int main_segment_num,
435 const int profile_segment_num,
438 const int edges_start = profile_point_num * main_segment_num;
439 for (
const int i_ring :
src.index_range()) {
440 const int ring_edge_start = edges_start + profile_segment_num * i_ring;
441 dst.
slice(ring_edge_start, profile_segment_num).
fill(
src[i_ring]);
447 const int main_segment_num,
448 const int profile_segment_num,
451 for (
const int i_ring :
IndexRange(main_segment_num)) {
452 const int ring_face_start = profile_segment_num * i_ring;
453 dst.
slice(ring_face_start, profile_segment_num).
fill(
src[i_ring]);
464 using T = decltype(dummy);
465 const Span<T> src = src_all.typed<T>();
466 MutableSpan<T> dst = dst_all.typed<T>();
467 switch (dst_domain) {
468 case ATTR_DOMAIN_POINT:
469 foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
470 copy_main_point_data_to_mesh_verts(
471 src.slice(info.main_points), info.profile_points.size(), dst.slice(info.vert_range));
474 case ATTR_DOMAIN_EDGE:
475 foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
476 copy_main_point_data_to_mesh_edges(src.slice(info.main_points),
477 info.profile_points.size(),
478 info.main_segment_num,
479 info.profile_segment_num,
480 dst.slice(info.edge_range));
483 case ATTR_DOMAIN_FACE:
484 foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
485 copy_main_point_data_to_mesh_faces(src.slice(info.main_points),
486 info.main_segment_num,
487 info.profile_segment_num,
488 dst.slice(info.poly_range));
491 case ATTR_DOMAIN_CORNER:
495 BLI_assert_unreachable();
503 const int main_point_num,
506 for (
const int i_ring :
IndexRange(main_point_num)) {
507 const int profile_vert_start = i_ring *
src.size();
508 for (
const int i_profile :
src.index_range()) {
509 dst[profile_vert_start + i_profile] =
src[i_profile];
516 const int main_segment_num,
519 for (
const int i_profile :
src.index_range()) {
520 const int profile_edge_offset = i_profile * main_segment_num;
521 dst.
slice(profile_edge_offset, main_segment_num).
fill(
src[i_profile]);
527 const int main_segment_num,
528 const int profile_segment_num,
531 for (
const int i_ring :
IndexRange(main_segment_num)) {
532 const int profile_face_start = i_ring * profile_segment_num;
533 for (
const int i_profile :
IndexRange(profile_segment_num)) {
534 dst[profile_face_start + i_profile] =
src[i_profile];
546 using T = decltype(dummy);
547 const Span<T> src = src_all.typed<T>();
548 MutableSpan<T> dst = dst_all.typed<T>();
549 switch (dst_domain) {
550 case ATTR_DOMAIN_POINT:
551 foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
552 copy_profile_point_data_to_mesh_verts(
553 src.slice(info.profile_points), info.main_points.size(), dst.slice(info.vert_range));
556 case ATTR_DOMAIN_EDGE:
557 foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
558 copy_profile_point_data_to_mesh_edges(
559 src.slice(info.profile_points), info.main_segment_num, dst.slice(info.edge_range));
562 case ATTR_DOMAIN_FACE:
563 foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) {
564 copy_profile_point_data_to_mesh_faces(src.slice(info.profile_points),
565 info.main_segment_num,
566 info.profile_segment_num,
567 dst.slice(info.poly_range));
570 case ATTR_DOMAIN_CORNER:
574 BLI_assert_unreachable();
591 for (const int i : range) {
592 dst.slice(offsets_to_range(mesh_offsets, i)).fill(src[curve_indices[i]]);
605 switch (dst_domain) {
607 offsets = mesh_offsets.
vert;
610 offsets = mesh_offsets.
edge;
613 offsets = mesh_offsets.
poly;
616 offsets = mesh_offsets.
loop;
623 using T = decltype(dummy);
624 copy_indices_to_offset_ranges(src.typed<T>(), curve_indices, offsets, dst.typed<T>());
630 const bool fill_caps)
674 if (main_attributes.
contains(
"radius")) {
678 main.curve_type_counts(),
701 const IndexRange points = profile.points_for_curve(info.i_profile);
702 mark_bezier_vector_edges_sharp(points.size(),
703 info.main_segment_num,
704 profile.bezier_evaluated_offsets_for_curve(info.i_profile),
705 handle_types_left.slice(points),
706 handle_types_right.slice(points),
707 edges.slice(info.edge_range));
720 main_attributes_set.
add_new(
id);
728 id, dst_domain,
type);
763 id, dst_domain,
type);
791 curves.offsets_for_write().last() = 1;
Low-level operations for curves.
General operations, lookup, etc. for materials.
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
#define BLI_assert_unreachable()
MINLINE void copy_v3_v3(float r[3], const float a[3])
_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
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
int main(int argc, char *argv[])
const T & last(const int64_t n=0) const
const CPPType & type() const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr void fill(const T &value)
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
void add_new(const Key &key)
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T & first() const
constexpr IndexRange index_range() const
bool is_builtin(const AttributeIDRef &attribute_id) const
bool contains(const AttributeIDRef &attribute_id) const
std::optional< AttributeMetaData > lookup_meta_data(const AttributeIDRef &attribute_id) const
GAttributeReader lookup(const AttributeIDRef &attribute_id) const
GVArray lookup_or_default(const AttributeIDRef &attribute_id, const eAttrDomain domain, const eCustomDataType data_type, const void *default_value=nullptr) const
bool for_all(const AttributeForeachCallback fn) const
IndexRange evaluated_points_for_curve(int index) const
VArray< int8_t > handle_types_left() const
VArray< int8_t > handle_types_right() const
IndexRange curves_range() const
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
void ensure_evaluated_offsets() const
AttributeAccessor attributes() const
Span< float3 > evaluated_positions() const
VArray< int8_t > curve_types() const
SyclQueue void void * src
ccl_global float * buffer
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
bool point_is_sharp(Span< int8_t > handle_types_left, Span< int8_t > handle_types_right, int index)
int segments_num(const int points_num, const bool cyclic)
Mesh * curve_to_wire_mesh(const CurvesGeometry &curve)
static void copy_main_point_data_to_mesh_verts(const Span< T > src, const int profile_point_num, MutableSpan< T > dst)
static void mark_bezier_vector_edges_sharp(const int profile_point_num, const int main_segment_num, const Span< int > control_point_offsets, const Span< int8_t > handle_types_left, const Span< int8_t > handle_types_right, MutableSpan< MEdge > edges)
static void copy_main_point_domain_attribute_to_mesh(const CurvesInfo &curves_info, const ResultOffsets &offsets, const eAttrDomain dst_domain, const GSpan src_all, GMutableSpan dst_all)
Mesh * curve_to_mesh_sweep(const CurvesGeometry &main, const CurvesGeometry &profile, bool fill_caps)
static void copy_profile_point_domain_attribute_to_mesh(const CurvesInfo &curves_info, const ResultOffsets &offsets, const eAttrDomain dst_domain, const GSpan src_all, GMutableSpan dst_all)
static void mark_edges_sharp(MutableSpan< MEdge > edges)
static CurvesInfo get_curves_info(const CurvesGeometry &main, const CurvesGeometry &profile)
static void copy_profile_point_data_to_mesh_edges(const Span< T > src, const int main_segment_num, MutableSpan< T > dst)
static void fill_mesh_topology(const int vert_offset, const int edge_offset, const int poly_offset, const int loop_offset, const int main_point_num, const int profile_point_num, const bool main_cyclic, const bool profile_cyclic, const bool fill_caps, MutableSpan< MEdge > edges, MutableSpan< MLoop > loops, MutableSpan< MPoly > polys)
static eAttrDomain get_attribute_domain_for_mesh(const AttributeAccessor &mesh_attributes, const AttributeIDRef &attribute_id)
static CurvesGeometry get_curve_single_vert()
static void copy_main_point_data_to_mesh_faces(const Span< T > src, const int main_segment_num, const int profile_segment_num, MutableSpan< T > dst)
static void foreach_curve_combination(const CurvesInfo &info, const ResultOffsets &offsets, const Fn &fn)
static GSpan evaluated_attribute_if_necessary(const GVArray &src, const CurvesGeometry &curves, const std::array< int, CURVE_TYPES_NUM > &type_counts, Vector< std::byte > &buffer)
static void copy_curve_domain_attribute_to_mesh(const ResultOffsets &mesh_offsets, const Span< int > curve_indices, const eAttrDomain dst_domain, const GVArray &src, GMutableSpan dst)
static ResultOffsets calculate_result_offsets(const CurvesInfo &info, const bool fill_caps)
static void copy_profile_point_data_to_mesh_verts(const Span< T > src, const int main_point_num, MutableSpan< T > dst)
static bool should_add_attribute_to_mesh(const AttributeAccessor &curve_attributes, const AttributeAccessor &mesh_attributes, const AttributeIDRef &id)
static void copy_indices_to_offset_ranges(const VArray< T > &src, const Span< int > curve_indices, const Span< int > mesh_offsets, MutableSpan< T > dst)
static void copy_main_point_data_to_mesh_edges(const Span< T > src, const int profile_point_num, const int main_segment_num, const int profile_segment_num, MutableSpan< T > dst)
static void fill_mesh_positions(const int main_point_num, const int profile_point_num, const Span< float3 > main_positions, const Span< float3 > profile_positions, const Span< float3 > tangents, const Span< float3 > normals, const Span< float > radii, MutableSpan< MVert > mesh_positions)
AttributeAccessor mesh_attributes(const Mesh &mesh)
MutableAttributeAccessor mesh_attributes_for_write(Mesh &mesh)
static void copy_profile_point_data_to_mesh_faces(const Span< T > src, const int main_segment_num, const int profile_segment_num, MutableSpan< T > dst)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
void devirtualize_varray(const VArray< T > &varray, const Func &func, bool enable=true)
MutableSpan< float > radii
MutableSpan< float3 > tangents
MutableSpan< float3 > normals
IndexRange profile_points
const CurvesGeometry & profile
VArraySpan< bool > profile_cyclic
const CurvesGeometry & main
VArraySpan< bool > main_cyclic
Array< int > main_indices
Array< int > profile_indices
void apply_scale(const float scale)
static float4x4 from_normalized_axis_data(const float3 location, const float3 forward, const float3 up)