solstice-anim

Geometry animation library of the solstice app
git clone git://git.meso-star.com/solstice-anim.git
Log | Files | Refs | README | LICENSE

commit 3317ccbcce83638088ec3fae64ab79d22154cb9f
parent 36a61109cd1a1077b7f2941cf92c781fa5cf1b16
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue, 25 Oct 2016 14:38:36 +0200

Add an heuristic to speed the pointing algorithm up.

Diffstat:
Msrc/sanim_node.c | 56+++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 53 insertions(+), 3 deletions(-)

diff --git a/src/sanim_node.c b/src/sanim_node.c @@ -297,6 +297,8 @@ pivot_solve_single_axis_line double* const local_target_2D = local_target + 1; struct pivot_data* pivot_data; double angle, previous_angle, delta; + double sign_dA, prev_sign_dA; + double kA; double d1, d2; int cpt = 0; ASSERT(node && node->data && in_dir); @@ -339,6 +341,8 @@ pivot_solve_single_axis_line } angle = 0; + prev_sign_dA = 0; + kA = 0.9; do { double pivot[4]; /* compute 2D normal after rotation */ @@ -357,13 +361,28 @@ pivot_solve_single_axis_line previous_angle = angle; compute_single_axis_angle(ref_normal_2D, rotated_n_2D, &angle); + if (fabs(previous_angle - angle) > PI) { + previous_angle = (angle > 0) ? 2 * PI : -2 * PI; + } delta = previous_angle - angle; if (fabs(delta) < 1e-10 || ++cpt > 100) break; - d22_rotation(pivot, angle); + if (d2) { + /* only if ref_point is not the rotation point + * the heuristic is to amortize algorithm's oscillations */ + sign_dA = sign(previous_angle - angle); + if (prev_sign_dA != sign_dA) + kA *= 0.9; + else + kA *= 1 / 0.9; + angle = previous_angle + kA * (angle - previous_angle); + prev_sign_dA = sign_dA; + } + /* update ref_point */ + d22_rotation(pivot, angle); d22_muld2(ref_point_2D, pivot, pivot_data->pivot.data.pivot1.ref_point + 1); /* no d3_add(ref_point, ref_point, pivot + 9) as pivot has no offset to add */ } while (1); @@ -502,6 +521,9 @@ pivot_solve_two_axis_point double mat[12], inv[9]; double local_in[3], rotated_n[3], local_out[3], local_target[3], ref_point[3]; double angleX, angleZ, previous_angleX, previous_angleZ, delta; + double sign_dX, sign_dZ, prev_sign_dX, prev_sign_dZ; + double kX, kZ; + double d1, d2; struct pivot_data* pivot_data; int cpt = 0; ASSERT(node && node->data && in_dir); @@ -530,12 +552,16 @@ pivot_solve_two_axis_point } /* check if in, target_point and ref_point are compatible */ - if (d3_dot(local_target, local_target) <= d3_dot(ref_point, ref_point)) { + d1 = d3_dot(local_target, local_target); + d2 = d3_dot(ref_point, ref_point); + if (d1 <= d2) { /* target in the pivot */ return RES_BAD_ARG; } angleX = angleZ = 0; + prev_sign_dX = prev_sign_dZ = 0; + kX = kZ = 0.9; do { double pivot[12]; /* compute rotated_n */ @@ -552,11 +578,35 @@ pivot_solve_two_axis_point previous_angleX = angleX; previous_angleZ = angleZ; compute_two_axis_angles(rotated_n, &angleX, &angleZ); - + if (fabs(previous_angleX - angleX) > PI) { + previous_angleX = (angleX > 0) ? 2 * PI : -2 * PI; + } + if (fabs(previous_angleZ - angleZ) > PI) { + previous_angleZ += (angleZ > 0) ? 2 * PI : -2 * PI; + } delta = MMAX(fabs(previous_angleX - angleX), fabs(previous_angleZ - angleZ)); if (delta < 1e-10 || ++cpt > 100) break; + if (d2) { + /* only if ref_point is not the rotation point + * the heuristic is to amortize algorithm's oscillations */ + sign_dX = sign(previous_angleX - angleX); + sign_dZ = sign(previous_angleZ - angleZ); + if (prev_sign_dX != sign_dX) + kX *= 0.9; + else + kX *= 1 / 0.9; + angleX = previous_angleX + kX * (angleX - previous_angleX); + if (prev_sign_dZ != sign_dZ) + kZ *= 0.9; + else + kZ *= 1 / 0.9; + angleZ = previous_angleZ + kZ * (angleZ - previous_angleZ); + prev_sign_dX = sign_dX; + prev_sign_dZ = sign_dZ; + } + get_ZXpivot_transform( angleZ, angleX, pivot_data->pivot.data.pivot2.spacing, pivot); /* update ref_point */