1 //****************************************************************************//
2 // coretrack.cpp //
3 // Copyright (C) 2001, 2002 Bruno 'Beosil' Heidelberger //
4 //****************************************************************************//
5 // This library is free software; you can redistribute it and/or modify it //
6 // under the terms of the GNU Lesser General Public License as published by //
7 // the Free Software Foundation; either version 2.1 of the License, or (at //
8 // your option) any later version. //
9 //****************************************************************************//
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 //****************************************************************************//
16 // Includes //
17 //****************************************************************************//
18
19 #include "cal3d/coretrack.h"
20 #include "cal3d/error.h"
21 #include "cal3d/corekeyframe.h"
22
23 /*****************************************************************************/
24 /** Constructs the core track instance.
25 *
26 * This function is the default constructor of the core track instance.
27 *****************************************************************************/
28
CalCoreTrack()29 CalCoreTrack::CalCoreTrack()
30 : m_coreBoneId(-1)
31 {
32 }
33
34 /*****************************************************************************/
35 /** Destructs the core track instance.
36 *
37 * This function is the destructor of the core track instance.
38 *****************************************************************************/
39
~CalCoreTrack()40 CalCoreTrack::~CalCoreTrack()
41 {
42 assert(m_keyframes.empty());
43 }
44
45 /*****************************************************************************/
46 /** Adds a core keyframe.
47 *
48 * This function adds a core keyframe to the core track instance.
49 *
50 * @param pCoreKeyframe A pointer to the core keyframe that should be added.
51 *
52 * @return One of the following values:
53 * \li \b true if successful
54 * \li \b false if an error happend
55 *****************************************************************************/
56
addCoreKeyframe(CalCoreKeyframe * pCoreKeyframe)57 bool CalCoreTrack::addCoreKeyframe(CalCoreKeyframe *pCoreKeyframe)
58 {
59 m_keyframes.push_back(pCoreKeyframe);
60 int idx = m_keyframes.size() - 1;
61 while (idx > 0 && m_keyframes[idx]->getTime() < m_keyframes[idx - 1]->getTime()) {
62 std::swap(m_keyframes[idx], m_keyframes[idx - 1]);
63 --idx;
64 }
65 return true;
66 }
67
68 /*****************************************************************************/
69 /** Creates the core track instance.
70 *
71 * This function creates the core track instance.
72 *
73 * @return One of the following values:
74 * \li \b true if successful
75 * \li \b false if an error happend
76 *****************************************************************************/
77
create()78 bool CalCoreTrack::create()
79 {
80 return true;
81 }
82
83 /*****************************************************************************/
84 /** Destroys the core track instance.
85 *
86 * This function destroys all data stored in the core track instance and frees
87 * all allocated memory.
88 *****************************************************************************/
89
destroy()90 void CalCoreTrack::destroy()
91 {
92 // destroy all core keyframes
93 for (unsigned int i = 0; i < m_keyframes.size(); ++i)
94 {
95 m_keyframes[i]->destroy();
96 delete m_keyframes[i];
97 }
98 m_keyframes.clear();
99
100 m_coreBoneId = -1;
101 }
102
103 /*****************************************************************************/
104 /** Returns a specified state.
105 *
106 * This function returns the state (translation and rotation of the core bone)
107 * for the specified time and duration.
108 *
109 * @param time The time in seconds at which the state should be returned.
110 * @param translation A reference to the translation reference that will be
111 * filled with the specified state.
112 * @param rotation A reference to the rotation reference that will be filled
113 * with the specified state.
114 *
115 * @return One of the following values:
116 * \li \b true if successful
117 * \li \b false if an error happend
118 *****************************************************************************/
119
getState(float time,CalVector & translation,CalQuaternion & rotation)120 bool CalCoreTrack::getState(float time, CalVector& translation, CalQuaternion& rotation)
121 {
122 std::vector<CalCoreKeyframe*>::iterator iteratorCoreKeyframeBefore;
123 std::vector<CalCoreKeyframe*>::iterator iteratorCoreKeyframeAfter;
124
125 // get the keyframe after the requested time
126 iteratorCoreKeyframeAfter = getUpperBound(time);
127
128 // check if the time is after the last keyframe
129 if(iteratorCoreKeyframeAfter == m_keyframes.end())
130 {
131 // return the last keyframe state
132 --iteratorCoreKeyframeAfter;
133 rotation = (*iteratorCoreKeyframeAfter)->getRotation();
134 translation = (*iteratorCoreKeyframeAfter)->getTranslation();
135
136 return true;
137 }
138
139 // check if the time is before the first keyframe
140 if(iteratorCoreKeyframeAfter == m_keyframes.begin())
141 {
142 // return the first keyframe state
143 rotation = (*iteratorCoreKeyframeAfter)->getRotation();
144 translation = (*iteratorCoreKeyframeAfter)->getTranslation();
145
146 return true;
147 }
148
149 // get the keyframe before the requested one
150 iteratorCoreKeyframeBefore = iteratorCoreKeyframeAfter;
151 --iteratorCoreKeyframeBefore;
152
153 // get the two keyframe pointers
154 CalCoreKeyframe *pCoreKeyframeBefore;
155 pCoreKeyframeBefore = *iteratorCoreKeyframeBefore;
156 CalCoreKeyframe *pCoreKeyframeAfter;
157 pCoreKeyframeAfter = *iteratorCoreKeyframeAfter;
158
159 // calculate the blending factor between the two keyframe states
160 float blendFactor;
161 blendFactor = (time - pCoreKeyframeBefore->getTime()) / (pCoreKeyframeAfter->getTime() - pCoreKeyframeBefore->getTime());
162
163 // blend between the two keyframes
164 translation = pCoreKeyframeBefore->getTranslation();
165 translation.blend(blendFactor, pCoreKeyframeAfter->getTranslation());
166
167 rotation = pCoreKeyframeBefore->getRotation();
168 rotation.blend(blendFactor, pCoreKeyframeAfter->getRotation());
169
170 return true;
171 }
172
getUpperBound(float time)173 std::vector<CalCoreKeyframe*>::iterator CalCoreTrack::getUpperBound(float time)
174 {
175
176 int lowerBound = 0;
177 int upperBound = m_keyframes.size()-1;
178 //static int aa = 0;
179
180 //upperBound += aa;
181 //upperBound %= m_keyframes.size();
182 //aa++;
183 //time = m_keyframes[upperBound]->getTime();
184
185 while(lowerBound<upperBound-1)
186 {
187 int middle = (lowerBound+upperBound)/2;
188
189 if(time >= m_keyframes[middle]->getTime())
190 {
191 lowerBound=middle;
192 }
193 else
194 {
195 upperBound=middle;
196 }
197 //break;
198 }
199
200 return m_keyframes.begin() + upperBound;
201
202 }
203
204 /*****************************************************************************/
205 /** Sets the ID of the core bone.
206 *
207 * This function sets the ID of the core bone to which the core track instance
208 * is attached to.
209 *
210 * @param coreBoneId The ID of the bone to which the core track instance should
211 * be attached to.
212 *
213 * @return One of the following values:
214 * \li \b true if successful
215 * \li \b false if an error happend
216 *****************************************************************************/
217
setCoreBoneId(int coreBoneId)218 bool CalCoreTrack::setCoreBoneId(int coreBoneId)
219 {
220 if(coreBoneId < 0)
221 {
222 CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__);
223 return false;
224 }
225
226 m_coreBoneId = coreBoneId;
227
228 return true;
229 }
230
231
getCoreKeyframeCount()232 int CalCoreTrack::getCoreKeyframeCount()
233 {
234 return m_keyframes.size();
235 }
236
237
getCoreKeyframe(int idx)238 CalCoreKeyframe* CalCoreTrack::getCoreKeyframe(int idx)
239 {
240 return m_keyframes[idx];
241 }
242
243 /*****************************************************************************/
244 /** Scale the core track.
245 *
246 * This function rescale all the data that are in the core track instance.
247 *
248 * @param factor A float with the scale factor
249 *
250 *****************************************************************************/
251
252
scale(float factor)253 void CalCoreTrack::scale(float factor)
254 {
255 for(size_t keyframeId = 0; keyframeId < m_keyframes.size(); keyframeId++)
256 {
257 CalVector translation = m_keyframes[keyframeId]->getTranslation();
258 translation*=factor;
259 m_keyframes[keyframeId]->setTranslation(translation);
260 }
261
262 }
263
264 //****************************************************************************//
265