goat3d

view src/xform_node.cc @ 54:dad392c710df

added copyright headers and license files + readme
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 17 Apr 2014 08:50:36 +0300
parents 9ef9de80649c
children 8970ca3d55e0
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 children.push_back(child);
96 anm_link_node(anm, child->anm);
97 child->parent = this;
98 }
100 void XFormNode::remove_child(XFormNode *child)
101 {
102 std::vector<XFormNode*>::iterator it;
103 it = std::find(children.begin(), children.end(), child);
104 if(it != children.end()) {
105 children.erase(it);
106 anm_unlink_node(anm, child->anm);
108 if(child->parent == this) {
109 child->parent = 0;
110 }
111 }
112 }
114 int XFormNode::get_children_count() const
115 {
116 return (int)children.size();
117 }
119 XFormNode *XFormNode::get_child(int idx)
120 {
121 if(idx >= 0 && idx < get_children_count()) {
122 return children[idx];
123 }
124 return 0;
125 }
127 const XFormNode *XFormNode::get_child(int idx) const
128 {
129 if(idx >= 0 && idx < get_children_count()) {
130 return children[idx];
131 }
132 return 0;
133 }
136 void XFormNode::use_animation(int idx)
137 {
138 if(idx >= 0) {
139 anm_use_animation(anm, idx);
140 }
141 }
143 void XFormNode::use_animation(const char *name)
144 {
145 anm_use_animation(anm, anm_find_animation(anm, name));
146 }
148 void XFormNode::use_animation(int aidx, int bidx, float t)
149 {
150 anm_use_animations(anm, aidx, bidx, t);
151 }
153 void XFormNode::use_animation(const char *aname, const char *bname, float t)
154 {
155 int aidx = anm_find_animation(anm, aname);
156 int bidx = anm_find_animation(anm, bname);
158 if(aidx == -1) {
159 use_animation(bidx);
160 }
161 if(bidx == -1) {
162 use_animation(aidx);
163 }
164 anm_use_animations(anm, aidx, bidx, t);
165 }
167 int XFormNode::get_active_animation_index(int which) const
168 {
169 return anm_get_active_animation_index(anm, which);
170 }
172 float XFormNode::get_active_animation_mix() const
173 {
174 return anm_get_active_animation_mix(anm);
175 }
177 int XFormNode::get_animation_count() const
178 {
179 return anm_get_animation_count(anm);
180 }
182 void XFormNode::add_animation(const char *name)
183 {
184 int idx = get_animation_count();
186 anm_add_animation(anm);
187 use_animation(idx);
189 if(name) {
190 set_animation_name(name);
191 }
192 }
194 void XFormNode::set_animation_name(const char *name)
195 {
196 anm_set_active_animation_name(anm, name);
197 }
199 const char *XFormNode::get_animation_name() const
200 {
201 return anm_get_active_animation_name(anm);
202 }
204 static const int track_type_base[] = {ANM_TRACK_POS_X, ANM_TRACK_ROT_X, ANM_TRACK_SCL_X};
205 static const int track_type_nelem[] = {3, 4, 3};
207 int XFormNode::get_key_count(int trackid) const
208 {
209 struct anm_animation *anim = anm_get_active_animation(anm, 0);
210 return anim->tracks[track_type_base[trackid]].count;
211 }
213 int XFormNode::get_position_key_count() const
214 {
215 return get_key_count(POSITION_TRACK);
216 }
218 int XFormNode::get_rotation_key_count() const
219 {
220 return get_key_count(ROTATION_TRACK);
221 }
223 int XFormNode::get_scaling_key_count() const
224 {
225 return get_key_count(SCALING_TRACK);
226 }
228 long XFormNode::get_key_time(int trackid, int idx) const
229 {
230 struct anm_animation *anim = anm_get_active_animation(anm, 0);
231 struct anm_keyframe *key = anm_get_keyframe(anim->tracks + track_type_base[trackid], idx);
232 return ANM_TM2MSEC(key->time);
233 }
235 long XFormNode::get_position_key_time(int idx) const
236 {
237 return get_key_time(POSITION_TRACK, idx);
238 }
240 long XFormNode::get_rotation_key_time(int idx) const
241 {
242 return get_key_time(ROTATION_TRACK, idx);
243 }
245 long XFormNode::get_scaling_key_time(int idx) const
246 {
247 return get_key_time(SCALING_TRACK, idx);
248 }
250 int XFormNode::get_key_value(int trackid, int idx, float *val) const
251 {
252 struct anm_animation *anim = anm_get_active_animation(anm, 0);
254 int nelem = track_type_nelem[trackid];
255 for(int i=0; i<nelem; i++) {
256 struct anm_keyframe *key = anm_get_keyframe(anim->tracks + track_type_base[trackid] + i, idx);
257 val[i] = key->val;
258 }
259 return nelem;
260 }
262 Vector3 XFormNode::get_position_key_value(int idx) const
263 {
264 float val[3];
265 get_key_value(POSITION_TRACK, idx, val);
266 return Vector3(val[0], val[1], val[2]);
267 }
269 Quaternion XFormNode::get_rotation_key_value(int idx) const
270 {
271 float val[4];
272 get_key_value(ROTATION_TRACK, idx, val);
273 return Quaternion(val[3], val[0], val[1], val[2]);
274 }
276 Vector3 XFormNode::get_scaling_key_value(int idx) const
277 {
278 float val[3];
279 get_key_value(SCALING_TRACK, idx, val);
280 return Vector3(val[0], val[1], val[2]);
281 }
283 void XFormNode::set_position(const Vector3 &pos, long tmsec)
284 {
285 anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec));
286 }
288 Vector3 XFormNode::get_node_position(long tmsec) const
289 {
290 vec3_t p = anm_get_node_position(anm, ANM_MSEC2TM(tmsec));
291 return Vector3(p.x, p.y, p.z);
292 }
294 void XFormNode::set_rotation(const Quaternion &quat, long tmsec)
295 {
296 anm_set_rotation(anm, quat_cons(quat.s, quat.v.x, quat.v.y, quat.v.z), ANM_MSEC2TM(tmsec));
297 }
299 Quaternion XFormNode::get_node_rotation(long tmsec) const
300 {
301 quat_t q = anm_get_node_rotation(anm, ANM_MSEC2TM(tmsec));
302 return Quaternion(q.w, q.x, q.y, q.z);
303 }
305 void XFormNode::set_scaling(const Vector3 &pos, long tmsec)
306 {
307 anm_set_scaling(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec));
308 }
310 Vector3 XFormNode::get_node_scaling(long tmsec) const
311 {
312 vec3_t s = anm_get_node_scaling(anm, ANM_MSEC2TM(tmsec));
313 return Vector3(s.x, s.y, s.z);
314 }
316 // these take hierarchy into account
317 Vector3 XFormNode::get_position(long tmsec) const
318 {
319 vec3_t v = anm_get_position(anm, ANM_MSEC2TM(tmsec));
320 return Vector3(v.x, v.y, v.z);
321 }
323 Quaternion XFormNode::get_rotation(long tmsec) const
324 {
325 quat_t q = anm_get_rotation(anm, tmsec);
326 return Quaternion(q.w, q.x, q.y, q.z);
327 }
329 Vector3 XFormNode::get_scaling(long tmsec) const
330 {
331 vec3_t v = anm_get_scaling(anm, ANM_MSEC2TM(tmsec));
332 return Vector3(v.x, v.y, v.z);
333 }
335 void XFormNode::set_pivot(const Vector3 &pivot)
336 {
337 anm_set_pivot(anm, v3_cons(pivot.x, pivot.y, pivot.z));
338 }
340 Vector3 XFormNode::get_pivot() const
341 {
342 vec3_t p = anm_get_pivot(anm);
343 return Vector3(p.x, p.y, p.z);
344 }
346 void XFormNode::set_local_matrix(const Matrix4x4 &mat)
347 {
348 local_matrix = mat;
349 }
351 const Matrix4x4 &XFormNode::get_local_matrix() const
352 {
353 return local_matrix;
354 }
356 void XFormNode::set_bone_matrix(const Matrix4x4 &bmat)
357 {
358 bone_matrix = bmat;
359 }
361 const Matrix4x4 &XFormNode::get_bone_matrix() const
362 {
363 return bone_matrix;
364 }
366 #define FOO
368 void XFormNode::get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const
369 {
370 anm_time_t tm = ANM_MSEC2TM(tmsec);
372 if(mat) {
373 anm_get_node_matrix(anm, (scalar_t(*)[4])mat, tm);
374 #ifdef FOO
375 *mat = local_matrix * *mat;
376 #else
377 *mat = *mat * local_matrix;
378 #endif
379 }
380 if(inv_mat) {
381 anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm);
382 }
383 }
385 void XFormNode::get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const
386 {
387 anm_time_t tm = ANM_MSEC2TM(tmsec);
389 if(mat) {
390 anm_get_matrix(anm, (scalar_t(*)[4])mat, tm);
391 #ifdef FOO
392 *mat = local_matrix * *mat;
393 #else
394 *mat = *mat * local_matrix;
395 #endif
396 }
397 if(inv_mat) {
398 anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm);
399 }
400 }
403 // ---- Track ----
405 Track::Track()
406 {
407 trk = new anm_track;
408 anm_init_track(trk);
409 }
411 Track::~Track()
412 {
413 anm_destroy_track(trk);
414 delete trk;
415 }
417 Track::Track(const Track &rhs)
418 {
419 trk = new anm_track;
420 anm_init_track(trk);
421 anm_copy_track(trk, rhs.trk);
422 interp = rhs.interp;
423 extrap = rhs.extrap;
424 }
426 Track &Track::operator =(const Track &rhs)
427 {
428 if(&rhs == this) {
429 return *this;
430 }
432 anm_copy_track(trk, rhs.trk);
433 interp = rhs.interp;
434 extrap = rhs.extrap;
435 return *this;
436 }
439 void Track::set_interpolator(Interp in)
440 {
441 anm_set_track_interpolator(trk, track_interpolator(in));
442 interp = in;
443 }
445 Interp Track::get_interpolator() const
446 {
447 return interp;
448 }
450 void Track::set_extrapolator(Extrap ex)
451 {
452 anm_set_track_extrapolator(trk, track_extrapolator(ex));
453 extrap = ex;
454 }
456 Extrap Track::get_extrapolator() const
457 {
458 return extrap;
459 }
461 void Track::set_default(double def)
462 {
463 anm_set_track_default(trk, def);
464 }
466 void Track::set_value(float val, long tmsec)
467 {
468 anm_set_value(trk, ANM_MSEC2TM(tmsec), val);
469 }
471 float Track::get_value(long tmsec) const
472 {
473 return anm_get_value(trk, ANM_MSEC2TM(tmsec));
474 }
476 float Track::operator ()(long tmsec) const
477 {
478 return anm_get_value(trk, ANM_MSEC2TM(tmsec));
479 }
482 // ---- Track3 ----
484 void Track3::set_interpolator(Interp in)
485 {
486 for(int i=0; i<3; i++) {
487 track[i].set_interpolator(in);
488 }
489 }
491 Interp Track3::get_interpolator() const
492 {
493 return track[0].get_interpolator();
494 }
496 void Track3::set_extrapolator(Extrap ex)
497 {
498 for(int i=0; i<3; i++) {
499 track[i].set_extrapolator(ex);
500 }
501 }
503 Extrap Track3::get_extrapolator() const
504 {
505 return track[0].get_extrapolator();
506 }
508 void Track3::set_default(const Vector3 &def)
509 {
510 for(int i=0; i<3; i++) {
511 track[i].set_default(def[i]);
512 }
513 }
515 void Track3::set_value(const Vector3 &val, long tmsec)
516 {
517 for(int i=0; i<3; i++) {
518 track[i].set_value(val[i], tmsec);
519 }
520 }
522 Vector3 Track3::get_value(long tmsec) const
523 {
524 return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec));
525 }
527 Vector3 Track3::operator ()(long tmsec) const
528 {
529 return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec));
530 }
533 static inline anm_interpolator track_interpolator(Interp in)
534 {
535 switch(in) {
536 case INTERP_STEP:
537 return ANM_INTERP_STEP;
538 case INTERP_LINEAR:
539 return ANM_INTERP_LINEAR;
540 case INTERP_CUBIC:
541 return ANM_INTERP_CUBIC;
542 }
544 assert(0);
545 return ANM_INTERP_STEP;
546 }
548 static inline anm_extrapolator track_extrapolator(Extrap ex)
549 {
550 switch(ex) {
551 case EXTRAP_EXTEND:
552 return ANM_EXTRAP_EXTEND;
553 case EXTRAP_CLAMP:
554 return ANM_EXTRAP_CLAMP;
555 case EXTRAP_REPEAT:
556 return ANM_EXTRAP_REPEAT;
557 }
559 assert(0);
560 return ANM_EXTRAP_EXTEND;
561 }