goat3d

view src/xform_node.cc @ 72:36e39632db75

- fixed exporter animation bounds calculation - fixed missing scene name in exported meshes - rewritting goatview as a full GUI app with Qt
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 06 May 2014 03:31:35 +0300
parents 8970ca3d55e0
children da100bf13f7f
line source
1 /*
2 goat3d - 3D scene, character, and animation file format library.
3 Copyright (C) 2013-2014 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <assert.h>
19 #include <algorithm>
20 #include "xform_node.h"
21 #include "anim/anim.h"
22 #include "anim/track.h"
24 using namespace g3dimpl;
26 static inline anm_interpolator track_interpolator(Interp in);
27 static inline anm_extrapolator track_extrapolator(Extrap ex);
29 XFormNode::XFormNode()
30 {
31 anm = new anm_node;
32 anm_init_node(anm);
33 parent = 0;
35 // TODO read them from anm to get the correct initial values
36 interp = INTERP_LINEAR;
37 extrap = EXTRAP_EXTEND;
38 }
40 XFormNode::~XFormNode()
41 {
42 anm_destroy_node(anm);
43 delete anm;
44 }
46 struct anm_node *XFormNode::get_libanim_node() const
47 {
48 return anm;
49 }
51 void XFormNode::set_name(const char *name)
52 {
53 anm_set_node_name(anm, name);
54 }
56 const char *XFormNode::get_name() const
57 {
58 return anm_get_node_name(anm);
59 }
61 void XFormNode::set_interpolator(Interp in)
62 {
63 anm_set_interpolator(anm, track_interpolator(in));
64 interp = in;
65 }
67 Interp XFormNode::get_interpolator() const
68 {
69 return interp;
70 }
72 void XFormNode::set_extrapolator(Extrap ex)
73 {
74 anm_set_extrapolator(anm, track_extrapolator(ex));
75 extrap = ex;
76 }
78 Extrap XFormNode::get_extrapolator() const
79 {
80 return extrap;
81 }
83 XFormNode *XFormNode::get_parent()
84 {
85 return parent;
86 }
88 const XFormNode *XFormNode::get_parent() const
89 {
90 return parent;
91 }
93 void XFormNode::add_child(XFormNode *child)
94 {
95 if(!child || child == this) return;
97 children.push_back(child);
98 anm_link_node(anm, child->anm);
99 child->parent = this;
100 }
102 void XFormNode::remove_child(XFormNode *child)
103 {
104 std::vector<XFormNode*>::iterator it;
105 it = std::find(children.begin(), children.end(), child);
106 if(it != children.end()) {
107 children.erase(it);
108 anm_unlink_node(anm, child->anm);
110 if(child->parent == this) {
111 child->parent = 0;
112 }
113 }
114 }
116 int XFormNode::get_children_count() const
117 {
118 return (int)children.size();
119 }
121 XFormNode *XFormNode::get_child(int idx)
122 {
123 if(idx >= 0 && idx < get_children_count()) {
124 return children[idx];
125 }
126 return 0;
127 }
129 const XFormNode *XFormNode::get_child(int idx) const
130 {
131 if(idx >= 0 && idx < get_children_count()) {
132 return children[idx];
133 }
134 return 0;
135 }
138 void XFormNode::use_animation(int idx)
139 {
140 if(idx >= 0) {
141 anm_use_animation(anm, idx);
142 }
143 }
145 void XFormNode::use_animation(const char *name)
146 {
147 anm_use_animation(anm, anm_find_animation(anm, name));
148 }
150 void XFormNode::use_animation(int aidx, int bidx, float t)
151 {
152 anm_use_animations(anm, aidx, bidx, t);
153 }
155 void XFormNode::use_animation(const char *aname, const char *bname, float t)
156 {
157 int aidx = anm_find_animation(anm, aname);
158 int bidx = anm_find_animation(anm, bname);
160 if(aidx == -1) {
161 use_animation(bidx);
162 }
163 if(bidx == -1) {
164 use_animation(aidx);
165 }
166 anm_use_animations(anm, aidx, bidx, t);
167 }
169 int XFormNode::get_active_animation_index(int which) const
170 {
171 return anm_get_active_animation_index(anm, which);
172 }
174 float XFormNode::get_active_animation_mix() const
175 {
176 return anm_get_active_animation_mix(anm);
177 }
179 int XFormNode::get_animation_count() const
180 {
181 return anm_get_animation_count(anm);
182 }
184 void XFormNode::add_animation(const char *name)
185 {
186 int idx = get_animation_count();
188 anm_add_animation(anm);
189 use_animation(idx);
191 if(name) {
192 set_animation_name(name);
193 }
194 }
196 void XFormNode::set_animation_name(const char *name)
197 {
198 anm_set_active_animation_name(anm, name);
199 }
201 const char *XFormNode::get_animation_name() const
202 {
203 return anm_get_active_animation_name(anm);
204 }
206 static const int track_type_base[] = {ANM_TRACK_POS_X, ANM_TRACK_ROT_X, ANM_TRACK_SCL_X};
207 static const int track_type_nelem[] = {3, 4, 3};
209 int XFormNode::get_key_count(int trackid) const
210 {
211 struct anm_animation *anim = anm_get_active_animation(anm, 0);
212 if(anim) {
213 return anim->tracks[track_type_base[trackid]].count;
214 }
215 return 0;
216 }
218 int XFormNode::get_position_key_count() const
219 {
220 return get_key_count(POSITION_TRACK);
221 }
223 int XFormNode::get_rotation_key_count() const
224 {
225 return get_key_count(ROTATION_TRACK);
226 }
228 int XFormNode::get_scaling_key_count() const
229 {
230 return get_key_count(SCALING_TRACK);
231 }
233 long XFormNode::get_key_time(int trackid, int idx) const
234 {
235 struct anm_animation *anim = anm_get_active_animation(anm, 0);
236 struct anm_keyframe *key = anm_get_keyframe(anim->tracks + track_type_base[trackid], idx);
237 return ANM_TM2MSEC(key->time);
238 }
240 long XFormNode::get_position_key_time(int idx) const
241 {
242 return get_key_time(POSITION_TRACK, idx);
243 }
245 long XFormNode::get_rotation_key_time(int idx) const
246 {
247 return get_key_time(ROTATION_TRACK, idx);
248 }
250 long XFormNode::get_scaling_key_time(int idx) const
251 {
252 return get_key_time(SCALING_TRACK, idx);
253 }
255 int XFormNode::get_key_value(int trackid, int idx, float *val) const
256 {
257 struct anm_animation *anim = anm_get_active_animation(anm, 0);
259 int nelem = track_type_nelem[trackid];
260 for(int i=0; i<nelem; i++) {
261 struct anm_keyframe *key = anm_get_keyframe(anim->tracks + track_type_base[trackid] + i, idx);
262 val[i] = key->val;
263 }
264 return nelem;
265 }
267 Vector3 XFormNode::get_position_key_value(int idx) const
268 {
269 float val[3];
270 get_key_value(POSITION_TRACK, idx, val);
271 return Vector3(val[0], val[1], val[2]);
272 }
274 Quaternion XFormNode::get_rotation_key_value(int idx) const
275 {
276 float val[4];
277 get_key_value(ROTATION_TRACK, idx, val);
278 return Quaternion(val[3], val[0], val[1], val[2]);
279 }
281 Vector3 XFormNode::get_scaling_key_value(int idx) const
282 {
283 float val[3];
284 get_key_value(SCALING_TRACK, idx, val);
285 return Vector3(val[0], val[1], val[2]);
286 }
288 void XFormNode::set_position(const Vector3 &pos, long tmsec)
289 {
290 anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec));
291 }
293 Vector3 XFormNode::get_node_position(long tmsec) const
294 {
295 vec3_t p = anm_get_node_position(anm, ANM_MSEC2TM(tmsec));
296 return Vector3(p.x, p.y, p.z);
297 }
299 void XFormNode::set_rotation(const Quaternion &quat, long tmsec)
300 {
301 anm_set_rotation(anm, quat_cons(quat.s, quat.v.x, quat.v.y, quat.v.z), ANM_MSEC2TM(tmsec));
302 }
304 Quaternion XFormNode::get_node_rotation(long tmsec) const
305 {
306 quat_t q = anm_get_node_rotation(anm, ANM_MSEC2TM(tmsec));
307 return Quaternion(q.w, q.x, q.y, q.z);
308 }
310 void XFormNode::set_scaling(const Vector3 &pos, long tmsec)
311 {
312 anm_set_scaling(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec));
313 }
315 Vector3 XFormNode::get_node_scaling(long tmsec) const
316 {
317 vec3_t s = anm_get_node_scaling(anm, ANM_MSEC2TM(tmsec));
318 return Vector3(s.x, s.y, s.z);
319 }
321 // these take hierarchy into account
322 Vector3 XFormNode::get_position(long tmsec) const
323 {
324 vec3_t v = anm_get_position(anm, ANM_MSEC2TM(tmsec));
325 return Vector3(v.x, v.y, v.z);
326 }
328 Quaternion XFormNode::get_rotation(long tmsec) const
329 {
330 quat_t q = anm_get_rotation(anm, tmsec);
331 return Quaternion(q.w, q.x, q.y, q.z);
332 }
334 Vector3 XFormNode::get_scaling(long tmsec) const
335 {
336 vec3_t v = anm_get_scaling(anm, ANM_MSEC2TM(tmsec));
337 return Vector3(v.x, v.y, v.z);
338 }
340 void XFormNode::set_pivot(const Vector3 &pivot)
341 {
342 anm_set_pivot(anm, v3_cons(pivot.x, pivot.y, pivot.z));
343 }
345 Vector3 XFormNode::get_pivot() const
346 {
347 vec3_t p = anm_get_pivot(anm);
348 return Vector3(p.x, p.y, p.z);
349 }
351 void XFormNode::set_local_matrix(const Matrix4x4 &mat)
352 {
353 local_matrix = mat;
354 }
356 const Matrix4x4 &XFormNode::get_local_matrix() const
357 {
358 return local_matrix;
359 }
361 void XFormNode::set_bone_matrix(const Matrix4x4 &bmat)
362 {
363 bone_matrix = bmat;
364 }
366 const Matrix4x4 &XFormNode::get_bone_matrix() const
367 {
368 return bone_matrix;
369 }
371 #define FOO
373 void XFormNode::get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const
374 {
375 anm_time_t tm = ANM_MSEC2TM(tmsec);
377 if(mat) {
378 anm_get_node_matrix(anm, (scalar_t(*)[4])mat, tm);
379 #ifdef FOO
380 *mat = local_matrix * *mat;
381 #else
382 *mat = *mat * local_matrix;
383 #endif
384 }
385 if(inv_mat) {
386 anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm);
387 }
388 }
390 void XFormNode::get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const
391 {
392 anm_time_t tm = ANM_MSEC2TM(tmsec);
394 if(mat) {
395 anm_get_matrix(anm, (scalar_t(*)[4])mat, tm);
396 #ifdef FOO
397 *mat = local_matrix * *mat;
398 #else
399 *mat = *mat * local_matrix;
400 #endif
401 }
402 if(inv_mat) {
403 anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm);
404 }
405 }
408 // ---- Track ----
410 Track::Track()
411 {
412 trk = new anm_track;
413 anm_init_track(trk);
414 }
416 Track::~Track()
417 {
418 anm_destroy_track(trk);
419 delete trk;
420 }
422 Track::Track(const Track &rhs)
423 {
424 trk = new anm_track;
425 anm_init_track(trk);
426 anm_copy_track(trk, rhs.trk);
427 interp = rhs.interp;
428 extrap = rhs.extrap;
429 }
431 Track &Track::operator =(const Track &rhs)
432 {
433 if(&rhs == this) {
434 return *this;
435 }
437 anm_copy_track(trk, rhs.trk);
438 interp = rhs.interp;
439 extrap = rhs.extrap;
440 return *this;
441 }
444 void Track::set_interpolator(Interp in)
445 {
446 anm_set_track_interpolator(trk, track_interpolator(in));
447 interp = in;
448 }
450 Interp Track::get_interpolator() const
451 {
452 return interp;
453 }
455 void Track::set_extrapolator(Extrap ex)
456 {
457 anm_set_track_extrapolator(trk, track_extrapolator(ex));
458 extrap = ex;
459 }
461 Extrap Track::get_extrapolator() const
462 {
463 return extrap;
464 }
466 void Track::set_default(double def)
467 {
468 anm_set_track_default(trk, def);
469 }
471 void Track::set_value(float val, long tmsec)
472 {
473 anm_set_value(trk, ANM_MSEC2TM(tmsec), val);
474 }
476 float Track::get_value(long tmsec) const
477 {
478 return anm_get_value(trk, ANM_MSEC2TM(tmsec));
479 }
481 float Track::operator ()(long tmsec) const
482 {
483 return anm_get_value(trk, ANM_MSEC2TM(tmsec));
484 }
487 // ---- Track3 ----
489 void Track3::set_interpolator(Interp in)
490 {
491 for(int i=0; i<3; i++) {
492 track[i].set_interpolator(in);
493 }
494 }
496 Interp Track3::get_interpolator() const
497 {
498 return track[0].get_interpolator();
499 }
501 void Track3::set_extrapolator(Extrap ex)
502 {
503 for(int i=0; i<3; i++) {
504 track[i].set_extrapolator(ex);
505 }
506 }
508 Extrap Track3::get_extrapolator() const
509 {
510 return track[0].get_extrapolator();
511 }
513 void Track3::set_default(const Vector3 &def)
514 {
515 for(int i=0; i<3; i++) {
516 track[i].set_default(def[i]);
517 }
518 }
520 void Track3::set_value(const Vector3 &val, long tmsec)
521 {
522 for(int i=0; i<3; i++) {
523 track[i].set_value(val[i], tmsec);
524 }
525 }
527 Vector3 Track3::get_value(long tmsec) const
528 {
529 return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec));
530 }
532 Vector3 Track3::operator ()(long tmsec) const
533 {
534 return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec));
535 }
538 static inline anm_interpolator track_interpolator(Interp in)
539 {
540 switch(in) {
541 case INTERP_STEP:
542 return ANM_INTERP_STEP;
543 case INTERP_LINEAR:
544 return ANM_INTERP_LINEAR;
545 case INTERP_CUBIC:
546 return ANM_INTERP_CUBIC;
547 }
549 assert(0);
550 return ANM_INTERP_STEP;
551 }
553 static inline anm_extrapolator track_extrapolator(Extrap ex)
554 {
555 switch(ex) {
556 case EXTRAP_EXTEND:
557 return ANM_EXTRAP_EXTEND;
558 case EXTRAP_CLAMP:
559 return ANM_EXTRAP_CLAMP;
560 case EXTRAP_REPEAT:
561 return ANM_EXTRAP_REPEAT;
562 }
564 assert(0);
565 return ANM_EXTRAP_EXTEND;
566 }