Blender V4.3
BKE_curves.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
11
12#include "BLI_bounds_types.hh"
15#include "BLI_index_mask_fwd.hh"
19#include "BLI_offset_indices.hh"
20#include "BLI_shared_cache.hh"
21#include "BLI_span.hh"
22#include "BLI_vector.hh"
24
25#include "BKE_attribute_math.hh"
26#include "BKE_curves.h"
27
28struct BlendDataReader;
29struct BlendWriter;
30struct MDeformVert;
31namespace blender::bke {
34enum class AttrDomain : int8_t;
35} // namespace blender::bke
36namespace blender::bke::bake {
38}
39
40namespace blender::bke {
41
42namespace curves::nurbs {
43
63
64} // namespace curves::nurbs
65
129
136 public:
143 CurvesGeometry(const CurvesGeometry &other);
148
149 /* --------------------------------------------------------------------
150 * Accessors.
151 */
152
156 int points_num() const;
160 int curves_num() const;
161 IndexRange points_range() const;
162 IndexRange curves_range() const;
163
170 Span<int> offsets() const;
172
177
186 void fill_curve_types(CurveType type);
190 void update_curve_types();
191
192 bool has_curve_with_type(CurveType type) const;
195 bool is_single_type(CurveType type) const;
197 const std::array<int, CURVE_TYPES_NUM> &curve_type_counts() const;
203 const IndexMask &selection,
204 IndexMaskMemory &memory) const;
205
207
208 Span<float3> positions() const;
210
212 VArray<bool> cyclic() const;
215
220 VArray<int> resolution() const;
223
228 VArray<float> tilt() const;
230
237
245
256
263
270
276
282
289
293 std::optional<Bounds<float3>> bounds_min_max() const;
294
295 void count_memory(MemoryCounter &memory) const;
296
297 private:
298 /* --------------------------------------------------------------------
299 * Evaluation.
300 */
301
302 public:
307 int evaluated_points_num() const;
308
313
319 Span<int> bezier_evaluated_offsets_for_curve(int curve_index) const;
320
324
334 Span<float> evaluated_lengths_for_curve(int curve_index, bool cyclic) const;
335 float evaluated_length_total_for_curve(int curve_index, bool cyclic) const;
336
338 void ensure_evaluated_lengths() const;
339
341
349 void interpolate_to_evaluated(int curve_index, GSpan src, GMutableSpan dst) const;
353 void interpolate_to_evaluated(GSpan src, GMutableSpan dst) const;
354
355 private:
359 void ensure_nurbs_basis_cache() const;
360
362 IndexRange lengths_range_for_curve(int curve_index, bool cyclic) const;
363
364 /* --------------------------------------------------------------------
365 * Operations.
366 */
367
368 public:
375 void resize(int points_num, int curves_num);
376
385 void tag_normals_changed();
390 void tag_radii_changed();
391
392 void translate(const float3 &translation);
393 void transform(const float4x4 &matrix);
394
396
397 void remove_points(const IndexMask &points_to_delete, const AttributeFilter &attribute_filter);
398 void remove_curves(const IndexMask &curves_to_delete, const AttributeFilter &attribute_filter);
399
404 void reverse_curves(const IndexMask &curves_to_reverse);
405
410
413
414 /* --------------------------------------------------------------------
415 * Attributes.
416 */
417
418 GVArray adapt_domain(const GVArray &varray, AttrDomain from, AttrDomain to) const;
419 template<typename T>
420 VArray<T> adapt_domain(const VArray<T> &varray, AttrDomain from, AttrDomain to) const
421 {
422 return this->adapt_domain(GVArray(varray), from, to).typed<T>();
423 }
424
425 /* --------------------------------------------------------------------
426 * File Read/Write.
427 */
428 void blend_read(BlendDataReader &reader);
433 /* The point custom data layers to be written. */
435 /* The curve custom data layers to be written. */
437 };
438
443 void blend_write(BlendWriter &writer, ID &id, const BlendWriteData &write_data);
444};
445
446static_assert(sizeof(blender::bke::CurvesGeometry) == sizeof(::CurvesGeometry));
447
453 public:
467 std::optional<Array<float3x3>> deform_mats;
468
470
471 std::optional<Span<float3>> positions() const;
472 std::optional<MutableSpan<float3>> positions_for_write();
473
478 bool is_valid() const;
479};
480
482
483namespace curves {
484
485/* -------------------------------------------------------------------- */
488
493inline int segments_num(const int points_num, const bool cyclic)
494{
495 BLI_assert(points_num > 0);
496 return (cyclic && points_num > 1) ? points_num : points_num - 1;
497}
498
500{
501 BLI_assert(std::abs(v.x + v.y + v.z - 1.0f) < 0.00001f);
502 return {v.x, v.y};
503}
504
506{
507 return {v.x, v.y, 1.0f - v.x - v.y};
508}
509
516inline IndexRange per_curve_point_offsets_range(const IndexRange points, const int curve_index)
517{
518 return {curve_index + points.start(), points.size() + 1};
519}
520
522
523/* -------------------------------------------------------------------- */
526
527namespace poly {
528
535void calculate_tangents(Span<float3> positions, bool is_cyclic, MutableSpan<float3> tangents);
536
543
549
550} // namespace poly
551
553
554/* -------------------------------------------------------------------- */
557
558namespace bezier {
559
564bool segment_is_vector(const HandleType left, const HandleType right);
565bool segment_is_vector(const int8_t left, const int8_t right);
566bool segment_is_vector(Span<int8_t> handle_types_left,
567 Span<int8_t> handle_types_right,
568 int segment_index);
569
578bool has_vector_handles(int num_curve_points, int64_t evaluated_size, bool cyclic, int resolution);
579
584bool last_cyclic_segment_is_vector(Span<int8_t> handle_types_left,
585 Span<int8_t> handle_types_right);
586
592bool point_is_sharp(Span<int8_t> handle_types_left, Span<int8_t> handle_types_right, int index);
593
603void calculate_evaluated_offsets(Span<int8_t> handle_types_left,
604 Span<int8_t> handle_types_right,
605 bool cyclic,
606 int resolution,
607 MutableSpan<int> evaluated_offsets);
608
617
636Insertion insert(const float3 &point_prev,
637 const float3 &handle_prev,
638 const float3 &handle_next,
639 const float3 &point_next,
640 float parameter);
641
648float3 calculate_vector_handle(const float3 &point, const float3 &next_point);
649
656void calculate_auto_handles(bool cyclic,
657 Span<int8_t> types_left,
658 Span<int8_t> types_right,
659 Span<float3> positions,
660 MutableSpan<float3> positions_left,
661 MutableSpan<float3> positions_right);
662
670void set_handle_position(const float3 &position,
671 HandleType type,
672 HandleType type_other,
673 const float3 &new_handle,
674 float3 &handle,
675 float3 &handle_other);
676
683template<typename T>
685 const T &point_0, const T &point_1, const T &point_2, const T &point_3, MutableSpan<T> result);
686
697 Span<float3> handles_left,
698 Span<float3> handles_right,
699 OffsetIndices<int> evaluated_offsets,
700 MutableSpan<float3> evaluated_positions);
701
707void interpolate_to_evaluated(GSpan src, OffsetIndices<int> evaluated_offsets, GMutableSpan dst);
708
709} // namespace bezier
710
712
713/* -------------------------------------------------------------------- */
716
717namespace catmull_rom {
718
724int calculate_evaluated_num(int points_num, bool cyclic, int resolution);
725
730void interpolate_to_evaluated(GSpan src, bool cyclic, int resolution, GMutableSpan dst);
731
736void interpolate_to_evaluated(const GSpan src,
737 const bool cyclic,
738 const OffsetIndices<int> evaluated_offsets,
739 GMutableSpan dst);
740
741float4 calculate_basis(const float parameter);
742
749template<typename T>
750T interpolate(const T &a, const T &b, const T &c, const T &d, const float parameter)
751{
752 BLI_assert(0.0f <= parameter && parameter <= 1.0f);
753 const float4 weights = calculate_basis(parameter);
755 /* Save multiplications by adjusting weights after mix. */
756 return 0.5f * attribute_math::mix4<T>(weights, a, b, c, d);
757 }
758 else {
759 return attribute_math::mix4<T>(weights * 0.5f, a, b, c, d);
760 }
761}
762
763} // namespace catmull_rom
764
766
767/* -------------------------------------------------------------------- */
770
771namespace nurbs {
772
776bool check_valid_num_and_order(int points_num, int8_t order, bool cyclic, KnotsMode knots_mode);
777
787 int points_num, int8_t order, bool cyclic, int resolution, KnotsMode knots_mode);
788
794int knots_num(int points_num, int8_t order, bool cyclic);
795
804void calculate_knots(
805 int points_num, KnotsMode mode, int8_t order, bool cyclic, MutableSpan<float> knots);
806
813void calculate_basis_cache(int points_num,
814 int evaluated_num,
815 int8_t order,
816 bool cyclic,
817 Span<float> knots,
818 BasisCache &basis_cache);
819
828void interpolate_to_evaluated(const BasisCache &basis_cache,
829 int8_t order,
830 Span<float> control_weights,
831 GSpan src,
832 GMutableSpan dst);
833
834} // namespace nurbs
835
837
838} // namespace curves
839
840Curves *curves_new_nomain(int points_num, int curves_num);
842
846Curves *curves_new_nomain_single(int points_num, CurveType type);
847
852void curves_copy_parameters(const Curves &src, Curves &dst);
853
855 const IndexMask &points_to_copy,
856 const AttributeFilter &attribute_filter);
857
859 const IndexMask &curves_to_copy,
860 const AttributeFilter &attribute_filter);
861
862CurvesGeometry curves_new_no_attributes(int point_num, int curve_num);
863
864std::array<int, CURVE_TYPES_NUM> calculate_type_counts(const VArray<int8_t> &types);
865
866/* -------------------------------------------------------------------- */
869
870inline int CurvesGeometry::points_num() const
871{
872 return this->point_num;
873}
874inline int CurvesGeometry::curves_num() const
875{
876 return this->curve_num;
877}
878inline IndexRange CurvesGeometry::points_range() const
879{
880 return IndexRange(this->points_num());
881}
882inline IndexRange CurvesGeometry::curves_range() const
883{
884 return IndexRange(this->curves_num());
885}
886
887inline bool CurvesGeometry::is_single_type(const CurveType type) const
888{
889 return this->curve_type_counts()[type] == this->curves_num();
890}
891
892inline bool CurvesGeometry::has_curve_with_type(const CurveType type) const
893{
894 return this->curve_type_counts()[type] > 0;
895}
896
897inline bool CurvesGeometry::has_curve_with_type(const Span<CurveType> types) const
898{
899 return std::any_of(
900 types.begin(), types.end(), [&](CurveType type) { return this->has_curve_with_type(type); });
901}
902
903inline const std::array<int, CURVE_TYPES_NUM> &CurvesGeometry::curve_type_counts() const
904{
905#ifndef NDEBUG
906
907 if (this->runtime->check_type_counts) {
908 const std::array<int, CURVE_TYPES_NUM> actual_type_counts = calculate_type_counts(
909 this->curve_types());
910 BLI_assert(this->runtime->type_counts == actual_type_counts);
911 this->runtime->check_type_counts = false;
912 }
913#endif
914 return this->runtime->type_counts;
915}
916
917inline OffsetIndices<int> CurvesGeometry::points_by_curve() const
918{
919 return OffsetIndices<int>({this->curve_offsets, this->curve_num + 1},
921}
922
923inline int CurvesGeometry::evaluated_points_num() const
924{
925 /* This could avoid calculating offsets in the future in simple circumstances. */
926 return this->evaluated_points_by_curve().total_size();
927}
928
929inline Span<int> CurvesGeometry::bezier_evaluated_offsets_for_curve(const int curve_index) const
930{
932 const IndexRange points = points_by_curve[curve_index];
933 const IndexRange range = curves::per_curve_point_offsets_range(points, curve_index);
934 const Span<int> offsets = this->runtime->evaluated_offsets_cache.data().all_bezier_offsets;
935 return offsets.slice(range);
936}
937
938inline IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index,
939 const bool cyclic) const
940{
941 BLI_assert(cyclic == this->cyclic()[curve_index]);
942 const IndexRange points = this->evaluated_points_by_curve()[curve_index];
943 const int start = points.start() + curve_index;
944 return {start, curves::segments_num(points.size(), cyclic)};
945}
946
947inline Span<float> CurvesGeometry::evaluated_lengths_for_curve(const int curve_index,
948 const bool cyclic) const
949{
950 const IndexRange range = this->lengths_range_for_curve(curve_index, cyclic);
951 return this->runtime->evaluated_length_cache.data().as_span().slice(range);
952}
953
954inline float CurvesGeometry::evaluated_length_total_for_curve(const int curve_index,
955 const bool cyclic) const
956{
957 const Span<float> lengths = this->evaluated_lengths_for_curve(curve_index, cyclic);
958 if (lengths.is_empty()) {
959 return 0.0f;
960 }
961 return lengths.last();
962}
963
965
966namespace curves {
967
968/* -------------------------------------------------------------------- */
971
972namespace bezier {
973
974inline bool point_is_sharp(const Span<int8_t> handle_types_left,
975 const Span<int8_t> handle_types_right,
976 const int index)
977{
978 return ELEM(handle_types_left[index], BEZIER_HANDLE_VECTOR, BEZIER_HANDLE_FREE) ||
979 ELEM(handle_types_right[index], BEZIER_HANDLE_VECTOR, BEZIER_HANDLE_FREE);
980}
981
982inline bool segment_is_vector(const HandleType left, const HandleType right)
983{
984 return left == BEZIER_HANDLE_VECTOR && right == BEZIER_HANDLE_VECTOR;
985}
986
987inline bool segment_is_vector(const int8_t left, const int8_t right)
988{
990}
991
992inline bool has_vector_handles(const int num_curve_points,
993 const int64_t evaluated_size,
994 const bool cyclic,
995 const int resolution)
996{
997 return evaluated_size - !cyclic != int64_t(segments_num(num_curve_points, cyclic)) * resolution;
998}
999
1000inline float3 calculate_vector_handle(const float3 &point, const float3 &next_point)
1001{
1002 return math::interpolate(point, next_point, 1.0f / 3.0f);
1003}
1004
1005} // namespace bezier
1006
1008
1009} // namespace curves
1010
1023
1024} // namespace blender::bke
1025
1026inline blender::bke::CurvesGeometry &CurvesGeometry::wrap()
1027{
1028 return *reinterpret_cast<blender::bke::CurvesGeometry *>(this);
1029}
1030inline const blender::bke::CurvesGeometry &CurvesGeometry::wrap() const
1031{
1032 return *reinterpret_cast<const blender::bke::CurvesGeometry *>(this);
1033}
Low-level operations for curves that cannot be defined in the C++ header yet.
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
CurveType
HandleType
@ BEZIER_HANDLE_FREE
@ BEZIER_HANDLE_VECTOR
KnotsMode
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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 point
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr int64_t size() const
constexpr int64_t start() const
constexpr const T & last(const int64_t n=0) const
Definition BLI_span.hh:326
constexpr bool is_empty() const
Definition BLI_span.hh:261
std::optional< MutableSpan< float3 > > positions_for_write()
ImplicitSharingPtrAndData positions_data
std::optional< Span< float3 > > positions() const
CurvesEditHints(const Curves &curves_id_orig)
std::optional< Array< float3x3 > > deform_mats
SharedCache< Vector< curves::nurbs::BasisCache > > nurbs_basis_cache
Definition BKE_curves.hh:90
SharedCache< Vector< float > > evaluated_length_cache
SharedCache< Vector< float3 > > evaluated_tangent_cache
SharedCache< EvaluatedOffsets > evaluated_offsets_cache
Definition BKE_curves.hh:88
SharedCache< Vector< float3 > > evaluated_normal_cache
std::unique_ptr< bake::BakeMaterialsList > bake_materials
SharedCache< Bounds< float3 > > bounds_cache
SharedCache< Vector< float3 > > evaluated_position_cache
Definition BKE_curves.hh:96
const ImplicitSharingInfo * curve_offsets_sharing_info
Definition BKE_curves.hh:72
std::array< int, CURVE_TYPES_NUM > type_counts
Definition BKE_curves.hh:78
VArray< int8_t > handle_types_left() const
void reverse_curves(const IndexMask &curves_to_reverse)
void blend_read(BlendDataReader &reader)
MutableSpan< float3 > positions_for_write()
void translate(const float3 &translation)
Array< int > point_to_curve_map() const
MutableSpan< MDeformVert > deform_verts_for_write()
OffsetIndices< int > points_by_curve() const
VArray< int8_t > normal_mode() const
MutableSpan< int8_t > handle_types_right_for_write()
VArray< int8_t > handle_types_right() const
void ensure_can_interpolate_to_evaluated() const
IndexRange curves_range() const
MutableSpan< int8_t > curve_types_for_write()
MutableSpan< int > resolution_for_write()
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
MutableSpan< float3 > handle_positions_left_for_write()
MutableAttributeAccessor attributes_for_write()
MutableSpan< float3 > handle_positions_right_for_write()
MutableSpan< int8_t > nurbs_knots_modes_for_write()
Span< float > evaluated_lengths_for_curve(int curve_index, bool cyclic) const
MutableSpan< float > tilt_for_write()
VArray< float > tilt() const
void blend_write(BlendWriter &writer, ID &id, const BlendWriteData &write_data)
Span< float3 > evaluated_tangents() const
Span< MDeformVert > deform_verts() const
MutableSpan< int8_t > nurbs_orders_for_write()
Span< float > nurbs_weights() const
MutableSpan< float2 > surface_uv_coords_for_write()
Span< float3 > handle_positions_left() const
VArray< int > resolution() const
Span< int > bezier_evaluated_offsets_for_curve(int curve_index) const
void interpolate_to_evaluated(int curve_index, GSpan src, GMutableSpan dst) const
IndexRange points_range() const
VArray< int8_t > nurbs_knots_modes() const
Span< float3 > evaluated_normals() const
std::optional< Bounds< float3 > > bounds_min_max() const
Span< float3 > positions() const
OffsetIndices< int > evaluated_points_by_curve() const
bool has_curve_with_type(CurveType type) const
MutableSpan< float > nurbs_weights_for_write()
GVArray adapt_domain(const GVArray &varray, AttrDomain from, AttrDomain to) const
void resize(int points_num, int curves_num)
Span< float3 > handle_positions_right() const
void remove_curves(const IndexMask &curves_to_delete, const AttributeFilter &attribute_filter)
MutableSpan< int8_t > normal_mode_for_write()
VArray< T > adapt_domain(const VArray< T > &varray, AttrDomain from, AttrDomain to) const
void fill_curve_types(CurveType type)
float evaluated_length_total_for_curve(int curve_index, bool cyclic) const
IndexMask indices_for_curve_type(CurveType type, IndexMaskMemory &memory) const
void count_memory(MemoryCounter &memory) const
bool is_single_type(CurveType type) const
MutableSpan< int > offsets_for_write()
Span< float2 > surface_uv_coords() const
void remove_points(const IndexMask &points_to_delete, const AttributeFilter &attribute_filter)
void transform(const float4x4 &matrix)
Span< float3 > evaluated_positions() const
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
CurvesGeometry & operator=(const CurvesGeometry &other)
MutableSpan< bool > cyclic_for_write()
VArray< int8_t > nurbs_orders() const
MutableSpan< int8_t > handle_types_left_for_write()
local_group_size(16, 16) .push_constant(Type b
static bool is_cyclic(const Nurb *nu)
static float normals[][3]
static char ** types
Definition makesdna.cc:71
static int left
#define T
T mix4(const float4 &weights, const T &v0, const T &v1, const T &v2, const T &v3)
Insertion insert(const float3 &point_prev, const float3 &handle_prev, const float3 &handle_next, const float3 &point_next, float parameter)
bool segment_is_vector(const HandleType left, const HandleType right)
bool point_is_sharp(Span< int8_t > handle_types_left, Span< int8_t > handle_types_right, int index)
void calculate_auto_handles(bool cyclic, Span< int8_t > types_left, Span< int8_t > types_right, Span< float3 > positions, MutableSpan< float3 > positions_left, MutableSpan< float3 > positions_right)
void calculate_evaluated_offsets(Span< int8_t > handle_types_left, Span< int8_t > handle_types_right, bool cyclic, int resolution, MutableSpan< int > evaluated_offsets)
float3 calculate_vector_handle(const float3 &point, const float3 &next_point)
bool has_vector_handles(int num_curve_points, int64_t evaluated_size, bool cyclic, int resolution)
bool last_cyclic_segment_is_vector(Span< int8_t > handle_types_left, Span< int8_t > handle_types_right)
void evaluate_segment(const T &point_0, const T &point_1, const T &point_2, const T &point_3, MutableSpan< T > result)
void calculate_evaluated_positions(Span< float3 > positions, Span< float3 > handles_left, Span< float3 > handles_right, OffsetIndices< int > evaluated_offsets, MutableSpan< float3 > evaluated_positions)
void interpolate_to_evaluated(GSpan src, OffsetIndices< int > evaluated_offsets, GMutableSpan dst)
void set_handle_position(const float3 &position, HandleType type, HandleType type_other, const float3 &new_handle, float3 &handle, float3 &handle_other)
T interpolate(const T &a, const T &b, const T &c, const T &d, const float parameter)
int calculate_evaluated_num(int points_num, bool cyclic, int resolution)
float4 calculate_basis(const float parameter)
void interpolate_to_evaluated(GSpan src, bool cyclic, int resolution, GMutableSpan dst)
int calculate_evaluated_num(int points_num, int8_t order, bool cyclic, int resolution, KnotsMode knots_mode)
bool check_valid_num_and_order(int points_num, int8_t order, bool cyclic, KnotsMode knots_mode)
void calculate_knots(int points_num, KnotsMode mode, int8_t order, bool cyclic, MutableSpan< float > knots)
void calculate_basis_cache(int points_num, int evaluated_num, int8_t order, bool cyclic, Span< float > knots, BasisCache &basis_cache)
int knots_num(int points_num, int8_t order, bool cyclic)
void interpolate_to_evaluated(const BasisCache &basis_cache, int8_t order, Span< float > control_weights, GSpan src, GMutableSpan dst)
void calculate_normals_z_up(Span< float3 > tangents, MutableSpan< float3 > normals)
void calculate_normals_minimum(Span< float3 > tangents, bool cyclic, MutableSpan< float3 > normals)
void calculate_tangents(Span< float3 > positions, bool is_cyclic, MutableSpan< float3 > tangents)
Definition curve_poly.cc:43
IndexRange per_curve_point_offsets_range(const IndexRange points, const int curve_index)
float3 decode_surface_bary_coord(const float2 &v)
int segments_num(const int points_num, const bool cyclic)
float2 encode_surface_bary_coord(const float3 &v)
CurvesGeometry curves_copy_curve_selection(const CurvesGeometry &curves, const IndexMask &curves_to_copy, const AttributeFilter &attribute_filter)
CurvesGeometry curves_copy_point_selection(const CurvesGeometry &curves, const IndexMask &points_to_copy, const AttributeFilter &attribute_filter)
void curves_copy_parameters(const Curves &src, Curves &dst)
CurvesGeometry curves_new_no_attributes(int point_num, int curve_num)
std::array< int, CURVE_TYPES_NUM > calculate_type_counts(const VArray< int8_t > &types)
Curves * curves_new_nomain_single(int points_num, CurveType type)
Curves * curves_new_nomain(int points_num, int curves_num)
void curves_normals_point_domain_calc(const CurvesGeometry &curves, MutableSpan< float3 > normals)
T interpolate(const T &a, const T &b, const FactorT &t)
constexpr bool is_same_any_v
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
VecBase< float, 3 > float3
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
__int64 int64_t
Definition stdint.h:89
signed char int8_t
Definition stdint.h:75
CurvesGeometryRuntimeHandle * runtime
Definition DNA_ID.h:413
Vector< CustomDataLayer, 16 > curve_layers
Vector< CustomDataLayer, 16 > point_layers