Nodes Splines: Apply tilt to normal evaluation

This patch makes the spline tilts (interpolated to the evaluated points)
affect the evaluated normals, allowing manual control of the rotation of
each profile in the curve to mesh node.

The method is based on Animation Nodes code, which keeps the data in
direction vector form, and rotates around the tangent vector.

Differential Revision: https://developer.blender.org/D11152
This commit is contained in:
Hans Goudey 2021-05-04 17:35:48 -05:00
parent 1f5710326f
commit d08cc63e2f
Notes: blender-bot 2023-02-14 07:36:17 +01:00
Referenced by issue #101629, bpy.ops.object.duplicates_make_real() duplicates curve objects with geometry
1 changed files with 25 additions and 3 deletions

View File

@ -17,6 +17,8 @@
#include "BLI_array.hh"
#include "BLI_span.hh"
#include "FN_generic_virtual_array.hh"
#include "BKE_spline.hh"
using blender::float3;
@ -183,6 +185,20 @@ Span<float3> Spline::evaluated_tangents() const
return evaluated_tangents_cache_;
}
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 * float3::dot(direction, axis);
const float3 diff = direction - axis_scaled;
const float3 cross = float3::cross(axis, diff);
return axis_scaled + diff * std::cos(angle) + cross * std::sin(angle);
}
static void calculate_normals_z_up(Span<float3> tangents, MutableSpan<float3> normals)
{
for (const int i : normals.index_range()) {
@ -193,8 +209,6 @@ static void calculate_normals_z_up(Span<float3> tangents, MutableSpan<float3> no
/**
* Return non-owning access to the direction vectors perpendicular to the tangents at every
* evaluated point. The method used to generate the normal vectors depends on Spline.normal_mode.
*
* TODO: Support changing the normal based on tilts.
*/
Span<float3> Spline::evaluated_normals() const
{
@ -211,9 +225,17 @@ Span<float3> Spline::evaluated_normals() const
evaluated_normals_cache_.resize(eval_size);
Span<float3> tangents = evaluated_tangents();
MutableSpan<float3> normals = evaluated_normals_cache_;
/* Only Z up normals are supported at the moment. */
calculate_normals_z_up(tangents, evaluated_normals_cache_);
calculate_normals_z_up(tangents, normals);
/* Rotate the generated normals with the interpolated tilt data. */
blender::fn::GVArray_Typed<float> tilts{
this->interpolate_to_evaluated_points(blender::fn::GVArray_For_Span(this->tilts()))};
for (const int i : normals.index_range()) {
normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]);
}
normal_cache_dirty_ = false;
return evaluated_normals_cache_;