goat3d

view src/xform_node.cc @ 103:45a9d493e98c

fixed the input latency issue by calling QWidget::update() instead of QGLWidget::updateGL() update schedules an update instead of redrawing immediately.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 12 Sep 2015 17:40:02 +0300
parents 8ecaf9cd3ce7
children
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 XFormNode *XFormNode::get_root()
94 {
95 if(!parent) return this;
96 return parent->get_root();
97 }
99 const XFormNode *XFormNode::get_root() const
100 {
101 if(!parent) return this;
102 return parent->get_root();
103 }
105 void XFormNode::add_child(XFormNode *child)
106 {
107 if(!child || child == this) return;
109 children.push_back(child);
110 anm_link_node(anm, child->anm);
111 child->parent = this;
112 }
114 void XFormNode::remove_child(XFormNode *child)
115 {
116 std::vector<XFormNode*>::iterator it;
117 it = std::find(children.begin(), children.end(), child);
118 if(it != children.end()) {
119 children.erase(it);
120 anm_unlink_node(anm, child->anm);
122 if(child->parent == this) {
123 child->parent = 0;
124 }
125 }
126 }
128 int XFormNode::get_children_count() const
129 {
130 return (int)children.size();
131 }
133 XFormNode *XFormNode::get_child(int idx)
134 {
135 if(idx >= 0 && idx < get_children_count()) {
136 return children[idx];
137 }
138 return 0;
139 }
141 const XFormNode *XFormNode::get_child(int idx) const
142 {
143 if(idx >= 0 && idx < get_children_count()) {
144 return children[idx];
145 }
146 return 0;
147 }
150 void XFormNode::use_animation(int idx)
151 {
152 if(idx >= 0) {
153 anm_use_animation(anm, idx);
154 }
155 }
157 void XFormNode::use_animation(const char *name)
158 {
159 anm_use_animation(anm, anm_find_animation(anm, name));
160 }
162 void XFormNode::use_animation(int aidx, int bidx, float t)
163 {
164 anm_use_animations(anm, aidx, bidx, t);
165 }
167 void XFormNode::use_animation(const char *aname, const char *bname, float t)
168 {
169 int aidx = anm_find_animation(anm, aname);
170 int bidx = anm_find_animation(anm, bname);
172 if(aidx == -1) {
173 use_animation(bidx);
174 }
175 if(bidx == -1) {
176 use_animation(aidx);
177 }
178 anm_use_animations(anm, aidx, bidx, t);
179 }
181 int XFormNode::get_active_animation_index(int which) const
182 {
183 return anm_get_active_animation_index(anm, which);
184 }
186 float XFormNode::get_active_animation_mix() const
187 {
188 return anm_get_active_animation_mix(anm);
189 }
191 int XFormNode::get_animation_count() const
192 {
193 return anm_get_animation_count(anm);
194 }
196 void XFormNode::add_animation(const char *name)
197 {
198 int idx = get_animation_count();
200 anm_add_animation(anm);
201 use_animation(idx);
203 if(name) {
204 set_animation_name(name);
205 }
206 }
208 void XFormNode::set_animation_name(const char *name)
209 {
210 anm_set_active_animation_name(anm, name);
211 }
213 const char *XFormNode::get_animation_name() const
214 {
215 return anm_get_active_animation_name(anm);
216 }
218 bool XFormNode::get_timeline_bounds(long *start, long *end)
219 {
220 long node_start = LONG_MAX;
221 long node_end = LONG_MIN;
223 for(int i=0; i<3; i++) {
224 int nkeys = get_key_count(i);
225 if(nkeys > 0) {
226 long tmp = get_key_time(i, 0);
227 if(tmp < node_start) node_start = tmp;
228 tmp = get_key_time(i, nkeys - 1);
229 if(tmp > node_end) node_end = tmp;
230 }
231 }
233 for(size_t i=0; i<children.size(); i++) {
234 long cstart, cend;
235 if(children[i]->get_timeline_bounds(&cstart, &cend)) {
236 if(cstart < node_start) node_start = cstart;
237 if(cend > node_end) node_end = cend;
238 }
239 }
241 if(node_start != LONG_MAX) {
242 *start = node_start;
243 *end = node_end;
244 return true;
245 }
246 return false;
247 }
249 static const int track_type_base[] = {ANM_TRACK_POS_X, ANM_TRACK_ROT_X, ANM_TRACK_SCL_X};
250 static const int track_type_nelem[] = {3, 4, 3};
252 int XFormNode::get_key_count(int trackid) const
253 {
254 struct anm_animation *anim = anm_get_active_animation(anm, 0);
255 if(anim) {
256 return anim->tracks[track_type_base[trackid]].count;
257 }
258 return 0;
259 }
261 int XFormNode::get_position_key_count() const
262 {
263 return get_key_count(POSITION_TRACK);
264 }
266 int XFormNode::get_rotation_key_count() const
267 {
268 return get_key_count(ROTATION_TRACK);
269 }
271 int XFormNode::get_scaling_key_count() const
272 {
273 return get_key_count(SCALING_TRACK);
274 }
276 long XFormNode::get_key_time(int trackid, int idx) const
277 {
278 struct anm_animation *anim = anm_get_active_animation(anm, 0);
279 struct anm_keyframe *key = anm_get_keyframe(anim->tracks + track_type_base[trackid], idx);
280 return ANM_TM2MSEC(key->time);
281 }
283 long XFormNode::get_position_key_time(int idx) const
284 {
285 return get_key_time(POSITION_TRACK, idx);
286 }
288 long XFormNode::get_rotation_key_time(int idx) const
289 {
290 return get_key_time(ROTATION_TRACK, idx);
291 }
293 long XFormNode::get_scaling_key_time(int idx) const
294 {
295 return get_key_time(SCALING_TRACK, idx);
296 }
298 int XFormNode::get_key_value(int trackid, int idx, float *val) const
299 {
300 struct anm_animation *anim = anm_get_active_animation(anm, 0);
302 int nelem = track_type_nelem[trackid];
303 for(int i=0; i<nelem; i++) {
304 struct anm_keyframe *key = anm_get_keyframe(anim->tracks + track_type_base[trackid] + i, idx);
305 val[i] = key->val;
306 }
307 return nelem;
308 }
310 Vector3 XFormNode::get_position_key_value(int idx) const
311 {
312 float val[3];
313 get_key_value(POSITION_TRACK, idx, val);
314 return Vector3(val[0], val[1], val[2]);
315 }
317 Quaternion XFormNode::get_rotation_key_value(int idx) const
318 {
319 float val[4];
320 get_key_value(ROTATION_TRACK, idx, val);
321 return Quaternion(val[3], val[0], val[1], val[2]);
322 }
324 Vector3 XFormNode::get_scaling_key_value(int idx) const
325 {
326 float val[3];
327 get_key_value(SCALING_TRACK, idx, val);
328 return Vector3(val[0], val[1], val[2]);
329 }
331 void XFormNode::set_position(const Vector3 &pos, long tmsec)
332 {
333 anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec));
334 }
336 Vector3 XFormNode::get_node_position(long tmsec) const
337 {
338 vec3_t p = anm_get_node_position(anm, ANM_MSEC2TM(tmsec));
339 return Vector3(p.x, p.y, p.z);
340 }
342 void XFormNode::set_rotation(const Quaternion &quat, long tmsec)
343 {
344 anm_set_rotation(anm, quat_cons(quat.s, quat.v.x, quat.v.y, quat.v.z), ANM_MSEC2TM(tmsec));
345 }
347 Quaternion XFormNode::get_node_rotation(long tmsec) const
348 {
349 quat_t q = anm_get_node_rotation(anm, ANM_MSEC2TM(tmsec));
350 return Quaternion(q.w, q.x, q.y, q.z);
351 }
353 void XFormNode::set_scaling(const Vector3 &pos, long tmsec)
354 {
355 anm_set_scaling(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec));
356 }
358 Vector3 XFormNode::get_node_scaling(long tmsec) const
359 {
360 vec3_t s = anm_get_node_scaling(anm, ANM_MSEC2TM(tmsec));
361 return Vector3(s.x, s.y, s.z);
362 }
364 // these take hierarchy into account
365 Vector3 XFormNode::get_position(long tmsec) const
366 {
367 vec3_t v = anm_get_position(anm, ANM_MSEC2TM(tmsec));
368 return Vector3(v.x, v.y, v.z);
369 }
371 Quaternion XFormNode::get_rotation(long tmsec) const
372 {
373 quat_t q = anm_get_rotation(anm, tmsec);
374 return Quaternion(q.w, q.x, q.y, q.z);
375 }
377 Vector3 XFormNode::get_scaling(long tmsec) const
378 {
379 vec3_t v = anm_get_scaling(anm, ANM_MSEC2TM(tmsec));
380 return Vector3(v.x, v.y, v.z);
381 }
383 void XFormNode::set_pivot(const Vector3 &pivot)
384 {
385 anm_set_pivot(anm, v3_cons(pivot.x, pivot.y, pivot.z));
386 }
388 Vector3 XFormNode::get_pivot() const
389 {
390 vec3_t p = anm_get_pivot(anm);
391 return Vector3(p.x, p.y, p.z);
392 }
394 void XFormNode::set_local_matrix(const Matrix4x4 &mat)
395 {
396 local_matrix = mat;
397 }
399 const Matrix4x4 &XFormNode::get_local_matrix() const
400 {
401 return local_matrix;
402 }
404 void XFormNode::set_bone_matrix(const Matrix4x4 &bmat)
405 {
406 bone_matrix = bmat;
407 }
409 const Matrix4x4 &XFormNode::get_bone_matrix() const
410 {
411 return bone_matrix;
412 }
414 #define FOO
416 void XFormNode::get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const
417 {
418 anm_time_t tm = ANM_MSEC2TM(tmsec);
420 if(mat) {
421 anm_get_node_matrix(anm, (scalar_t(*)[4])mat, tm);
422 #ifdef FOO
423 *mat = local_matrix * *mat;
424 #else
425 *mat = *mat * local_matrix;
426 #endif
427 }
428 if(inv_mat) {
429 anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm);
430 }
431 }
433 void XFormNode::get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const
434 {
435 anm_time_t tm = ANM_MSEC2TM(tmsec);
437 if(mat) {
438 anm_get_matrix(anm, (scalar_t(*)[4])mat, tm);
439 #ifdef FOO
440 *mat = local_matrix * *mat;
441 #else
442 *mat = *mat * local_matrix;
443 #endif
444 }
445 if(inv_mat) {
446 anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm);
447 }
448 }
451 // ---- Track ----
453 Track::Track()
454 {
455 trk = new anm_track;
456 anm_init_track(trk);
457 }
459 Track::~Track()
460 {
461 anm_destroy_track(trk);
462 delete trk;
463 }
465 Track::Track(const Track &rhs)
466 {
467 trk = new anm_track;
468 anm_init_track(trk);
469 anm_copy_track(trk, rhs.trk);
470 interp = rhs.interp;
471 extrap = rhs.extrap;
472 }
474 Track &Track::operator =(const Track &rhs)
475 {
476 if(&rhs == this) {
477 return *this;
478 }
480 anm_copy_track(trk, rhs.trk);
481 interp = rhs.interp;
482 extrap = rhs.extrap;
483 return *this;
484 }
487 void Track::set_interpolator(Interp in)
488 {
489 anm_set_track_interpolator(trk, track_interpolator(in));
490 interp = in;
491 }
493 Interp Track::get_interpolator() const
494 {
495 return interp;
496 }
498 void Track::set_extrapolator(Extrap ex)
499 {
500 anm_set_track_extrapolator(trk, track_extrapolator(ex));
501 extrap = ex;
502 }
504 Extrap Track::get_extrapolator() const
505 {
506 return extrap;
507 }
509 void Track::set_default(double def)
510 {
511 anm_set_track_default(trk, def);
512 }
514 void Track::set_value(float val, long tmsec)
515 {
516 anm_set_value(trk, ANM_MSEC2TM(tmsec), val);
517 }
519 float Track::get_value(long tmsec) const
520 {
521 return anm_get_value(trk, ANM_MSEC2TM(tmsec));
522 }
524 float Track::operator ()(long tmsec) const
525 {
526 return anm_get_value(trk, ANM_MSEC2TM(tmsec));
527 }
530 // ---- Track3 ----
532 void Track3::set_interpolator(Interp in)
533 {
534 for(int i=0; i<3; i++) {
535 track[i].set_interpolator(in);
536 }
537 }
539 Interp Track3::get_interpolator() const
540 {
541 return track[0].get_interpolator();
542 }
544 void Track3::set_extrapolator(Extrap ex)
545 {
546 for(int i=0; i<3; i++) {
547 track[i].set_extrapolator(ex);
548 }
549 }
551 Extrap Track3::get_extrapolator() const
552 {
553 return track[0].get_extrapolator();
554 }
556 void Track3::set_default(const Vector3 &def)
557 {
558 for(int i=0; i<3; i++) {
559 track[i].set_default(def[i]);
560 }
561 }
563 void Track3::set_value(const Vector3 &val, long tmsec)
564 {
565 for(int i=0; i<3; i++) {
566 track[i].set_value(val[i], tmsec);
567 }
568 }
570 Vector3 Track3::get_value(long tmsec) const
571 {
572 return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec));
573 }
575 Vector3 Track3::operator ()(long tmsec) const
576 {
577 return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec));
578 }
581 static inline anm_interpolator track_interpolator(Interp in)
582 {
583 switch(in) {
584 case INTERP_STEP:
585 return ANM_INTERP_STEP;
586 case INTERP_LINEAR:
587 return ANM_INTERP_LINEAR;
588 case INTERP_CUBIC:
589 return ANM_INTERP_CUBIC;
590 }
592 assert(0);
593 return ANM_INTERP_STEP;
594 }
596 static inline anm_extrapolator track_extrapolator(Extrap ex)
597 {
598 switch(ex) {
599 case EXTRAP_EXTEND:
600 return ANM_EXTRAP_EXTEND;
601 case EXTRAP_CLAMP:
602 return ANM_EXTRAP_CLAMP;
603 case EXTRAP_REPEAT:
604 return ANM_EXTRAP_REPEAT;
605 }
607 assert(0);
608 return ANM_EXTRAP_EXTEND;
609 }