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