1 //****************************************************************************//
2 // morphtargetmixer.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/error.h"
20 #include "cal3d/morphtargetmixer.h"
21 #include "cal3d/model.h"
22 #include "cal3d/mesh.h"
23 #include "cal3d/submesh.h"
24 #include "cal3d/coremorphanimation.h"
25 #include "cal3d/coremodel.h"
26 #include "cal3d/coremesh.h"
27 #include "cal3d/coresubmesh.h"
28
29 /*****************************************************************************/
30 /** Constructs the morph target mixer instance.
31 *
32 * This function is the default constructor of the morph target mixer instance.
33 *****************************************************************************/
34
CalMorphTargetMixer(CalModel * pModel)35 CalMorphTargetMixer::CalMorphTargetMixer(CalModel* pModel)
36 {
37 assert(pModel);
38 m_pModel = pModel;
39
40 if(pModel->getCoreModel()->getCoreMorphAnimationCount() != 0)
41 {
42 int morphAnimationCount = pModel->getCoreModel()->getCoreMorphAnimationCount();
43 // reserve the space needed in all the vectors
44 m_vectorCurrentWeight.resize(morphAnimationCount);
45 m_vectorEndWeight.resize(morphAnimationCount);
46 m_vectorDuration.resize(morphAnimationCount);
47 std::vector<float>::iterator iteratorCurrentWeight = m_vectorCurrentWeight.begin();
48 std::vector<float>::iterator iteratorEndWeight = m_vectorEndWeight.begin();
49 std::vector<float>::iterator iteratorDuration = m_vectorDuration.begin();
50 while(iteratorCurrentWeight!=m_vectorCurrentWeight.end())
51 {
52 (*iteratorCurrentWeight) = 0.0f;
53 (*iteratorEndWeight) = 0.0f;
54 (*iteratorDuration) = 0.0f;
55 ++iteratorCurrentWeight;
56 ++iteratorEndWeight;
57 ++iteratorDuration;
58 }
59 }
60 }
61
62
63 /*****************************************************************************/
64 /** Interpolates the weight of a morph target.
65 *
66 * This function interpolates the weight of a morph target a new value
67 * in a given amount of time.
68 *
69 * @param id The ID of the morph target that should be blended.
70 * @param weight The weight to interpolate the morph target to.
71 * @param delay The time in seconds until the new weight should be reached.
72 *
73 * @return One of the following values:
74 * \li \b true if successful
75 * \li \b false if an error happend
76 *****************************************************************************/
blend(int id,float weight,float delay)77 bool CalMorphTargetMixer::blend(int id, float weight, float delay)
78 {
79 if((id < 0) || (id >= (int)m_vectorCurrentWeight.size()))
80 {
81 CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__);
82 return false;
83 }
84 m_vectorEndWeight[id] = weight;
85 m_vectorDuration[id] = delay;
86 return true;
87 }
88
89 /*****************************************************************************/
90 /** Fades a morph target out.
91 *
92 * This function fades a morph target out in a given amount of time.
93 *
94 * @param id The ID of the morph target that should be faded out.
95 * @param delay The time in seconds until the the morph target is
96 * completely removed.
97 *
98 * @return One of the following values:
99 * \li \b true if successful
100 * \li \b false if an error happend
101 *****************************************************************************/
102
clear(int id,float delay)103 bool CalMorphTargetMixer::clear(int id, float delay)
104 {
105 if((id < 0) || (id >= (int)m_vectorCurrentWeight.size()))
106 {
107 CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__);
108 return false;
109 }
110 m_vectorEndWeight[id] = 0.0f;
111 m_vectorDuration[id] = delay;
112 return true;
113 }
114
115 /*****************************************************************************/
116 /** Get the weight of a morph target.
117 *
118 * @param id The id of the morph target which weight you want.
119 *
120 * @return The weight of the morph target with the given id.
121 *****************************************************************************/
getCurrentWeight(int id) const122 float CalMorphTargetMixer::getCurrentWeight(int id) const
123 {
124 if((id < 0) || (id >= (int)m_vectorCurrentWeight.size()))
125 {
126 CalError::setLastError(CalError::INVALID_HANDLE, __FILE__, __LINE__);
127 return false;
128 }
129 return m_vectorCurrentWeight[id];
130 }
131
132 /*****************************************************************************/
133 /** Get the weight of the base vertices.
134 *
135 * @return The weight of the base vertices.
136 *****************************************************************************/
getCurrentWeightBase()137 float CalMorphTargetMixer::getCurrentWeightBase()
138 {
139 float currentWeight = 1.0f;
140 std::vector<float>::iterator iteratorCurrentWeight = m_vectorCurrentWeight.begin();
141 while(iteratorCurrentWeight!=m_vectorCurrentWeight.end())
142 {
143 currentWeight -=(*iteratorCurrentWeight);
144 ++iteratorCurrentWeight;
145 }
146 return currentWeight;
147 }
148
149 /*****************************************************************************/
150 /** Updates all morph targets.
151 *
152 * This function updates all morph targets of the mixer instance for a
153 * given amount of time.
154 *
155 * @param deltaTime The elapsed time in seconds since the last update.
156 *****************************************************************************/
157
update(float deltaTime)158 void CalMorphTargetMixer::update(float deltaTime)
159 {
160 std::vector<float>::iterator iteratorCurrentWeight = m_vectorCurrentWeight.begin();
161 std::vector<float>::iterator iteratorEndWeight = m_vectorEndWeight.begin();
162 std::vector<float>::iterator iteratorDuration = m_vectorDuration.begin();
163 while(iteratorCurrentWeight!=m_vectorCurrentWeight.end())
164 {
165 if(deltaTime >= (*iteratorDuration))
166 {
167 (*iteratorCurrentWeight) = (*iteratorEndWeight);
168 (*iteratorDuration) = 0.0f;
169 }
170 else
171 {
172 (*iteratorCurrentWeight) += ((*iteratorEndWeight)-(*iteratorCurrentWeight)) *
173 deltaTime/(*iteratorDuration);
174 (*iteratorDuration) -= deltaTime;
175 }
176 ++iteratorCurrentWeight;
177 ++iteratorEndWeight;
178 ++iteratorDuration;
179 }
180 int morphAnimationID = 0;
181 while(morphAnimationID<getMorphTargetCount())
182 {
183 CalCoreMorphAnimation* pCoreMorphAnimation =
184 m_pModel->getCoreModel()->getCoreMorphAnimation(morphAnimationID);
185 std::vector<int>& vectorCoreMeshID = pCoreMorphAnimation->getVectorCoreMeshID();
186 std::vector<int>& vectorMorphTargetID = pCoreMorphAnimation->getVectorMorphTargetID();
187 size_t meshIterator = 0;
188 while(meshIterator<vectorCoreMeshID.size())
189 {
190 std::vector<CalSubmesh *> &vectorSubmesh =
191 m_pModel->getMesh(vectorCoreMeshID[meshIterator])->getVectorSubmesh();
192 int submeshCount = vectorSubmesh.size();
193 int submeshId;
194 for(submeshId=0;submeshId<submeshCount;++submeshId)
195 {
196 vectorSubmesh[submeshId]->setMorphTargetWeight
197 (vectorMorphTargetID[meshIterator],m_vectorCurrentWeight[morphAnimationID]);
198 }
199 ++meshIterator;
200 }
201 ++morphAnimationID;
202 }
203 }
204
205 /*****************************************************************************/
206 /** Returns the number of morph targets this morph target mixer mixes.
207 *
208 * @return The number of morph targets this morph target mixer mixes.
209 *****************************************************************************/
210
getMorphTargetCount() const211 int CalMorphTargetMixer::getMorphTargetCount() const
212 {
213 return m_vectorCurrentWeight.size();
214 }
215
216 //****************************************************************************//
217