-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathFacialAnimation.cpp
326 lines (294 loc) · 10.8 KB
/
FacialAnimation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#include "FacialAnimation.h"
#include "global.h"
#include "Timeshift.h"
#include "Run3SoundRuntime.h"
FacialAnimation::FacialAnimation()
{
mAnimate=false;
endAnim=timeAnim=0;
curstate=0;
mPatched=false;
}
FacialAnimation::~FacialAnimation()
{
}
String FacialAnimation::getAttrib(TiXmlElement *XMLNode, const String &attrib, const String &defaultValue)
{
if(XMLNode->Attribute(attrib.c_str()))
return XMLNode->Attribute(attrib.c_str());
else
return defaultValue;
}
Real FacialAnimation::getAttribReal(TiXmlElement *XMLNode, const String &attrib, Real defaultValue)
{
if(XMLNode->Attribute(attrib.c_str()))
return StringConverter::parseReal(XMLNode->Attribute(attrib.c_str()));
else
return defaultValue;
}
bool FacialAnimation::getAttribBool(TiXmlElement *XMLNode, const String &attrib, bool defaultValue)
{
if(!XMLNode->Attribute(attrib.c_str()))
return defaultValue;
if(String(XMLNode->Attribute(attrib.c_str())) == "true")
return true;
return false;
}
Entity* FacialAnimation::preInit(String meshFile,String name)
{
/*LogManager::getSingleton().logMessage( "[FacialAnimation] 1" );
mesh = MeshManager::getSingleton().load(meshFile, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
LogManager::getSingleton().logMessage( "[FacialAnimation] 2" );
Animation* anim = mesh->createAnimation("manl", 0);
LogManager::getSingleton().logMessage( "[FacialAnimation] 3" );
VertexAnimationTrack* track = anim->createVertexTrack(0, VAT_POSE);
LogManager::getSingleton().logMessage( "[FacialAnimation] 4" );
manualKeyFrame = track->createVertexPoseKeyFrame(0);
LogManager::getSingleton().logMessage( "[FacialAnimation] 5" );
// create pose references, initially zero
for (int i = 0; i < SI_COUNT; ++i)
{
manualKeyFrame->addPoseReference(i, 0.0f);
}
LogManager::getSingleton().logMessage( "[FacialAnimation] 6" );
head = global::getSingleton().getSceneManager()->createEntity(name, meshFile);
LogManager::getSingleton().logMessage( "[FacialAnimation] 7" );
manualAnimState = head->getAnimationState("manl");
LogManager::getSingleton().logMessage( "[FacialAnimation] 8" );
manualAnimState->setTimePosition(0);
LogManager::getSingleton().logMessage( "[FacialAnimation] 9" );
//manualAnimState->setEnabled(true);
LogManager::getSingleton().logMessage( "[FacialAnimation] 10" );
return head;*/
try{
LogManager::getSingleton().logMessage( "[FacialAnimation] 1" );
// Pre-load the mesh so that we can tweak it with a manual animation
mesh = MeshManager::getSingleton().load(meshFile, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
//we'll read through this list while loading
PoseList poseList = mesh->getPoseList();
//used to loop through each submesh
int numSubMeshes = mesh->getNumSubMeshes();
int curPoseIndex = 0;
//create the animation on the mesh
if (mesh->hasAnimation("manl"+name))
{
head = global::getSingleton().getSceneManager()->createEntity(name, meshFile);
// LogManager::getSingleton().logMessage( "[FacialAnimation] Getting animation: manl"+name );
manualAnimState = head->getAnimationState("manl"+name);
manualAnimState->setTimePosition(0);
//LogManager::getSingleton().logMessage( "[FacialAnimation] 2" );
manualAnimState->setEnabled(true);
}
else
{
//LogManager::getSingleton().logMessage( "[FacialAnimation] New animation: manl"+name );
Animation* anim = mesh->createAnimation("manl"+name, 0);
//skip submesh 0 since it is the shared geometry, and we have no poses on that
for(int curSubMesh = 1; curSubMesh <= numSubMeshes; curSubMesh++){
//create the VertexTrack on this animation
Ogre::VertexAnimationTrack *vt = anim->createVertexTrack(curSubMesh, VAT_POSE);
//create the keyframe we will use to update this vertex track
//keep all our keyframes in a map for later updating
vertexPoseKeyFrameMap[curSubMesh] = vt->createVertexPoseKeyFrame(0);
//add the references to each pose that applies to this subMesh
while(poseList[curPoseIndex]->getTarget() == curSubMesh-1){
//create a pose reference for each pose
vertexPoseKeyFrameMap[curSubMesh]->addPoseReference(curPoseIndex, 0.0f);
curPoseIndex++;
}
}
//create the head
head = global::getSingleton().getSceneManager()->createEntity(name, meshFile);
// LogManager::getSingleton().logMessage( "[FacialAnimation] Getting animation: manl"+name );
manualAnimState = head->getAnimationState("manl"+name);
manualAnimState->setTimePosition(0);
//LogManager::getSingleton().logMessage( "[FacialAnimation] 2" );
manualAnimState->setEnabled(true);
//LogManager::getSingleton().logMessage( "[FacialAnimation] 3" );
//put entity in scene
}
return head;
}
catch(runtime_error err){
std::string error = "ERROR: ";
error.append(__FILE__);
error.append(err.what());
LogManager::getSingleton().logMessage(error);
return 0;
}
}
void FacialAnimation::init(String xmlData)
{
LogManager::getSingleton().logMessage("[FacialAnimation] Loading facial animation.");
letters.clear();
try
{
// Strip the path
Ogre::String basename, path;
Ogre::StringUtil::splitFilename(xmlData, basename, path);
DataStreamPtr pStream = ResourceGroupManager::getSingleton().
openResource( basename, "General" );
String data = pStream->getAsString();
// Open the .xml File
SequenceDoc = new TiXmlDocument();
SequenceDoc->Parse( data.c_str() );
pStream->close();
pStream.setNull();
if( SequenceDoc->Error() )
{
//We'll just log, and continue on gracefully
LogManager::getSingleton().logMessage("[FacialAnimation] TiXml reporated an error.");
return;
}
}
catch(...)
{
//rest=true;
//We'll just log, and continue on gracefully
LogManager::getSingleton().logMessage("[FacialAnimation] SaveFile does not present,or TiXml reporated an error.");
return;
}
SequenceRoot = SequenceDoc->RootElement();
if( String( SequenceRoot->Value()) != "facialanimation" ) {
LogManager::getSingleton().logMessage( "[FacialAnimation] Error: Invalid .xml File. Missing <facialanimation>" );
return;
}
subtitle = getAttrib(SequenceRoot,"subtitle_text","");
if (!(global::getSingleton().getPlayer()->getAllowSubtitles()))
subtitle="";
mPatched=getAttribBool(SequenceRoot,"patched",false);
LogManager::getSingleton().logMessage("[FacialAnimation] processing nodes...");
TiXmlElement* pElement;
pElement = SequenceRoot->FirstChildElement("node");
while(pElement)
{
String key = getAttrib(pElement,"letter","A");
Real time = getAttribReal(pElement,"time",0.0f);
bool patch = getAttribBool(pElement,"patch",false);
MorphState s;
s.init(time,key,patch);
letters.push_back(s);
endAnim=time;
duration=time+1.0f;
pElement = pElement->NextSiblingElement("node");
LogManager::getSingleton().logMessage("[FacialAnimation] processing node...");
}
soundFile = getAttrib(SequenceRoot->FirstChildElement("file"),"name","run3/sounds/pogran/document01.wav");
//duration = getAttribReal(SequenceRoot->FirstChildElement("file"),"duration",3.0f);
LogManager::getSingleton().logMessage("[FacialAnimation] Loading ok.");
delete SequenceDoc;
}
void FacialAnimation::animate(Vector3 pos)
{
mAnimate=true;
mPos=pos;
curstate=0;
LogManager::getSingleton().logMessage("[FacialAnimation] Starting animation.");
if (!(subtitle.empty()))
{
HUD::getSingleton().flashText(subtitle,PROCESS_ANIM,endAnim);
}
//manualAnimState = head->getAnimationState("manl"+head->getName());
if (manualAnimState)
{
manualAnimState->setEnabled(true);
LogManager::getSingleton().logMessage("[FacialAnimation] Ok.");
}
timeAnim=0;
//curMState=letters[curstate];
}
void FacialAnimation::upd(Real tm)
{
try
{
//just starting
//if (((mAnimate)&&(timeAnim<PROCESS_ANIM))&&(curstate==0))
if (((mAnimate))&&(curstate==0))
{
if (timeAnim>PROCESS_ANIM)
timeAnim=PROCESS_ANIM;
LogManager::getSingleton().logMessage("[FacialAnimation] Pre-ready sequence.");
if (letters[curstate].getIndex()!=-1)
{
//manualKeyFrame->updatePoseReference(letters[curstate].getIndex(), timeAnim/PROCESS_ANIM);
//manualAnimState->getParent()->_notifyDirty();
updatePose(letters[curstate].getIndex(), timeAnim/PROCESS_ANIM);
}
timeAnim+=tm;
if (timeAnim>PROCESS_ANIM)
{
if (letters[curstate].getIndex()!=-1)
{
updatePose(letters[curstate].getIndex(), 0);
}
curstate++;
Run3SoundRuntime::getSingleton().emitSound(soundFile,duration,false,mPos,200,50,800);
LogManager::getSingleton().logMessage("[FacialAnimation] Pre-ready ended.");
}
LogManager::getSingleton().logMessage("[FacialAnimation] Ok pre.");
}
//if (((mAnimate)&&(timeAnim>PROCESS_ANIM)&&(timeAnim<endAnim+PROCESS_ANIM))&&(curstate<letters.size()))
if (((mAnimate)&&(timeAnim>PROCESS_ANIM))&&(curstate<letters.size()))
{
// timeAnim-PROCESS_ANIM is time for active animation
// Triangle functions are there
if (timeAnim>endAnim+PROCESS_ANIM)
timeAnim=endAnim+PROCESS_ANIM;
Real down=(letters[curstate].getSecond()-(timeAnim-PROCESS_ANIM))/(letters[curstate].getSecond());
Real up=1-down;
if (letters[curstate-1].getIndex()!=-1)
{
updatePose(letters[curstate-1].getIndex(), down);
}
if (letters[curstate].getIndex()!=-1)
{
updatePose(letters[curstate].getIndex(), up);
}
//manualKeyFrame->updatePoseReference(letters[curstate-1].getIndex(), down);
//manualKeyFrame->updatePoseReference(letters[curstate].getIndex(), up);
//manualAnimState->getParent()->_notifyDirty();
timeAnim+=tm;
if (timeAnim>letters[curstate].getSecond()+PROCESS_ANIM)
{
if (letters[curstate-1].getIndex()!=-1)
{
updatePose(letters[curstate-1].getIndex(), 0);
}
if (letters[curstate].getIndex()!=-1)
{
updatePose(letters[curstate].getIndex(), 1);
}
curstate++;
}
}
//just ending
if ((mAnimate)&&(timeAnim>endAnim+PROCESS_ANIM))
{
//manualKeyFrame->updatePoseReference(letters[curstate].getIndex(), (endAnim+timeAnim)/(endAnim+PROCESS_ANIM));
//manualAnimState->getParent()->_notifyDirty();
if (letters[curstate-1].getIndex()!=-1)
{
updatePose(letters[curstate-1].getIndex(), 1.0f-(timeAnim-(endAnim+PROCESS_ANIM))/(PROCESS_ANIM));
}
/*if (letters[curstate].getIndex()!=-1)
{
updatePose(letters[curstate].getIndex(), (timeAnim-(endAnim+PROCESS_ANIM))/(PROCESS_ANIM));
}*/
timeAnim+=tm;
if (timeAnim>endAnim+2*PROCESS_ANIM)
{
if (letters[curstate-1].getIndex()!=-1)
{
updatePose(letters[curstate-1].getIndex(), 0);
}
mAnimate=false;
timeAnim=0;
curstate=0;
}
}
}
catch(...)
{
}
//LogManager::getSingleton().logMessage("[FacialAnimation] Ok step.");
}