2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
7 Copyright (c) 2000-2006 Torus Knot Software Ltd
8 Also see acknowledgements in Readme.html
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22 http://www.gnu.org/copyleft/lesser.txt.
24 You may alternatively use this source under the terms of a specific version of
25 the OGRE Unrestricted License provided you have obtained such a license from
26 Torus Knot Software Ltd.
27 -----------------------------------------------------------------------------
29 #include "OgreStableHeaders.h"
30 #include "OgreRotationalSpline.h"
36 //---------------------------------------------------------------------
37 RotationalSpline::RotationalSpline()
41 //---------------------------------------------------------------------
42 RotationalSpline::~RotationalSpline()
45 //---------------------------------------------------------------------
46 void RotationalSpline::addPoint(const Quaternion
& p
)
54 //---------------------------------------------------------------------
55 Quaternion
RotationalSpline::interpolate(Real t
, bool useShortestPath
)
57 // Work out which segment this is in
58 Real fSeg
= t
* (mPoints
.size() - 1);
59 unsigned int segIdx
= (unsigned int)fSeg
;
63 return interpolate(segIdx
, t
, useShortestPath
);
66 //---------------------------------------------------------------------
67 Quaternion
RotationalSpline::interpolate(unsigned int fromIndex
, Real t
,
71 assert (fromIndex
>= 0 && fromIndex
< mPoints
.size() &&
72 "fromIndex out of bounds");
74 if ((fromIndex
+ 1) == mPoints
.size())
76 // Duff request, cannot blend to nothing
78 return mPoints
[fromIndex
];
84 return mPoints
[fromIndex
];
88 return mPoints
[fromIndex
+ 1];
92 // Use squad using tangents we've already set up
93 Quaternion
&p
= mPoints
[fromIndex
];
94 Quaternion
&q
= mPoints
[fromIndex
+1];
95 Quaternion
&a
= mTangents
[fromIndex
];
96 Quaternion
&b
= mTangents
[fromIndex
+1];
98 // NB interpolate to nearest rotation
99 return Quaternion::Squad(t
, p
, a
, b
, q
, useShortestPath
);
102 //---------------------------------------------------------------------
103 void RotationalSpline::recalcTangents(void)
105 // ShoeMake (1987) approach
106 // Just like Catmull-Rom really, just more gnarly
107 // And no, I don't understand how to derive this!
109 // let p = point[i], pInv = p.Inverse
110 // tangent[i] = p * exp( -0.25 * ( log(pInv * point[i+1]) + log(pInv * point[i-1]) ) )
112 // Assume endpoint tangents are parallel with line with neighbour
114 unsigned int i
, numPoints
;
117 numPoints
= (unsigned int)mPoints
.size();
121 // Can't do anything yet
125 mTangents
.resize(numPoints
);
127 if (mPoints
[0] == mPoints
[numPoints
-1])
136 Quaternion invp
, part1
, part2
, preExp
;
137 for(i
= 0; i
< numPoints
; ++i
)
139 Quaternion
&p
= mPoints
[i
];
144 // special case start
145 part1
= (invp
* mPoints
[i
+1]).Log();
148 // Use numPoints-2 since numPoints-1 == end == start == this one
149 part2
= (invp
* mPoints
[numPoints
-2]).Log();
153 part2
= (invp
* p
).Log();
156 else if (i
== numPoints
-1)
161 // Wrap to [1] (not [0], this is the same as end == this one)
162 part1
= (invp
* mPoints
[1]).Log();
166 part1
= (invp
* p
).Log();
168 part2
= (invp
* mPoints
[i
-1]).Log();
172 part1
= (invp
* mPoints
[i
+1]).Log();
173 part2
= (invp
* mPoints
[i
-1]).Log();
176 preExp
= -0.25 * (part1
+ part2
);
177 mTangents
[i
] = p
* preExp
.Exp();
184 //---------------------------------------------------------------------
185 const Quaternion
& RotationalSpline::getPoint(unsigned short index
) const
187 assert (index
< mPoints
.size() && "Point index is out of bounds!!");
189 return mPoints
[index
];
191 //---------------------------------------------------------------------
192 unsigned short RotationalSpline::getNumPoints(void) const
194 return (unsigned short)mPoints
.size();
196 //---------------------------------------------------------------------
197 void RotationalSpline::clear(void)
202 //---------------------------------------------------------------------
203 void RotationalSpline::updatePoint(unsigned short index
, const Quaternion
& value
)
205 assert (index
< mPoints
.size() && "Point index is out of bounds!!");
207 mPoints
[index
] = value
;
213 //---------------------------------------------------------------------
214 void RotationalSpline::setAutoCalculate(bool autoCalc
)
216 mAutoCalc
= autoCalc
;
218 //---------------------------------------------------------------------