21 bool &r_used_fallback)
23 const float epsilon = 1e-6f;
26 if (prev_equal && next_equal) {
27 r_used_fallback =
true;
28 return {0.0f, 0.0f, 0.0f};
49 if (positions.size() == 1) {
54 bool used_fallback =
false;
56 for (
const int i :
IndexRange(1, positions.size() - 2)) {
58 positions[i - 1], positions[i], positions[i + 1], used_fallback);
62 const float3 &second_to_last = positions[positions.size() - 2];
63 const float3 &last = positions.last();
64 const float3 &first = positions.first();
65 const float3 &second = positions[1];
70 const float epsilon = 1e-6f;
72 tangents.
first() = {0.0f, 0.0f, 0.0f};
79 tangents.
last() = {0.0f, 0.0f, 0.0f};
92 int first_valid_tangent_index = -1;
95 first_valid_tangent_index = i;
99 if (first_valid_tangent_index == -1) {
102 const float3 up_vector{0.0f, 0.0f, 1.0f};
103 tangents.
fill(up_vector);
106 const float3 &first_valid_tangent = tangents[first_valid_tangent_index];
109 tangents.
take_front(first_valid_tangent_index).
fill(first_valid_tangent);
112 float3 &tangent = tangents[i];
114 const float3 &prev_tangent = tangents[i - 1];
115 tangent = prev_tangent;
126 const float epsilon = 1e-4f;
127 for (
const int i : normals.index_range()) {
128 const float3 &tangent = tangents[i];
129 if (std::abs(tangent.x) + std::abs(tangent.y) < epsilon) {
130 normals[i] = {1.0f, 0.0f, 0.0f};
142 const float3 &last_tangent,
143 const float3 ¤t_tangent)
167 if (normals.is_empty()) {
171 const float epsilon = 1e-4f;
176 normals.first() = {1.0f, 0.0f, 0.0f};
183 for (
const int i :
IndexRange(1, normals.size() - 1)) {
194 normals.last(), tangents.
last(), tangents.
first());
196 normals.first(), uncorrected_last_normal, tangents.
first());
197 if (correction_angle >
M_PI) {
198 correction_angle = correction_angle - 2 *
M_PI;
202 const float angle_step = correction_angle / normals.size();
203 for (
const int i : normals.index_range()) {
204 const float3 axis = tangents[i];
208 const float angle = angle_step * i;
Low-level operations for curves.
float angle_signed_on_axis_v3v3_v3(const float v1[3], const float v2[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT
float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
constexpr IndexRange drop_front(int64_t n) const
constexpr int64_t size() const
constexpr void fill(const T &value) const
constexpr T & first() const
constexpr IndexRange index_range() const
constexpr MutableSpan take_front(const int64_t n) const
constexpr T & last(const int64_t n=0) const
constexpr const T & first() const
constexpr int64_t size() const
constexpr const T & last(const int64_t n=0) const
static bool is_cyclic(const Nurb *nu)
ccl_device_inline float2 fabs(const float2 a)
void calculate_normals_z_up(Span< float3 > tangents, MutableSpan< float3 > normals)
static float3 direction_bisect(const float3 &prev, const float3 &middle, const float3 &next, bool &r_used_fallback)
void calculate_normals_minimum(Span< float3 > tangents, bool cyclic, MutableSpan< float3 > normals)
static float3 calculate_next_normal(const float3 &last_normal, const float3 &last_tangent, const float3 ¤t_tangent)
void calculate_tangents(Span< float3 > positions, bool is_cyclic, MutableSpan< float3 > tangents)
float3 rotate_direction_around_axis(const float3 &direction, const float3 &axis, float angle)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
bool almost_equal_relative(const VecBase< T, Size > &a, const VecBase< T, Size > &b, const T &epsilon_factor)
VecBase< float, 3 > float3