Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/curve_poly.cc
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| /** \file | /** \file | ||||
| * \ingroup bke | * \ingroup bke | ||||
| */ | */ | ||||
| #include <algorithm> | #include <algorithm> | ||||
| #include "BLI_math_vector.h" | #include "BLI_math_rotation.hh" | ||||
| #include "BLI_math_vector.hh" | #include "BLI_math_vector.hh" | ||||
| #include "BKE_curves.hh" | #include "BKE_curves.hh" | ||||
| namespace blender::bke::curves::poly { | namespace blender::bke::curves::poly { | ||||
| static float3 direction_bisect(const float3 &prev, const float3 &middle, const float3 &next) | static float3 direction_bisect(const float3 &prev, const float3 &middle, const float3 &next) | ||||
| { | { | ||||
| Show All 31 Lines | if (is_cyclic) { | ||||
| tangents.last() = direction_bisect(second_to_last, last, first); | tangents.last() = direction_bisect(second_to_last, last, first); | ||||
| } | } | ||||
| else { | else { | ||||
| tangents.first() = math::normalize(positions[1] - positions.first()); | tangents.first() = math::normalize(positions[1] - positions.first()); | ||||
| tangents.last() = math::normalize(positions.last() - positions[positions.size() - 2]); | tangents.last() = math::normalize(positions.last() - positions[positions.size() - 2]); | ||||
| } | } | ||||
| } | } | ||||
| static float3 rotate_direction_around_axis(const float3 &direction, | |||||
| const float3 &axis, | |||||
| const float angle) | |||||
| { | |||||
| BLI_ASSERT_UNIT_V3(direction); | |||||
| BLI_ASSERT_UNIT_V3(axis); | |||||
| const float3 axis_scaled = axis * math::dot(direction, axis); | |||||
| const float3 diff = direction - axis_scaled; | |||||
| const float3 cross = math::cross(axis, diff); | |||||
| return axis_scaled + diff * std::cos(angle) + cross * std::sin(angle); | |||||
| } | |||||
| void calculate_normals_z_up(const Span<float3> tangents, MutableSpan<float3> normals) | void calculate_normals_z_up(const Span<float3> tangents, MutableSpan<float3> normals) | ||||
| { | { | ||||
| BLI_assert(normals.size() == tangents.size()); | BLI_assert(normals.size() == tangents.size()); | ||||
| /* Same as in `vec_to_quat`. */ | /* Same as in `vec_to_quat`. */ | ||||
| const float epsilon = 1e-4f; | const float epsilon = 1e-4f; | ||||
| for (const int i : normals.index_range()) { | for (const int i : normals.index_range()) { | ||||
| const float3 &tangent = tangents[i]; | const float3 &tangent = tangents[i]; | ||||
| Show All 14 Lines | static float3 calculate_next_normal(const float3 &last_normal, | ||||
| const float3 ¤t_tangent) | const float3 ¤t_tangent) | ||||
| { | { | ||||
| if (math::is_zero(last_tangent) || math::is_zero(current_tangent)) { | if (math::is_zero(last_tangent) || math::is_zero(current_tangent)) { | ||||
| return last_normal; | return last_normal; | ||||
| } | } | ||||
| const float angle = angle_normalized_v3v3(last_tangent, current_tangent); | const float angle = angle_normalized_v3v3(last_tangent, current_tangent); | ||||
| if (angle != 0.0) { | if (angle != 0.0) { | ||||
| const float3 axis = math::normalize(math::cross(last_tangent, current_tangent)); | const float3 axis = math::normalize(math::cross(last_tangent, current_tangent)); | ||||
| return rotate_direction_around_axis(last_normal, axis, angle); | return math::rotate_direction_around_axis(last_normal, axis, angle); | ||||
| } | } | ||||
| return last_normal; | return last_normal; | ||||
| } | } | ||||
| void calculate_normals_minimum(const Span<float3> tangents, | void calculate_normals_minimum(const Span<float3> tangents, | ||||
| const bool cyclic, | const bool cyclic, | ||||
| MutableSpan<float3> normals) | MutableSpan<float3> normals) | ||||
| { | { | ||||
| Show All 32 Lines | void calculate_normals_minimum(const Span<float3> tangents, | ||||
| if (correction_angle > M_PI) { | if (correction_angle > M_PI) { | ||||
| correction_angle = correction_angle - 2 * M_PI; | correction_angle = correction_angle - 2 * M_PI; | ||||
| } | } | ||||
| /* Gradually apply correction by rotating all normals slightly. */ | /* Gradually apply correction by rotating all normals slightly. */ | ||||
| const float angle_step = correction_angle / normals.size(); | const float angle_step = correction_angle / normals.size(); | ||||
| for (const int i : normals.index_range()) { | for (const int i : normals.index_range()) { | ||||
| const float angle = angle_step * i; | const float angle = angle_step * i; | ||||
| normals[i] = rotate_direction_around_axis(normals[i], tangents[i], angle); | normals[i] = math::rotate_direction_around_axis(normals[i], tangents[i], angle); | ||||
| } | } | ||||
| } | } | ||||
| } // namespace blender::bke::curves::poly | } // namespace blender::bke::curves::poly | ||||