1 /*
2 * Skeleton.cpp
3 * Copyright (C) 2007 by Bryan Duff <duff0097@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20 /**> HEADER FILES <**/
21 #include "Skeleton.h"
22 #include "Serialize.h"
23
24 extern double multiplier;
25 extern unsigned int gSourceID[100];
26 extern unsigned int gSampleSet[100];
27 extern int visions;
28 extern Camera camera;
29 extern float soundscalefactor;
30
31 extern XYZ vel;
32 extern XYZ midp;
33 extern XYZ newpoint1, newpoint2;
34
35 extern float oldlength;
36 extern float relaxlength;
37
38 extern float friction;
39 extern int numrepeats;
40 extern float groundlevel;
41 extern float offset;
42 extern XYZ impact;
43 extern XYZ overpoint;
44 extern XYZ underpoint;
45 extern int whichtri;
46 extern XYZ normalrotated;
47 extern bool groundish;
48
49
DoConstraint()50 void Joint::DoConstraint()
51 {
52
53 if(hasparent) {
54 //Find midpoint
55 midp = (position + parent->position) / 2;
56 //Find vector from midpoint to second vector
57 vel = parent->position - midp;
58 //Change to unit vector
59 Normalise(&vel);
60 //Apply velocity change
61 velocity += ((midp - vel * length / 2) - position);
62 parent->velocity += ((midp + vel * length / 2) - parent->position);
63 //Move child point to within certain distance of parent point
64 if(!locked)
65 position = midp - vel * length / 2;
66 if(!parent->locked)
67 parent->position = midp + vel * length / 2;
68 }
69 }
70
DoConstraint(int broken)71 void Muscle::DoConstraint(int broken)
72 {
73 oldlength = length;
74 relaxlength = findDistance(parent1->position, parent2->position);
75
76 if(type == boneconnect)
77 strength = 1;
78 if(type == constraint)
79 strength = 0;
80
81 if(strength < 0)
82 strength = 0;
83 if(strength > 1)
84 strength = 1;
85
86 length -=
87 (length - relaxlength) * (1 - strength) * multiplier * multiplier * 10000;
88 length -=
89 (length - targetlength) * (strength) * multiplier * multiplier * 10000;
90 if(strength == 0)
91 length = relaxlength;
92
93 if((relaxlength - length > 0 && relaxlength - oldlength < 0)
94 || (relaxlength - length < 0 && relaxlength - oldlength > 0))
95 length = relaxlength;
96
97 if(length < minlength)
98 length = minlength;
99 if(length > maxlength && !broken)
100 length = maxlength;
101
102 //Find midpoint
103 midp = (parent1->position + parent2->position) / 2;
104 //Find vector from midpoint to second vector
105 vel = parent2->position - midp;
106 //Change to unit vector
107 Normalise(&vel);
108 //Apply velocity change
109 newpoint1 = midp - vel * length / 2;
110 newpoint2 = midp + vel * length / 2;
111 parent1->velocity += (newpoint1 - parent1->position);
112 parent2->velocity += (newpoint2 - parent2->position);
113 //Move child point to within certain distance of parent point
114 if(!parent1->locked)
115 parent1->position = newpoint1;
116 if(!parent2->locked)
117 parent2->position = newpoint2;
118 }
119
DoConstraints()120 void Skeleton::DoConstraints()
121 {
122 numrepeats = 3;
123
124 for(int j = 0; j < numrepeats; j++) {
125 for(int i = 0; i < num_joints; i++) {
126 joints[i].DoConstraint();
127 }
128 }
129 }
130
DoConstraints(Model * collide,XYZ * move,float rotation)131 void Skeleton::DoConstraints(Model * collide, XYZ * move, float rotation)
132 {
133 friction = 20;
134 numrepeats = 2;
135 groundlevel = 0;
136
137 move->y += .35;
138
139 for(int j = 0; j < numrepeats; j++) {
140 for(int i = 0; i < num_joints; i++) {
141 if(joints[i].existing || i == jointlabels[lefthand]
142 || i == jointlabels[righthand]) {
143 //Length constraints
144 joints[i].DoConstraint();
145 //Ground constraint
146 offset = 0;
147 overpoint = joints[i].position;
148 overpoint.y += 10;
149 underpoint = joints[i].position;
150 underpoint.y -= offset;
151 whichtri =
152 collide->LineCheck2(overpoint, underpoint, &impact, *move,
153 rotation);
154 if(collide->normals[whichtri].y <= .8)
155 whichtri =
156 collide->LineCheck2(joints[i].realoldposition, joints[i].position,
157 &impact, *move, rotation);
158 if(joints[i].position.y <= groundlevel + offset || whichtri != -1) {
159 if(whichtri == -1
160 || (whichtri != -1 && collide->normals[whichtri].y > .8)) {
161 if(whichtri == -1)
162 joints[i].position.y = groundlevel + offset;
163 if(whichtri != -1) {
164 joints[i].position = impact;
165 joints[i].position.y += offset;
166 }
167 joints[i].velocity.y *= -.3;
168 joints[i].velocity.x *= .3;
169 joints[i].velocity.z *= .3;
170 }
171 offset = .2;
172 if(whichtri != -1 && collide->normals[whichtri].y <= .8) {
173 normalrotated =
174 DoRotation(collide->normals[whichtri], 0, rotation, 0);
175 joints[i].position = impact + normalrotated * offset;
176 ReflectVector(&joints[i].velocity, &normalrotated);
177 joints[i].velocity *= .3;
178 }
179 if(broken <= 1) {
180 XYZ avgvelocity;
181 avgvelocity = 0;
182 float gLoc[3];
183 ALint tempint;
184 for(int k = 0; k < num_joints; k++) {
185 avgvelocity += joints[k].velocity;
186 }
187 avgvelocity /= num_joints;
188 if(joints[i].label == head
189 && (findLengthfast(joints[i].velocity) > 2
190 || findLengthfast(avgvelocity) > 2)) {
191 avgvelocity += joints[i].velocity;
192 gLoc[0] = joints[i].position.x / soundscalefactor;
193 gLoc[1] = joints[i].position.y / soundscalefactor;
194 gLoc[2] = joints[i].position.z / soundscalefactor;
195 #ifdef DEBIAN_NEEDS_TO_UPDATE_THEIR_OPENAL
196 alGetSourceiv(gSourceID[headlandsound], AL_SOURCE_STATE,
197 &tempint);
198 #else
199 alGetSourcei(gSourceID[headlandsound], AL_SOURCE_STATE, &tempint);
200 #endif
201 if(tempint != AL_PLAYING) {
202 alSourcef(gSourceID[headlandsound], AL_MIN_GAIN,
203 ALfloat(findLengthfast(avgvelocity) * 2 /
204 findDistancefast(joints[i].position,
205 camera.position) *
206 soundscalefactor * 2));
207 alSourcef(gSourceID[headlandsound], AL_MAX_GAIN,
208 ALfloat(findLengthfast(avgvelocity) * 2 /
209 findDistancefast(joints[i].position,
210 camera.position) *
211 soundscalefactor * 2));
212 alSourcefv(gSourceID[headlandsound], AL_POSITION, gLoc);
213 alSourcePlay(gSourceID[headlandsound]);
214 }
215 }
216 avgvelocity = 0;
217 for(int k = 0; k < num_joints; k++) {
218 avgvelocity += joints[k].velocity;
219 }
220 avgvelocity /= num_joints;
221 if((joints[i].label == abdomen)
222 && (findLengthfast(joints[i].velocity) > 2
223 || findLengthfast(avgvelocity) > 2)) {
224 avgvelocity += joints[i].velocity;
225 gLoc[0] = joints[i].position.x / soundscalefactor;
226 gLoc[1] = joints[i].position.y / soundscalefactor;
227 gLoc[2] = joints[i].position.z / soundscalefactor;
228 #ifdef DEBIAN_NEEDS_TO_UPDATE_THEIR_OPENAL
229 alGetSourceiv(gSourceID[bodylandsound], AL_SOURCE_STATE,
230 &tempint);
231 #else
232 alGetSourcei(gSourceID[bodylandsound], AL_SOURCE_STATE, &tempint);
233 #endif
234 if(tempint != AL_PLAYING) {
235 alSourcef(gSourceID[bodylandsound], AL_MIN_GAIN,
236 ALfloat(findLengthfast(joints[i].velocity) * 1 /
237 findDistancefast(joints[i].position,
238 camera.position) *
239 soundscalefactor * 2));
240 alSourcef(gSourceID[bodylandsound], AL_MAX_GAIN,
241 ALfloat(findLengthfast(joints[i].velocity) * 1 /
242 findDistancefast(joints[i].position,
243 camera.position) *
244 soundscalefactor * 2));
245 alSourcefv(gSourceID[bodylandsound], AL_POSITION, gLoc);
246 alSourcePlay(gSourceID[bodylandsound]);
247 }
248 }
249 }
250 }
251 }
252 }
253 if(num_muscles)
254 for(int i = 0; i < num_muscles; i++) {
255 //Length constraints
256 muscles[i].DoConstraint(broken);
257 }
258 }
259
260 for(int i = 0; i < num_joints; i++) {
261 joints[i].realoldposition = joints[i].position;
262 }
263
264 //Add velocity
265 for(int i = 0; i < num_joints; i++) {
266 if(joints[i].existing || i == jointlabels[lefthand]
267 || i == jointlabels[righthand])
268 joints[i].position = joints[i].position + joints[i].velocity * multiplier;
269 }
270 }
271
DoGravity()272 void Skeleton::DoGravity()
273 {
274 for(int i = 0; i < num_joints; i++) {
275 joints[i].velocity.y += gravity * multiplier;
276 }
277 }
278
Draw(int muscleview)279 void Skeleton::Draw(int muscleview)
280 {
281 float jointcolor[4];
282
283 if(muscleview != 2) {
284 jointcolor[0] = 0;
285 jointcolor[1] = 0;
286 jointcolor[2] = .5;
287 jointcolor[3] = 1;
288 }
289
290 if(muscleview == 2) {
291 jointcolor[0] = 0;
292 jointcolor[1] = 0;
293 jointcolor[2] = 0;
294 jointcolor[3] = .5;
295 }
296 //Calc motionblur-ness
297 for(int i = 0; i < num_joints; i++) {
298 joints[i].oldposition = joints[i].position;
299 joints[i].blurred =
300 findDistance(joints[i].position, joints[i].oldposition) * 100;
301 if(joints[i].blurred < 1)
302 joints[i].blurred = 1;
303 }
304
305 //Do Motionblur
306 glDepthMask(0);
307 glEnable(GL_BLEND);
308 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
309 glBegin(GL_QUADS);
310 for(int i = 0; i < num_joints; i++) {
311 if(joints[i].hasparent) {
312 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
313 jointcolor[3] / joints[i].blurred);
314 glVertex3f(joints[i].position.x, joints[i].position.y,
315 joints[i].position.z);
316 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
317 jointcolor[3] / joints[i].parent->blurred);
318 glVertex3f(joints[i].parent->position.x, joints[i].parent->position.y,
319 joints[i].parent->position.z);
320 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
321 jointcolor[3] / joints[i].parent->blurred);
322 glVertex3f(joints[i].parent->oldposition.x,
323 joints[i].parent->oldposition.y,
324 joints[i].parent->oldposition.z);
325 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
326 jointcolor[3] / joints[i].blurred);
327 glVertex3f(joints[i].oldposition.x, joints[i].oldposition.y,
328 joints[i].oldposition.z);
329 }
330 }
331 for(int i = 0; i < num_muscles; i++) {
332 if(muscles[i].type == boneconnect) {
333 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
334 jointcolor[3] / muscles[i].parent2->blurred);
335 glVertex3f(muscles[i].parent1->position.x, muscles[i].parent1->position.y,
336 muscles[i].parent1->position.z);
337 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
338 jointcolor[3] / muscles[i].parent2->blurred);
339 glVertex3f(muscles[i].parent2->position.x, muscles[i].parent2->position.y,
340 muscles[i].parent2->position.z);
341 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
342 jointcolor[3] / muscles[i].parent2->blurred);
343 glVertex3f(muscles[i].parent2->oldposition.x,
344 muscles[i].parent2->oldposition.y,
345 muscles[i].parent2->oldposition.z);
346 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
347 jointcolor[3] / muscles[i].parent1->blurred);
348 glVertex3f(muscles[i].parent1->oldposition.x,
349 muscles[i].parent1->oldposition.y,
350 muscles[i].parent1->oldposition.z);
351 }
352 }
353 glEnd();
354
355 glBegin(GL_LINES);
356 for(int i = 0; i < num_joints; i++) {
357 if(joints[i].hasparent) {
358 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
359 jointcolor[3] / joints[i].blurred);
360 glVertex3f(joints[i].position.x, joints[i].position.y,
361 joints[i].position.z);
362 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
363 jointcolor[3] / joints[i].parent->blurred);
364 glVertex3f(joints[i].parent->position.x, joints[i].parent->position.y,
365 joints[i].parent->position.z);
366 }
367 }
368 for(int i = 0; i < num_muscles; i++) {
369 if(muscles[i].type == boneconnect) {
370 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
371 jointcolor[3] / muscles[i].parent1->blurred);
372 glVertex3f(muscles[i].parent1->position.x, muscles[i].parent1->position.y,
373 muscles[i].parent1->position.z);
374 glColor4f(jointcolor[0], jointcolor[1], jointcolor[2],
375 jointcolor[3] / muscles[i].parent2->blurred);
376 glVertex3f(muscles[i].parent2->position.x, muscles[i].parent2->position.y,
377 muscles[i].parent2->position.z);
378 }
379 }
380 glColor3f(.6, .6, 0);
381 if(muscleview == 1)
382 for(int i = 0; i < num_muscles; i++) {
383 if(muscles[i].type != boneconnect) {
384 glVertex3f(muscles[i].parent1->position.x,
385 muscles[i].parent1->position.y,
386 muscles[i].parent1->position.z);
387 glVertex3f(muscles[i].parent2->position.x,
388 muscles[i].parent2->position.y,
389 muscles[i].parent2->position.z);
390 }
391 }
392 glEnd();
393
394 if(muscleview != 2) {
395 glPointSize(3);
396 glBegin(GL_POINTS);
397 for(int i = 0; i < num_joints; i++) {
398 if(i != selected)
399 glColor4f(0, 0, .5, 1);
400 if(i == selected)
401 glColor4f(1, 1, 0, 1);
402 if(joints[i].locked && i != selected)
403 glColor4f(1, 0, 0, 1);
404 glVertex3f(joints[i].position.x, joints[i].position.y,
405 joints[i].position.z);
406 }
407 glEnd();
408 }
409 //Set old position to current position
410 if(muscleview == 2)
411 for(int i = 0; i < num_joints; i++) {
412 joints[i].oldposition = joints[i].position;
413 }
414 glDepthMask(1);
415 }
416
AddJoint(float x,float y,float z,int which)417 void Skeleton::AddJoint(float x, float y, float z, int which)
418 {
419 if(num_joints < max_joints - 1) {
420 joints[num_joints].velocity = 0;
421 joints[num_joints].position.x = x;
422 joints[num_joints].position.y = y;
423 joints[num_joints].position.z = z;
424 joints[num_joints].locked = 0;
425
426 if(which >= num_joints || which < 0)
427 joints[num_joints].hasparent = 0;
428 if(which < num_joints && which >= 0) {
429 joints[num_joints].parent = &joints[which];
430 joints[num_joints].hasparent = 1;
431 joints[num_joints].length =
432 findDistance(joints[num_joints].position,
433 joints[num_joints].parent->position);
434 }
435 num_joints++;
436 }
437 }
438
DeleteJoint(int whichjoint)439 void Skeleton::DeleteJoint(int whichjoint)
440 {
441 if(whichjoint < num_joints && whichjoint >= 0) {
442 for(int i = 0; i < num_muscles; i++) {
443 while(muscles[i].parent1 == &joints[whichjoint] && i < num_muscles)
444 DeleteMuscle(i);
445 while(muscles[i].parent2 == &joints[whichjoint] && i < num_muscles)
446 DeleteMuscle(i);
447 }
448 for(int i = 0; i < num_joints; i++) {
449 if(joints[i].parent == &joints[whichjoint])
450 joints[i].hasparent = 0;
451 }
452 joints[whichjoint].hasparent = 0;
453 }
454 }
455
DeleteMuscle(int whichmuscle)456 void Skeleton::DeleteMuscle(int whichmuscle)
457 {
458 if(whichmuscle < num_muscles) {
459 muscles[whichmuscle].minlength = muscles[num_muscles - 1].minlength;
460 muscles[whichmuscle].maxlength = muscles[num_muscles - 1].maxlength;
461 muscles[whichmuscle].strength = muscles[num_muscles - 1].strength;
462 muscles[whichmuscle].parent1 = muscles[num_muscles - 1].parent1;
463 muscles[whichmuscle].parent2 = muscles[num_muscles - 1].parent2;
464 muscles[whichmuscle].length = muscles[num_muscles - 1].length;
465 muscles[whichmuscle].visible = muscles[num_muscles - 1].visible;
466 muscles[whichmuscle].type = muscles[num_muscles - 1].type;
467 muscles[whichmuscle].targetlength = muscles[num_muscles - 1].targetlength;
468
469 num_muscles--;
470 }
471 }
472
SetJoint(float x,float y,float z,int which,int whichjoint)473 void Skeleton::SetJoint(float x, float y, float z, int which, int whichjoint)
474 {
475 if(whichjoint < num_joints) {
476 joints[whichjoint].velocity = 0;
477 joints[whichjoint].position.x = x;
478 joints[whichjoint].position.y = y;
479 joints[whichjoint].position.z = z;
480
481 if(which >= num_joints || which < 0)
482 joints[whichjoint].hasparent = 0;
483 if(which < num_joints && which >= 0) {
484 joints[whichjoint].parent = &joints[which];
485 joints[whichjoint].hasparent = 1;
486 joints[whichjoint].length =
487 findDistance(joints[whichjoint].position,
488 joints[whichjoint].parent->position);
489 }
490 }
491 }
492
AddMuscle(int attach1,int attach2,float minlength,float maxlength,int type)493 void Skeleton::AddMuscle(int attach1, int attach2, float minlength,
494 float maxlength, int type)
495 {
496 if(num_muscles < max_muscles - 1 && attach1 < num_joints
497 && attach1 >= 0 & attach2 < num_joints && attach2 >= 0
498 && attach1 != attach2) {
499 muscles[num_muscles].parent1 = &joints[attach1];
500 muscles[num_muscles].parent2 = &joints[attach2];
501 muscles[num_muscles].length =
502 findDistance(muscles[num_muscles].parent1->position,
503 muscles[num_muscles].parent2->position);
504 muscles[num_muscles].targetlength =
505 findDistance(muscles[num_muscles].parent1->position,
506 muscles[num_muscles].parent2->position);
507 muscles[num_muscles].strength = .7;
508 muscles[num_muscles].type = type;
509 muscles[num_muscles].minlength = minlength;
510 muscles[num_muscles].maxlength = maxlength;
511
512 num_muscles++;
513 }
514 }
515
MusclesSet()516 void Skeleton::MusclesSet()
517 {
518 for(int i = 0; i < num_muscles; i++) {
519 muscles[i].length =
520 findDistance(muscles[i].parent1->position,
521 muscles[i].parent2->position);
522 }
523 }
524
FindRotationJoint(int which)525 void Skeleton::FindRotationJoint(int which)
526 {
527 XYZ temppoint1, temppoint2, tempforward;
528 float distance;
529
530 temppoint1 = joints[which].position;
531 temppoint2 = joints[which].parent->position;
532 distance = findDistance(temppoint1, temppoint2);
533 joints[which].rotate2 =
534 asin((temppoint1.y - temppoint2.y) / distance) * RAD2DEG;
535 temppoint1.y = 0;
536 temppoint2.y = 0;
537 joints[which].rotate1 =
538 acos((temppoint1.z - temppoint2.z) / findDistance(temppoint1,
539 temppoint2)) * RAD2DEG;
540 if(temppoint1.x > temppoint2.x)
541 joints[which].rotate1 = 360 - joints[which].rotate1;
542 if(joints[which].label == head)
543 tempforward = specialforward[0];
544 else if(joints[which].label == rightshoulder
545 || joints[which].label == rightelbow
546 || joints[which].label == rightwrist
547 || joints[which].label == righthand)
548 tempforward = specialforward[1];
549 else if(joints[which].label == leftshoulder
550 || joints[which].label == leftelbow
551 || joints[which].label == leftwrist
552 || joints[which].label == lefthand)
553 tempforward = specialforward[2];
554 else if(joints[which].label == righthip || joints[which].label == rightknee
555 || joints[which].label == rightankle)
556 tempforward = specialforward[3];
557 else if(joints[which].label == lefthip || joints[which].label == leftknee
558 || joints[which].label == leftankle)
559 tempforward = specialforward[4];
560 else if(!joints[which].lower)
561 tempforward = forward;
562 else if(joints[which].lower)
563 tempforward = lowforward;
564 tempforward = DoRotation(tempforward, 0, joints[which].rotate1 - 90, 0);
565 tempforward = DoRotation(tempforward, 0, 0, joints[which].rotate2 - 90);
566 tempforward.y = 0;
567 Normalise(&tempforward);
568 joints[which].rotate3 = acos(0 - tempforward.z) * RAD2DEG;
569 if(0 > tempforward.x)
570 joints[which].rotate3 = 360 - joints[which].rotate3;
571 }
572
FindRotationMuscle(int which)573 void Skeleton::FindRotationMuscle(int which)
574 {
575 XYZ temppoint1, temppoint2, tempforward;
576 float distance;
577
578 temppoint1 = muscles[which].parent1->position;
579 temppoint2 = muscles[which].parent2->position;
580 distance = findDistance(temppoint1, temppoint2);
581 muscles[which].rotate2 =
582 asin((temppoint1.y - temppoint2.y) / distance) * RAD2DEG;
583 temppoint1.y = 0;
584 temppoint2.y = 0;
585 muscles[which].rotate1 =
586 acos((temppoint1.z - temppoint2.z) / findDistance(temppoint1,
587 temppoint2));
588 muscles[which].rotate1 *= 360 / 6.28;
589 if(temppoint1.x > temppoint2.x)
590 muscles[which].rotate1 = 360 - muscles[which].rotate1;
591 if(muscles[which].parent1->label == head)
592 tempforward = specialforward[0];
593 else if(muscles[which].parent1->label == rightshoulder
594 || muscles[which].parent1->label == rightelbow
595 || muscles[which].parent1->label == rightwrist)
596 tempforward = specialforward[1];
597 else if(muscles[which].parent1->label == leftshoulder
598 || muscles[which].parent1->label == leftelbow
599 || muscles[which].parent1->label == leftwrist)
600 tempforward = specialforward[2];
601 else if(muscles[which].parent1->label == righthip
602 || muscles[which].parent1->label == rightknee
603 || muscles[which].parent1->label == rightankle)
604 tempforward = specialforward[3];
605 else if(muscles[which].parent1->label == lefthip
606 || muscles[which].parent1->label == leftknee
607 || muscles[which].parent1->label == leftankle)
608 tempforward = specialforward[4];
609 else if(!muscles[which].parent1->lower)
610 tempforward = forward;
611 else if(muscles[which].parent1->lower)
612 tempforward = lowforward;
613 tempforward = DoRotation(tempforward, 0, muscles[which].rotate1 - 90, 0);
614 tempforward = DoRotation(tempforward, 0, 0, muscles[which].rotate2 - 90);
615 tempforward.y = 0;
616 Normalise(&tempforward);
617 muscles[which].rotate3 = acos(0 - tempforward.z) * RAD2DEG;
618 for(int i = 0; i < num_joints; i++) {
619 if(&joints[i] == muscles[which].parent1) {
620 joints[i].rotate1 = muscles[which].rotate1;
621 joints[i].rotate2 = muscles[which].rotate2;
622 joints[i].rotate3 = muscles[which].rotate3;
623 }
624 }
625 if(0 > tempforward.x)
626 muscles[which].rotate3 = 360 - muscles[which].rotate3;
627 }
628
629 extern Skeleton testskeleton;
630
Load(char * fileName)631 void Animation::Load(char *fileName)
632 {
633 files.OpenFile((unsigned char *)fileName);
634 if(files.sFile) {
635 ReadInt(files.sFile, 1, &numframes);
636 for(int i = 0; i < numframes; i++) {
637 for(int j = 0; j < max_joints; j++) {
638 ReadXYZ(files.sFile, 1, &position[j][i]);
639 }
640 for(int j = 0; j < max_joints; j++) {
641 ReadFloat(files.sFile, 1, &twist[j][i]);
642 }
643 for(int j = 0; j < max_joints; j++) {
644 ReadBool(files.sFile, 1, &onground[j][i]);
645 }
646 ReadFloat(files.sFile, 1, &speed[i]);
647 ReadFloat(files.sFile, 1, &gunrotation[i]);
648 }
649 for(int i = 0; i < numframes; i++) {
650 for(int j = 0; j < max_joints; j++) {
651 ReadFloat(files.sFile, 1, &twist2[j][i]);
652 }
653 }
654 }
655
656 files.EndLoad();
657
658 for(int j = 0; j < numframes; j++) {
659 for(int i = 0; i < testskeleton.num_joints; i++) {
660 testskeleton.joints[i].position = position[i][j];
661 }
662 //Find forward vectors
663 CrossProduct(testskeleton.joints[testskeleton.forwardjoints[1]].position -
664 testskeleton.joints[testskeleton.forwardjoints[0]].position,
665 testskeleton.joints[testskeleton.forwardjoints[2]].position -
666 testskeleton.joints[testskeleton.forwardjoints[0]].position,
667 &testskeleton.forward);
668 Normalise(&testskeleton.forward);
669
670 CrossProduct(testskeleton.joints[testskeleton.lowforwardjoints[1]].
671 position -
672 testskeleton.joints[testskeleton.lowforwardjoints[0]].position,
673 testskeleton.joints[testskeleton.lowforwardjoints[2]].
674 position -
675 testskeleton.joints[testskeleton.lowforwardjoints[0]].position,
676 &testskeleton.lowforward);
677 Normalise(&testskeleton.lowforward);
678
679 //Special forwards
680 testskeleton.specialforward[0] = testskeleton.forward;
681
682 testskeleton.specialforward[1] =
683 testskeleton.joints[testskeleton.jointlabels[rightshoulder]].position +
684 testskeleton.joints[testskeleton.jointlabels[rightwrist]].position;
685 testskeleton.specialforward[1] =
686 testskeleton.joints[testskeleton.jointlabels[rightelbow]].position -
687 testskeleton.specialforward[1] / 2;
688 testskeleton.specialforward[1] += testskeleton.forward * .2;
689 Normalise(&testskeleton.specialforward[1]);
690 testskeleton.specialforward[2] =
691 testskeleton.joints[testskeleton.jointlabels[leftshoulder]].position +
692 testskeleton.joints[testskeleton.jointlabels[leftwrist]].position;
693 testskeleton.specialforward[2] =
694 testskeleton.joints[testskeleton.jointlabels[leftelbow]].position -
695 testskeleton.specialforward[2] / 2;
696 testskeleton.specialforward[2] += testskeleton.forward * .2;
697 Normalise(&testskeleton.specialforward[2]);
698
699 testskeleton.specialforward[3] =
700 testskeleton.joints[testskeleton.jointlabels[righthip]].position +
701 testskeleton.joints[testskeleton.jointlabels[rightankle]].position;
702 testskeleton.specialforward[3] =
703 testskeleton.specialforward[3] / 2 -
704 testskeleton.joints[testskeleton.jointlabels[rightknee]].position;
705 testskeleton.specialforward[3] += testskeleton.lowforward * .2;
706 Normalise(&testskeleton.specialforward[3]);
707 testskeleton.specialforward[4] =
708 testskeleton.joints[testskeleton.jointlabels[lefthip]].position +
709 testskeleton.joints[testskeleton.jointlabels[leftankle]].position;
710 testskeleton.specialforward[4] =
711 testskeleton.specialforward[4] / 2 -
712 testskeleton.joints[testskeleton.jointlabels[leftknee]].position;
713 testskeleton.specialforward[4] += testskeleton.lowforward * .2;
714 Normalise(&testskeleton.specialforward[4]);
715
716 //Find joint rotations
717 for(int i = 0; i < testskeleton.num_joints; i++) {
718 if(testskeleton.joints[i].hasparent && testskeleton.joints[i].visible) {
719 testskeleton.FindRotationJoint(i);
720 }
721 }
722 for(int i = 0; i < testskeleton.num_muscles; i++) {
723 if(testskeleton.muscles[i].visible) {
724 testskeleton.FindRotationMuscle(i);
725 }
726 }
727 for(int i = 0; i < testskeleton.num_muscles; i++) {
728 if(testskeleton.muscles[i].visible) {
729 mrotate1[i][j] = testskeleton.muscles[i].rotate1;
730 mrotate2[i][j] = testskeleton.muscles[i].rotate2;
731 mrotate3[i][j] = testskeleton.muscles[i].rotate3;
732 if(j != 0 && mrotate3[i][j] > mrotate3[i][j - 1] + 180)
733 mrotate3[i][j] -= 360;
734 if(j != 0 && mrotate3[i][j] < mrotate3[i][j - 1] - 180)
735 mrotate3[i][j] += 360;
736 if(j != 0 && mrotate2[i][j] > mrotate2[i][j - 1] + 180)
737 mrotate2[i][j] -= 360;
738 if(j != 0 && mrotate2[i][j] < mrotate2[i][j - 1] - 180)
739 mrotate2[i][j] += 360;
740 if(j != 0 && mrotate1[i][j] > mrotate1[i][j - 1] + 180)
741 mrotate1[i][j] -= 360;
742 if(j != 0 && mrotate1[i][j] < mrotate1[i][j - 1] - 180)
743 mrotate1[i][j] += 360;
744 }
745 }
746 for(int i = 0; i < testskeleton.num_joints; i++) {
747 if(testskeleton.joints[i].hasparent && testskeleton.joints[i].visible) {
748 rotate1[i][j] = testskeleton.joints[i].rotate1;
749 rotate2[i][j] = testskeleton.joints[i].rotate2;
750 rotate3[i][j] = testskeleton.joints[i].rotate3;
751 if(j != 0 && rotate3[i][j] > rotate3[i][j - 1] + 180)
752 rotate3[i][j] -= 360;
753 if(j != 0 && rotate3[i][j] < rotate3[i][j - 1] - 180)
754 rotate3[i][j] += 360;
755 if(j != 0 && rotate2[i][j] > rotate2[i][j - 1] + 180)
756 rotate2[i][j] -= 360;
757 if(j != 0 && rotate2[i][j] < rotate2[i][j - 1] - 180)
758 rotate2[i][j] += 360;
759 if(j != 0 && rotate1[i][j] > rotate1[i][j - 1] + 180)
760 rotate1[i][j] -= 360;
761 if(j != 0 && rotate1[i][j] < rotate1[i][j - 1] - 180)
762 rotate1[i][j] += 360;
763 }
764 }
765 }
766
767 for(int k = 0; k < 2; k++)
768 for(int j = 0; j < numframes; j++) {
769 for(int i = 0; i < testskeleton.num_muscles; i++) {
770 if(testskeleton.muscles[i].visible) {
771 if(j != 0 && mrotate3[i][j] > mrotate3[i][j - 1] + 180)
772 mrotate3[i][j] -= 360;
773 if(j != 0 && mrotate3[i][j] < mrotate3[i][j - 1] - 180)
774 mrotate3[i][j] += 360;
775 if(j != 0 && mrotate2[i][j] > mrotate2[i][j - 1] + 180)
776 mrotate2[i][j] -= 360;
777 if(j != 0 && mrotate2[i][j] < mrotate2[i][j - 1] - 180)
778 mrotate2[i][j] += 360;
779 if(j != 0 && mrotate1[i][j] > mrotate1[i][j - 1] + 180)
780 mrotate1[i][j] -= 360;
781 if(j != 0 && mrotate1[i][j] < mrotate1[i][j - 1] - 180)
782 mrotate1[i][j] += 360;
783
784 if(j == 0 && mrotate3[i][j] > mrotate3[i][numframes - 1] + 180)
785 mrotate3[i][j] -= 360;
786 if(j == 0 && mrotate3[i][j] < mrotate3[i][numframes - 1] - 180)
787 mrotate3[i][j] += 360;
788 if(j == 0 && mrotate2[i][j] > mrotate2[i][numframes - 1] + 180)
789 mrotate2[i][j] -= 360;
790 if(j == 0 && mrotate2[i][j] < mrotate2[i][numframes - 1] - 180)
791 mrotate2[i][j] += 360;
792 if(j == 0 && mrotate1[i][j] > mrotate1[i][numframes - 1] + 180)
793 mrotate1[i][j] -= 360;
794 if(j == 0 && mrotate1[i][j] < mrotate1[i][numframes - 1] - 180)
795 mrotate1[i][j] += 360;
796 }
797 }
798 for(int i = 0; i < testskeleton.num_joints; i++) {
799 if(testskeleton.joints[i].hasparent && testskeleton.joints[i].visible) {
800 if(j != 0 && rotate3[i][j] > rotate3[i][j - 1] + 180)
801 rotate3[i][j] -= 360;
802 if(j != 0 && rotate3[i][j] < rotate3[i][j - 1] - 180)
803 rotate3[i][j] += 360;
804 if(j != 0 && rotate2[i][j] > rotate2[i][j - 1] + 180)
805 rotate2[i][j] -= 360;
806 if(j != 0 && rotate2[i][j] < rotate2[i][j - 1] - 180)
807 rotate2[i][j] += 360;
808 if(j != 0 && rotate1[i][j] > rotate1[i][j - 1] + 180)
809 rotate1[i][j] -= 360;
810 if(j != 0 && rotate1[i][j] < rotate1[i][j - 1] - 180)
811 rotate1[i][j] += 360;
812
813 if(j == 0 && rotate3[i][j] > rotate3[i][numframes - 1] + 180)
814 rotate3[i][j] -= 360;
815 if(j == 0 && rotate3[i][j] < rotate3[i][numframes - 1] - 180)
816 rotate3[i][j] += 360;
817 if(j == 0 && rotate2[i][j] > rotate2[i][numframes - 1] + 180)
818 rotate2[i][j] -= 360;
819 if(j == 0 && rotate2[i][j] < rotate2[i][numframes - 1] - 180)
820 rotate2[i][j] += 360;
821 if(j == 0 && rotate1[i][j] > rotate1[i][numframes - 1] + 180)
822 rotate1[i][j] -= 360;
823 if(j == 0 && rotate1[i][j] < rotate1[i][numframes - 1] - 180)
824 rotate1[i][j] += 360;
825 }
826 }
827 }
828 }
829
Load(char * fileName,float rotate)830 void Animation::Load(char *fileName, float rotate)
831 {
832 files.OpenFile((unsigned char *)fileName);
833 if(files.sFile) {
834 ReadInt(files.sFile, 1, &numframes);
835 for(int i = 0; i < numframes; i++) {
836 for(int j = 0; j < max_joints; j++) {
837 ReadXYZ(files.sFile, 1, &position[j][i]);
838 position[j][i] = DoRotation(position[j][i], 0, rotate, 0);
839 }
840 for(int j = 0; j < max_joints; j++) {
841 ReadFloat(files.sFile, 1, &twist[j][i]);
842 }
843 for(int j = 0; j < max_joints; j++) {
844 ReadBool(files.sFile, 1, &onground[j][i]);
845 }
846 ReadFloat(files.sFile, 1, &speed[i]);
847 ReadFloat(files.sFile, 1, &gunrotation[i]);
848 }
849 for(int i = 0; i < numframes; i++) {
850 for(int j = 0; j < max_joints; j++) {
851 ReadFloat(files.sFile, 1, &twist2[j][i]);
852 }
853 }
854 }
855 files.EndLoad();
856
857 for(int j = 0; j < numframes; j++) {
858 for(int i = 0; i < testskeleton.num_joints; i++) {
859 testskeleton.joints[i].position = position[i][j];
860 }
861 //Find forward vectors
862 CrossProduct(testskeleton.joints[testskeleton.forwardjoints[1]].position -
863 testskeleton.joints[testskeleton.forwardjoints[0]].position,
864 testskeleton.joints[testskeleton.forwardjoints[2]].position -
865 testskeleton.joints[testskeleton.forwardjoints[0]].position,
866 &testskeleton.forward);
867 Normalise(&testskeleton.forward);
868
869 CrossProduct(testskeleton.joints[testskeleton.lowforwardjoints[1]].
870 position -
871 testskeleton.joints[testskeleton.lowforwardjoints[0]].position,
872 testskeleton.joints[testskeleton.lowforwardjoints[2]].
873 position -
874 testskeleton.joints[testskeleton.lowforwardjoints[0]].position,
875 &testskeleton.lowforward);
876 Normalise(&testskeleton.lowforward);
877
878 //Special forwards
879 testskeleton.specialforward[0] = testskeleton.forward;
880
881 testskeleton.specialforward[1] =
882 testskeleton.joints[testskeleton.jointlabels[rightshoulder]].position +
883 testskeleton.joints[testskeleton.jointlabels[rightwrist]].position;
884 testskeleton.specialforward[1] =
885 testskeleton.joints[testskeleton.jointlabels[rightelbow]].position -
886 testskeleton.specialforward[1] / 2;
887 testskeleton.specialforward[1] += testskeleton.forward * .2;
888 Normalise(&testskeleton.specialforward[1]);
889 testskeleton.specialforward[2] =
890 testskeleton.joints[testskeleton.jointlabels[leftshoulder]].position +
891 testskeleton.joints[testskeleton.jointlabels[leftwrist]].position;
892 testskeleton.specialforward[2] =
893 testskeleton.joints[testskeleton.jointlabels[leftelbow]].position -
894 testskeleton.specialforward[2] / 2;
895 testskeleton.specialforward[2] += testskeleton.forward * .2;
896 Normalise(&testskeleton.specialforward[2]);
897
898 testskeleton.specialforward[3] =
899 testskeleton.joints[testskeleton.jointlabels[righthip]].position +
900 testskeleton.joints[testskeleton.jointlabels[rightankle]].position;
901 testskeleton.specialforward[3] =
902 testskeleton.specialforward[3] / 2 -
903 testskeleton.joints[testskeleton.jointlabels[rightknee]].position;
904 testskeleton.specialforward[3] += testskeleton.lowforward * .2;
905 Normalise(&testskeleton.specialforward[3]);
906 testskeleton.specialforward[4] =
907 testskeleton.joints[testskeleton.jointlabels[lefthip]].position +
908 testskeleton.joints[testskeleton.jointlabels[leftankle]].position;
909 testskeleton.specialforward[4] =
910 testskeleton.specialforward[4] / 2 -
911 testskeleton.joints[testskeleton.jointlabels[leftknee]].position;
912 testskeleton.specialforward[4] += testskeleton.lowforward * .2;
913 Normalise(&testskeleton.specialforward[4]);
914
915 //Find joint rotations
916 for(int i = 0; i < testskeleton.num_joints; i++) {
917 if(testskeleton.joints[i].hasparent && testskeleton.joints[i].visible) {
918 testskeleton.FindRotationJoint(i);
919 }
920 }
921 for(int i = 0; i < testskeleton.num_muscles; i++) {
922 if(testskeleton.muscles[i].visible) {
923 testskeleton.FindRotationMuscle(i);
924 }
925 }
926 for(int i = 0; i < testskeleton.num_muscles; i++) {
927 if(testskeleton.muscles[i].visible) {
928 mrotate1[i][j] = testskeleton.muscles[i].rotate1;
929 mrotate2[i][j] = testskeleton.muscles[i].rotate2;
930 mrotate3[i][j] = testskeleton.muscles[i].rotate3;
931 if(j != 0 && mrotate3[i][j] > mrotate3[i][j - 1] + 180)
932 mrotate3[i][j] -= 360;
933 if(j != 0 && mrotate3[i][j] < mrotate3[i][j - 1] - 180)
934 mrotate3[i][j] += 360;
935 if(j != 0 && mrotate2[i][j] > mrotate2[i][j - 1] + 180)
936 mrotate2[i][j] -= 360;
937 if(j != 0 && mrotate2[i][j] < mrotate2[i][j - 1] - 180)
938 mrotate2[i][j] += 360;
939 if(j != 0 && mrotate1[i][j] > mrotate1[i][j - 1] + 180)
940 mrotate1[i][j] -= 360;
941 if(j != 0 && mrotate1[i][j] < mrotate1[i][j - 1] - 180)
942 mrotate1[i][j] += 360;
943 }
944 }
945 for(int i = 0; i < testskeleton.num_joints; i++) {
946 if(testskeleton.joints[i].hasparent && testskeleton.joints[i].visible) {
947 rotate1[i][j] = testskeleton.joints[i].rotate1;
948 rotate2[i][j] = testskeleton.joints[i].rotate2;
949 rotate3[i][j] = testskeleton.joints[i].rotate3;
950 if(j != 0 && rotate3[i][j] > rotate3[i][j - 1] + 180)
951 rotate3[i][j] -= 360;
952 if(j != 0 && rotate3[i][j] < rotate3[i][j - 1] - 180)
953 rotate3[i][j] += 360;
954 if(j != 0 && rotate2[i][j] > rotate2[i][j - 1] + 180)
955 rotate2[i][j] -= 360;
956 if(j != 0 && rotate2[i][j] < rotate2[i][j - 1] - 180)
957 rotate2[i][j] += 360;
958 if(j != 0 && rotate1[i][j] > rotate1[i][j - 1] + 180)
959 rotate1[i][j] -= 360;
960 if(j != 0 && rotate1[i][j] < rotate1[i][j - 1] - 180)
961 rotate1[i][j] += 360;
962 }
963 }
964 }
965
966 for(int k = 0; k < 2; k++)
967 for(int j = 0; j < numframes; j++) {
968 for(int i = 0; i < testskeleton.num_muscles; i++) {
969 if(testskeleton.muscles[i].visible) {
970 if(j != 0 && mrotate3[i][j] > mrotate3[i][j - 1] + 180)
971 mrotate3[i][j] -= 360;
972 if(j != 0 && mrotate3[i][j] < mrotate3[i][j - 1] - 180)
973 mrotate3[i][j] += 360;
974 if(j != 0 && mrotate2[i][j] > mrotate2[i][j - 1] + 180)
975 mrotate2[i][j] -= 360;
976 if(j != 0 && mrotate2[i][j] < mrotate2[i][j - 1] - 180)
977 mrotate2[i][j] += 360;
978 if(j != 0 && mrotate1[i][j] > mrotate1[i][j - 1] + 180)
979 mrotate1[i][j] -= 360;
980 if(j != 0 && mrotate1[i][j] < mrotate1[i][j - 1] - 180)
981 mrotate1[i][j] += 360;
982
983 if(j == 0 && mrotate3[i][j] > mrotate3[i][numframes - 1] + 180)
984 mrotate3[i][j] -= 360;
985 if(j == 0 && mrotate3[i][j] < mrotate3[i][numframes - 1] - 180)
986 mrotate3[i][j] += 360;
987 if(j == 0 && mrotate2[i][j] > mrotate2[i][numframes - 1] + 180)
988 mrotate2[i][j] -= 360;
989 if(j == 0 && mrotate2[i][j] < mrotate2[i][numframes - 1] - 180)
990 mrotate2[i][j] += 360;
991 if(j == 0 && mrotate1[i][j] > mrotate1[i][numframes - 1] + 180)
992 mrotate1[i][j] -= 360;
993 if(j == 0 && mrotate1[i][j] < mrotate1[i][numframes - 1] - 180)
994 mrotate1[i][j] += 360;
995 }
996 }
997 for(int i = 0; i < testskeleton.num_joints; i++) {
998 if(testskeleton.joints[i].hasparent && testskeleton.joints[i].visible) {
999 if(j != 0 && rotate3[i][j] > rotate3[i][j - 1] + 180)
1000 rotate3[i][j] -= 360;
1001 if(j != 0 && rotate3[i][j] < rotate3[i][j - 1] - 180)
1002 rotate3[i][j] += 360;
1003 if(j != 0 && rotate2[i][j] > rotate2[i][j - 1] + 180)
1004 rotate2[i][j] -= 360;
1005 if(j != 0 && rotate2[i][j] < rotate2[i][j - 1] - 180)
1006 rotate2[i][j] += 360;
1007 if(j != 0 && rotate1[i][j] > rotate1[i][j - 1] + 180)
1008 rotate1[i][j] -= 360;
1009 if(j != 0 && rotate1[i][j] < rotate1[i][j - 1] - 180)
1010 rotate1[i][j] += 360;
1011
1012 if(j == 0 && rotate3[i][j] > rotate3[i][numframes - 1] + 180)
1013 rotate3[i][j] -= 360;
1014 if(j == 0 && rotate3[i][j] < rotate3[i][numframes - 1] - 180)
1015 rotate3[i][j] += 360;
1016 if(j == 0 && rotate2[i][j] > rotate2[i][numframes - 1] + 180)
1017 rotate2[i][j] -= 360;
1018 if(j == 0 && rotate2[i][j] < rotate2[i][numframes - 1] - 180)
1019 rotate2[i][j] += 360;
1020 if(j == 0 && rotate1[i][j] > rotate1[i][numframes - 1] + 180)
1021 rotate1[i][j] -= 360;
1022 if(j == 0 && rotate1[i][j] < rotate1[i][numframes - 1] - 180)
1023 rotate1[i][j] += 360;
1024 }
1025 }
1026 }
1027 }
1028
Load(char * fileName)1029 void Skeleton::Load(char *fileName)
1030 {
1031 int parentID;
1032 bool what;
1033 files.OpenFile((unsigned char *)fileName);
1034 if(files.sFile) {
1035 ReadInt(files.sFile, 1, &num_joints);
1036 for(int i = 0; i < num_joints; i++) {
1037 ReadXYZ(files.sFile, 1, &joints[i].position);
1038 ReadFloat(files.sFile, 1, &joints[i].length);
1039 ReadFloat(files.sFile, 1, &joints[i].mass);
1040 ReadBool(files.sFile, 1, &joints[i].hasparent);
1041 ReadBool(files.sFile, 1, &joints[i].locked);
1042 ReadInt(files.sFile, 1, &joints[i].modelnum);
1043 ReadBool(files.sFile, 1, &joints[i].visible);
1044 ReadBool(files.sFile, 1, &what);
1045 ReadInt(files.sFile, 1, &joints[i].label);
1046 ReadInt(files.sFile, 1, &joints[i].hasgun);
1047 ReadBool(files.sFile, 1, &joints[i].lower);
1048 ReadInt(files.sFile, 1, &parentID);
1049 if(joints[i].hasparent)
1050 joints[i].parent = &joints[parentID];
1051 joints[i].velocity = 0;
1052 joints[i].oldposition = joints[i].position;
1053 joints[i].existing = 1;
1054 }
1055
1056 ReadInt(files.sFile, 1, &num_muscles);
1057 for(int i = 0; i < num_muscles; i++) {
1058 ReadFloat(files.sFile, 1, &muscles[i].length);
1059 ReadFloat(files.sFile, 1, &muscles[i].targetlength);
1060 ReadFloat(files.sFile, 1, &muscles[i].minlength);
1061 ReadFloat(files.sFile, 1, &muscles[i].maxlength);
1062 ReadFloat(files.sFile, 1, &muscles[i].strength);
1063 ReadInt(files.sFile, 1, &muscles[i].type);
1064 ReadBool(files.sFile, 1, &muscles[i].visible);
1065 ReadInt(files.sFile, 1, &parentID);
1066 muscles[i].parent1 = &joints[parentID];
1067 ReadInt(files.sFile, 1, &parentID);
1068 muscles[i].parent2 = &joints[parentID];
1069 }
1070
1071 for(int j = 0; j < 3; j++) {
1072 ReadInt(files.sFile, 1, &forwardjoints[j]);
1073 }
1074 for(int j = 0; j < 3; j++) {
1075 ReadInt(files.sFile, 1, &lowforwardjoints[j]);
1076 }
1077 }
1078 files.EndLoad();
1079
1080 for(int i = 0; i < num_joints; i++) {
1081 for(int j = 0; j < num_joints; j++) {
1082 if(joints[i].label == j)
1083 jointlabels[j] = i;
1084 }
1085 }
1086
1087 broken = 0;
1088 }
1089