GteSlerpEstimate.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
11 
12 // The spherical linear interpolation (slerp) of unit-length quaternions
13 // q0 and q1 for t in [0,1] and theta in (0,pi) is
14 // slerp(t,q0,q1) = [sin((1-t)*theta)*q0 + sin(theta)*q1]/sin(theta)
15 // where theta is the angle between q0 and q1 [cos(theta) = Dot(q0,q1)].
16 // This function is a parameterization of the great spherical arc between
17 // q0 and q1 on the unit hypersphere. Moreover, the parameterization is
18 // one of normalized arclength--a particle traveling along the arc through
19 // time t does so with constant speed.
20 //
21 // Read the comments in GteChebyshevRatio.h regarding estimates for the
22 // ratio sin(t*theta)/sin(theta).
23 //
24 // When using slerp in animations involving sequences of quaternions, it is
25 // typical that the quaternions are preprocessed so that consecutive ones
26 // form an acute angle A in [0,pi/2]. Other preprocessing can help with
27 // performance. See the function comments in the SLERP class.
28 
29 namespace gte
30 {
31 
32 template <typename Real>
33 class SLERP
34 {
35 public:
36  // The angle between q0 and q1 is in [0,pi). There are no angle
37  // restrictions and nothing is precomputed.
38  template <int N>
39  inline static Quaternion<Real> Estimate(Real t,
40  Quaternion<Real> const& q0, Quaternion<Real> const& q1);
41 
42 
43  // The angle between q0 and q1 must be in [0,pi/2]. The suffix R is for
44  // 'Restricted'. The preprocessing code is
45  // Quaternion<Real> q[n]; // assuming initialized
46  // for (i0 = 0, i1 = 1; i1 < n; i0 = i1++)
47  // {
48  // cosA = Dot(q[i0], q[i1]);
49  // if (cosA < 0)
50  // {
51  // q[i1] = -q[i1]; // now Dot(q[i0], q[i]1) >= 0
52  // }
53  // }
54  template <int N>
55  inline static Quaternion<Real> EstimateR(Real t,
56  Quaternion<Real> const& q0, Quaternion<Real> const& q1);
57 
58 
59  // The angle between q0 and q1 must be in [0,pi/2]. The suffix R is for
60  // 'Restricted' and the suffix P is for 'Preprocessed'. The preprocessing
61  // code is
62  // Quaternion<Real> q[n]; // assuming initialized
63  // Real cosA[n-1], omcosA[n-1]; // to be precomputed
64  // for (i0 = 0, i1 = 1; i1 < n; i0 = i1++)
65  // {
66  // cs = Dot(q[i0], q[i1]);
67  // if (cosA[i0] < 0)
68  // {
69  // q[i1] = -q[i1];
70  // cs = -cs;
71  // }
72  // cosA[n-1] = cs; // for GeneralRP
73  // omcosA[i0] = 1 - cs; // for EstimateRP
74  // }
75  template <int N>
76  inline static Quaternion<Real> EstimateRP(Real t,
77  Quaternion<Real> const& q0, Quaternion<Real> const& q1, Real omcosA);
78 
79  // The angle between q0 and q1 is A and must be in [0,pi/2]. Quaternion
80  // qh is slerp(1/2,q0,q1) = (q0+q1)/|q0+q1|, so the angle between q0 and
81  // qh is A/2 and the angle between qh and q1 is A/2. The preprocessing
82  // code is
83  // Quaternion<Real> q[n]; // assuming initialized
84  // Quaternion<Real> qh[n-1]; // to be precomputed
85  // Real omcosAH[n-1]; // to be precomputed
86  // for (i0 = 0, i1 = 1; i1 < n; i0 = i1++)
87  // {
88  // cosA = Dot(q[i0], q[i1]);
89  // if (cosA < 0)
90  // {
91  // q[i1] = -q[i1];
92  // cosA = -cosA;
93  // }
94  // cosAH = sqrt((1 + cosA)/2);
95  // qh[i0] = (q0 + q1) / (2 * cosAH[i0]);
96  // omcosAH[i0] = 1 - cosAH;
97  // }
98  template <int N>
99  inline static Quaternion<Real> EstimateRPH(Real t,
100  Quaternion<Real> const& q0, Quaternion<Real> const& q1,
101  Quaternion<Real> const& qh, Real omcosAH);
102 };
103 
104 
105 template <typename Real> template <int N> inline
107 Quaternion<Real> const& q0, Quaternion<Real> const& q1)
108 {
109  static_assert(1 <= N && N <= 16, "Invalid degree.");
110 
111  Real cs = Dot(q0, q1);
112  Real sign;
113  if (cs >= (Real)0)
114  {
115  sign = (Real)1;
116  }
117  else
118  {
119  cs = -cs;
120  sign = (Real)-1;
121  }
122 
123  Real f0, f1;
125  GetEstimate<N>(t, (Real)1 - cs, f0, f1);
126  return q0 * f0 + q1 * (sign * f1);
127 }
128 
129 template <typename Real> template <int N> inline
131 Quaternion<Real> const& q0, Quaternion<Real> const& q1)
132 {
133  static_assert(1 <= N && N <= 16, "Invalid degree.");
134 
135  Real f0, f1;
137  GetEstimate<N>(t, (Real)1 - Dot(q0, q1), f0, f1);
138  return q0 * f0 + q1 * f1;
139 }
140 
141 template <typename Real> template <int N> inline
143 Quaternion<Real> const& q0, Quaternion<Real> const& q1, Real omcosA)
144 {
145  static_assert(1 <= N && N <= 16, "Invalid degree.");
146 
147  Real f0, f1;
149  GetEstimate<N>(t, omcosA, f0, f1);
150  return q0 * f0 + q1 * f1;
151 }
152 
153 template <typename Real> template <int N> inline
155 Quaternion<Real> const& q0, Quaternion<Real> const& q1,
156 Quaternion<Real> const& qh, Real omcosAH)
157 {
158  static_assert(1 <= N && N <= 16, "Invalid degree.");
159 
160  Real f0, f1;
161  Real twoT = t * (Real)2;
162  if (twoT <= (Real)1)
163  {
165  GetEstimate<N>(twoT, omcosAH, f0, f1);
166  return q0 * f0 + qh * f1;
167  }
168  else
169  {
171  GetEstimate<N>(twoT - (Real)1, omcosAH, f0, f1);
172  return qh * f0 + q1 * f1;
173  }
174 }
175 
176 
177 }
static Quaternion< Real > EstimateRPH(Real t, Quaternion< Real > const &q0, Quaternion< Real > const &q1, Quaternion< Real > const &qh, Real omcosAH)
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLdouble GLdouble t
Definition: glext.h:239
static Quaternion< Real > EstimateR(Real t, Quaternion< Real > const &q0, Quaternion< Real > const &q1)
static Quaternion< Real > EstimateRP(Real t, Quaternion< Real > const &q0, Quaternion< Real > const &q1, Real omcosA)
static Quaternion< Real > Estimate(Real t, Quaternion< Real > const &q0, Quaternion< Real > const &q1)


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01