# HG changeset patch # User John Tsiombikas # Date 1388206059 -7200 # Node ID 498ca7ac70473df24d5f12ba06e65810da30e781 # Parent 9d911100935bcdcb2ce68024405b4b9a73c4eee2 - placed all the implementation stuff in the g3dimpl namespace - added animation stuff to the public API - started writing animation saving/loading diff -r 9d911100935b -r 498ca7ac7047 src/camera.cc --- a/src/camera.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/camera.cc Sat Dec 28 06:47:39 2013 +0200 @@ -1,5 +1,7 @@ #include "camera.h" +using namespace g3dimpl; + Camera::Camera() { near_clip = 0.5; diff -r 9d911100935b -r 498ca7ac7047 src/camera.h --- a/src/camera.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/camera.h Sat Dec 28 06:47:39 2013 +0200 @@ -3,6 +3,8 @@ #include "object.h" +namespace g3dimpl { + class Camera : public Object { public: float near_clip, far_clip; @@ -17,4 +19,6 @@ TargetCamera(); }; +} // namespace g3dimpl + #endif // CAMERA_H_ diff -r 9d911100935b -r 498ca7ac7047 src/chunk.cc --- a/src/chunk.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/chunk.cc Sat Dec 28 06:47:39 2013 +0200 @@ -1,6 +1,8 @@ #include "goat3d.h" #include "chunk.h" +using namespace g3dimpl; + ChunkHeader chunk_header(int id) { ChunkHeader hdr; @@ -9,7 +11,7 @@ return hdr; } -bool write_chunk_header(const ChunkHeader *hdr, goat3d_io *io) +bool g3dimpl::write_chunk_header(const ChunkHeader *hdr, goat3d_io *io) { io->seek(-(long)hdr->size, SEEK_CUR, io->cls); if(io->write(hdr, sizeof *hdr, io->cls) < (long)sizeof *hdr) { @@ -18,7 +20,7 @@ return true; } -bool read_chunk_header(ChunkHeader *hdr, goat3d_io *io) +bool g3dimpl::read_chunk_header(ChunkHeader *hdr, goat3d_io *io) { if(io->read(hdr, sizeof *hdr, io->cls) < (long)sizeof *hdr) { return false; @@ -26,7 +28,7 @@ return true; } -void skip_chunk(const ChunkHeader *hdr, goat3d_io *io) +void g3dimpl::skip_chunk(const ChunkHeader *hdr, goat3d_io *io) { io->seek(hdr->size - sizeof *hdr, SEEK_CUR, io->cls); } diff -r 9d911100935b -r 498ca7ac7047 src/chunk.h --- a/src/chunk.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/chunk.h Sat Dec 28 06:47:39 2013 +0200 @@ -7,6 +7,8 @@ typedef unsigned __int32 uint32_t; #endif +namespace g3dimpl { + enum { CNK_INVALID, // this shouldn't appear in files CNK_SCENE, // the root chunk @@ -120,5 +122,6 @@ bool read_chunk_header(ChunkHeader *hdr, goat3d_io *io); void skip_chunk(const ChunkHeader *hdr, goat3d_io *io); +} // namespace g3dimpl #endif // CHUNK_H_ diff -r 9d911100935b -r 498ca7ac7047 src/goat3d.cc --- a/src/goat3d.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/goat3d.cc Sat Dec 28 06:47:39 2013 +0200 @@ -12,6 +12,8 @@ #include #endif +using namespace g3dimpl; + struct goat3d { Scene *scn; unsigned int flags; @@ -147,6 +149,72 @@ return g->scn->save(io) ? 0 : -1; } +/* save/load animations */ +GOAT3DAPI int goat3d_load_anim(struct goat3d *g, const char *fname) +{ + FILE *fp = fopen(fname, "rb"); + if(!fp) { + return -1; + } + + int res = goat3d_load_anim_file(g, fp); + fclose(fp); + return res; +} + +GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const struct goat3d_node *root, const char *fname) +{ + FILE *fp = fopen(fname, "wb"); + if(!fp) { + return -1; + } + + int res = goat3d_save_anim_file(g, root, fp); + fclose(fp); + return res; +} + +GOAT3DAPI int goat3d_load_anim_file(struct goat3d *g, FILE *fp) +{ + goat3d_io io; + io.cls = fp; + io.read = read_file; + io.write = write_file; + io.seek = seek_file; + + return goat3d_load_anim_io(g, &io); +} + +GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, const struct goat3d_node *root, FILE *fp) +{ + goat3d_io io; + io.cls = fp; + io.read = read_file; + io.write = write_file; + io.seek = seek_file; + + return goat3d_save_anim_io(g, root, &io); +} + +GOAT3DAPI int goat3d_load_anim_io(struct goat3d *g, struct goat3d_io *io) +{ + if(!g->scn->load_anim(io)) { + if(!g->scn->load_anim_xml(io)) { + return -1; + } + } + return 0; +} + +GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, const struct goat3d_node *root, struct goat3d_io *io) +{ + if(goat3d_getopt(g, GOAT3D_OPT_SAVEXML)) { + return g->scn->save_anim_xml(root, io) ? 0 : -1; + } + return g->scn->save_anim(root, io) ? 0 : -1; +} + + GOAT3DAPI int goat3d_set_name(struct goat3d *g, const char *name) { g->scn->set_name(name); @@ -704,6 +772,61 @@ return (goat3d_node*)node->get_child(idx); } +GOAT3DAPI struct goat3d_node *goat3d_get_node_parent(const struct goat3d_node *node) +{ + return (goat3d_node*)node->get_parent(); +} + +GOAT3DAPI void goat3d_use_anim(struct goat3d_node *node, int idx) +{ + node->use_animation(idx); +} + +GOAT3DAPI void goat3d_use_anims(struct goat3d_node *node, int aidx, int bidx, float t) +{ + node->use_animation(aidx, bidx, t); +} + +GOAT3DAPI void goat3d_use_anim_by_name(struct goat3d_node *node, const char *name) +{ + node->use_animation(name); +} + +GOAT3DAPI void goat3d_use_anims_by_name(struct goat3d_node *node, const char *aname, const char *bname, float t) +{ + node->use_animation(aname, bname, t); +} + +GOAT3DAPI int goat3d_get_active_anim(struct goat3d_node *node, int which) +{ + return node->get_active_animation_index(which); +} + +GOAT3DAPI float goat3d_get_active_anim_mix(struct goat3d_node *node) +{ + return node->get_active_animation_mix(); +} + +GOAT3DAPI int goat3d_get_anim_count(struct goat3d_node *node) +{ + return node->get_animation_count(); +} + +GOAT3DAPI void goat3d_add_anim(struct goat3d_node *root) +{ + root->add_animation(); +} + +GOAT3DAPI void goat3d_set_anim_name(struct goat3d_node *root, const char *name) +{ + root->set_animation_name(name); +} + +GOAT3DAPI const char *goat3d_get_anim_name(struct goat3d_node *node) +{ + return node->get_animation_name(); +} + GOAT3DAPI void goat3d_set_node_position(struct goat3d_node *node, float x, float y, float z, long tmsec) { node->set_position(Vector3(x, y, z), tmsec); diff -r 9d911100935b -r 498ca7ac7047 src/goat3d.h --- a/src/goat3d.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/goat3d.h Sat Dec 28 06:47:39 2013 +0200 @@ -88,6 +88,16 @@ GOAT3DAPI int goat3d_load_io(struct goat3d *g, struct goat3d_io *io); GOAT3DAPI int goat3d_save_io(const struct goat3d *g, struct goat3d_io *io); +/* load/save animation files (g must already be loaded to load animations) */ +GOAT3DAPI int goat3d_load_anim(struct goat3d *g, const char *fname); +GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const struct goat3d_node *root, const char *fname); + +GOAT3DAPI int goat3d_load_anim_file(struct goat3d *g, FILE *fp); +GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, const struct goat3d_node *root, FILE *fp); + +GOAT3DAPI int goat3d_load_anim_io(struct goat3d *g, struct goat3d_io *io); +GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, const struct goat3d_node *root, struct goat3d_io *io); + /* misc scene properties */ GOAT3DAPI int goat3d_set_name(struct goat3d *g, const char *name); GOAT3DAPI const char *goat3d_get_name(const struct goat3d *g); @@ -147,9 +157,9 @@ const void *data, int vnum); GOAT3DAPI void goat3d_add_mesh_attrib1f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, float val); GOAT3DAPI void goat3d_add_mesh_attrib3f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, - float x, float y, float z); + float x, float y, float z); GOAT3DAPI void goat3d_add_mesh_attrib4f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, - float x, float y, float z, float w); + float x, float y, float z, float w); /* returns a pointer to the beginning of the requested mesh attribute array */ GOAT3DAPI void *goat3d_get_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib); /* returns a pointer to the requested mesh attribute */ @@ -216,6 +226,21 @@ GOAT3DAPI void goat3d_add_node_child(struct goat3d_node *node, struct goat3d_node *child); GOAT3DAPI int goat3d_get_node_child_count(const struct goat3d_node *node); GOAT3DAPI struct goat3d_node *goat3d_get_node_child(const struct goat3d_node *node, int idx); +GOAT3DAPI struct goat3d_node *goat3d_get_node_parent(const struct goat3d_node *node); + +GOAT3DAPI void goat3d_use_anim(struct goat3d_node *node, int idx); +GOAT3DAPI void goat3d_use_anims(struct goat3d_node *node, int aidx, int bidx, float t); +GOAT3DAPI void goat3d_use_anim_by_name(struct goat3d_node *node, const char *name); +GOAT3DAPI void goat3d_use_anims_by_name(struct goat3d_node *node, const char *aname, const char *bname, float t); + +GOAT3DAPI int goat3d_get_active_anim(struct goat3d_node *node, int which); +GOAT3DAPI float goat3d_get_active_anim_mix(struct goat3d_node *node); + +GOAT3DAPI int goat3d_get_anim_count(struct goat3d_node *node); +GOAT3DAPI void goat3d_add_anim(struct goat3d_node *root); + +GOAT3DAPI void goat3d_set_anim_name(struct goat3d_node *root, const char *name); +GOAT3DAPI const char *goat3d_get_anim_name(struct goat3d_node *node); GOAT3DAPI void goat3d_set_node_position(struct goat3d_node *node, float x, float y, float z, long tmsec); GOAT3DAPI void goat3d_set_node_rotation(struct goat3d_node *node, float qx, float qy, float qz, float qw, long tmsec); diff -r 9d911100935b -r 498ca7ac7047 src/goat3d_impl.h --- a/src/goat3d_impl.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/goat3d_impl.h Sat Dec 28 06:47:39 2013 +0200 @@ -10,6 +10,8 @@ #include "material.h" #include "node.h" +namespace g3dimpl { + extern int goat_log_level; #if __cplusplus >= 201103L @@ -77,9 +79,17 @@ bool loadxml(goat3d_io *io); bool savexml(goat3d_io *io) const; + + bool load_anim(goat3d_io *io); + bool save_anim(const XFormNode *node, goat3d_io *io) const; + + bool load_anim_xml(goat3d_io *io); + bool save_anim_xml(const XFormNode *node, goat3d_io *io) const; }; void io_fprintf(goat3d_io *io, const char *fmt, ...); void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap); +} // namespace g3dimpl + #endif // GOAT3D_IMPL_H_ diff -r 9d911100935b -r 498ca7ac7047 src/goat3d_readxml.cc --- a/src/goat3d_readxml.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/goat3d_readxml.cc Sat Dec 28 06:47:39 2013 +0200 @@ -4,6 +4,7 @@ #include "tinyxml2.h" #include "log.h" +using namespace g3dimpl; using namespace tinyxml2; static Material *read_material(Scene *scn, XMLElement *xml_mtl); diff -r 9d911100935b -r 498ca7ac7047 src/goat3d_write.cc --- a/src/goat3d_write.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/goat3d_write.cc Sat Dec 28 06:47:39 2013 +0200 @@ -1,6 +1,8 @@ #include "goat3d_impl.h" #include "chunk.h" +using namespace g3dimpl; + /* static long save_env(const Scene *scn, long offset, goat3d_io *io); static long save_materials(const Scene *scn, long offset, goat3d_io *io); diff -r 9d911100935b -r 498ca7ac7047 src/goat3d_writexml.cc --- a/src/goat3d_writexml.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/goat3d_writexml.cc Sat Dec 28 06:47:39 2013 +0200 @@ -1,12 +1,17 @@ +#include #include #include "goat3d_impl.h" +#include "anim/anim.h" #include "log.h" +using namespace g3dimpl; + static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level); static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level); static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level); static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level); static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level); +static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level); static void xmlout(goat3d_io *io, int level, const char *fmt, ...); bool Scene::savexml(goat3d_io *io) const @@ -38,6 +43,39 @@ return true; } +static void collect_nodes(std::list *res, const XFormNode *node) +{ + if(!node) return; + + res->push_back(node); + + for(int i=0; iget_children_count(); i++) { + collect_nodes(res, node->get_child(i)); + } +} + +bool Scene::save_anim_xml(const XFormNode *node, goat3d_io *io) const +{ + xmlout(io, 0, "\n"); + + const char *anim_name = node->get_animation_name(); + if(anim_name && *anim_name) { + xmlout(io, 1, "\n", anim_name); + } + + std::list allnodes; + collect_nodes(&allnodes, node); + + std::list::const_iterator it = allnodes.begin(); + while(it != allnodes.end()) { + const XFormNode *n = *it++; + write_node_anim(io, n, 1); + } + + xmlout(io, 0, "\n"); + return true; +} + static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level) { xmlout(io, level, "\n"); @@ -100,7 +138,7 @@ xmlout(io, level, "\n"); xmlout(io, level + 1, "\n", node->get_name()); - XFormNode *parent = node->get_parent(); + const XFormNode *parent = node->get_parent(); if(parent) { xmlout(io, level + 1, "\n", parent->get_name()); } @@ -140,6 +178,55 @@ return true; } +static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level) +{ + static const char *attr_names[] = { "position", "rotation", "scaling" }; + struct anm_node *anode = node->get_libanim_node(); + struct anm_animation *anim = anm_get_active_animation(anode, 0); + + if(!anode || !anim) { + return false; + } + + struct anm_track *trk[4]; + + for(int i=0; i<3; i++) { // 3 attributes + switch(i) { + case 0: // position + trk[0] = anim->tracks + ANM_TRACK_POS_X; + trk[1] = anim->tracks + ANM_TRACK_POS_Y; + trk[2] = anim->tracks + ANM_TRACK_POS_Z; + trk[3] = 0; + break; + + case 1: // rotation + trk[0] = anim->tracks + ANM_TRACK_ROT_X; + trk[1] = anim->tracks + ANM_TRACK_ROT_Y; + trk[2] = anim->tracks + ANM_TRACK_ROT_Z; + trk[3] = anim->tracks + ANM_TRACK_ROT_W; + break; + + case 2: // scaling + trk[0] = anim->tracks + ANM_TRACK_SCL_X; + trk[1] = anim->tracks + ANM_TRACK_SCL_Y; + trk[2] = anim->tracks + ANM_TRACK_SCL_Z; + trk[3] = 0; + } + + if(trk[0]->count <= 0) { + continue; // skip tracks without any keyframes + } + + xmlout(io, level + 1, "\n"); + xmlout(io, level + 2, "\n", node->get_name()); + xmlout(io, level + 2, "\n", attr_names[i]); + + // TODO cont: move all the keyframe retreival to XFormNode and use that... + + xmlout(io, level + 1, "\n"); + } + return true; +} static void xmlout(goat3d_io *io, int level, const char *fmt, ...) { diff -r 9d911100935b -r 498ca7ac7047 src/light.cc --- a/src/light.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/light.cc Sat Dec 28 06:47:39 2013 +0200 @@ -1,5 +1,7 @@ #include "light.h" +using namespace g3dimpl; + Light::Light() : color(1, 1, 1), attenuation(1, 0, 0) { diff -r 9d911100935b -r 498ca7ac7047 src/light.h --- a/src/light.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/light.h Sat Dec 28 06:47:39 2013 +0200 @@ -4,6 +4,8 @@ #include #include "object.h" +namespace g3dimpl { + class Light : public Object { public: Vector3 color; @@ -27,4 +29,6 @@ SpotLight(); }; +} // namespace g3dimpl + #endif // LIGHT_H_ diff -r 9d911100935b -r 498ca7ac7047 src/log.cc --- a/src/log.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/log.cc Sat Dec 28 06:47:39 2013 +0200 @@ -4,7 +4,7 @@ int goat_log_level = 256; -void logmsg(int prio, const char *fmt, ...) +void g3dimpl::logmsg(int prio, const char *fmt, ...) { va_list ap; diff -r 9d911100935b -r 498ca7ac7047 src/log.h --- a/src/log.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/log.h Sat Dec 28 06:47:39 2013 +0200 @@ -1,8 +1,12 @@ #ifndef LOG_H_ #define LOG_H_ +namespace g3dimpl { + enum { LOG_ERROR, LOG_INFO }; void logmsg(int prio, const char *fmt, ...); +} // namespace g3dimpl + #endif // LOG_H_ diff -r 9d911100935b -r 498ca7ac7047 src/material.cc --- a/src/material.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/material.cc Sat Dec 28 06:47:39 2013 +0200 @@ -1,5 +1,7 @@ #include "material.h" +using namespace g3dimpl; + MaterialAttrib Material::def_attr; int Material::get_attrib_count() const diff -r 9d911100935b -r 498ca7ac7047 src/material.h --- a/src/material.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/material.h Sat Dec 28 06:47:39 2013 +0200 @@ -5,6 +5,8 @@ #include #include +namespace g3dimpl { + struct MaterialAttrib { Vector4 value; std::string map; @@ -31,4 +33,6 @@ const MaterialAttrib &operator [](const std::string &name) const; }; +} // namespace g3dimpl + #endif // MATERIAL_H_ diff -r 9d911100935b -r 498ca7ac7047 src/mesh.cc --- a/src/mesh.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/mesh.cc Sat Dec 28 06:47:39 2013 +0200 @@ -3,6 +3,8 @@ #include "openctm.h" #include "log.h" +using namespace g3dimpl; + Int4::Int4() { x = y = z = w = 0; diff -r 9d911100935b -r 498ca7ac7047 src/mesh.h --- a/src/mesh.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/mesh.h Sat Dec 28 06:47:39 2013 +0200 @@ -5,6 +5,8 @@ #include "object.h" #include "material.h" +namespace g3dimpl { + class Node; struct Face { @@ -43,4 +45,6 @@ const Material *get_material() const; }; +} // namespace g3dimpl + #endif // MESH_H_ diff -r 9d911100935b -r 498ca7ac7047 src/node.cc --- a/src/node.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/node.cc Sat Dec 28 06:47:39 2013 +0200 @@ -2,6 +2,8 @@ #include #include "node.h" +using namespace g3dimpl; + Node::Node() { obj = 0; @@ -22,7 +24,7 @@ return obj; } -void delete_node_tree(Node *n) +void g3dimpl::delete_node_tree(Node *n) { for(int i=0; iget_children_count(); i++) { delete_node_tree((Node*)n->get_child(i)); diff -r 9d911100935b -r 498ca7ac7047 src/node.h --- a/src/node.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/node.h Sat Dec 28 06:47:39 2013 +0200 @@ -4,6 +4,8 @@ #include "xform_node.h" #include "object.h" +namespace g3dimpl { + class Node : public XFormNode { private: Object *obj; @@ -18,4 +20,6 @@ void delete_node_tree(Node *n); +} // namespace g3dimpl + #endif // NODE_H_ diff -r 9d911100935b -r 498ca7ac7047 src/scene.cc --- a/src/scene.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/scene.cc Sat Dec 28 06:47:39 2013 +0200 @@ -3,6 +3,8 @@ #include "goat3d_impl.h" #include "chunk.h" +using namespace g3dimpl; + Scene::Scene() : name("unnamed"), ambient(0.05, 0.05, 0.05) { @@ -213,7 +215,7 @@ // Scene::savexml is defined in goat3d_writexml.cc -void io_fprintf(goat3d_io *io, const char *fmt, ...) +void g3dimpl::io_fprintf(goat3d_io *io, const char *fmt, ...) { va_list ap; @@ -223,7 +225,7 @@ } -void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap) +void g3dimpl::io_vfprintf(goat3d_io *io, const char *fmt, va_list ap) { char smallbuf[256]; char *buf = smallbuf; diff -r 9d911100935b -r 498ca7ac7047 src/xform_node.cc --- a/src/xform_node.cc Sun Dec 08 03:00:25 2013 +0200 +++ b/src/xform_node.cc Sat Dec 28 06:47:39 2013 +0200 @@ -1,8 +1,10 @@ #include #include #include "xform_node.h" -#include "anim.h" -#include "track.h" +#include "anim/anim.h" +#include "anim/track.h" + +using namespace g3dimpl; static inline anm_interpolator track_interpolator(Interp in); static inline anm_extrapolator track_extrapolator(Extrap ex); @@ -11,8 +13,11 @@ { anm = new anm_node; anm_init_node(anm); + parent = 0; - parent = 0; + // TODO read them from anm to get the correct initial values + interp = INTERP_LINEAR; + extrap = EXTRAP_EXTEND; } XFormNode::~XFormNode() @@ -21,6 +26,11 @@ delete anm; } +struct anm_node *XFormNode::get_libanim_node() const +{ + return anm; +} + void XFormNode::set_name(const char *name) { anm_set_node_name(anm, name); @@ -53,6 +63,16 @@ return extrap; } +XFormNode *XFormNode::get_parent() +{ + return parent; +} + +const XFormNode *XFormNode::get_parent() const +{ + return parent; +} + void XFormNode::add_child(XFormNode *child) { children.push_back(child); @@ -67,8 +87,11 @@ if(it != children.end()) { children.erase(it); anm_unlink_node(anm, child->anm); + + if(child->parent == this) { + child->parent = 0; + } } - child->parent = 0; } int XFormNode::get_children_count() const @@ -92,11 +115,77 @@ return 0; } -XFormNode *XFormNode::get_parent() const + +void XFormNode::use_animation(int idx) { - return parent; + if(idx >= 0) { + anm_use_animation(anm, idx); + } } +void XFormNode::use_animation(const char *name) +{ + anm_use_animation(anm, anm_find_animation(anm, name)); +} + +void XFormNode::use_animation(int aidx, int bidx, float t) +{ + anm_use_animations(anm, aidx, bidx, t); +} + +void XFormNode::use_animation(const char *aname, const char *bname, float t) +{ + int aidx = anm_find_animation(anm, aname); + int bidx = anm_find_animation(anm, bname); + + if(aidx == -1) { + use_animation(bidx); + } + if(bidx == -1) { + use_animation(aidx); + } + anm_use_animations(anm, aidx, bidx, t); +} + +int XFormNode::get_active_animation_index(int which) const +{ + return anm_get_active_animation_index(anm, which); +} + +float XFormNode::get_active_animation_mix() const +{ + return anm_get_active_animation_mix(anm); +} + +int XFormNode::get_animation_count() const +{ + return anm_get_animation_count(anm); +} + +void XFormNode::add_animation(const char *name) +{ + int idx = get_animation_count(); + + anm_add_animation(anm); + use_animation(idx); + + if(name) { + set_animation_name(name); + } +} + +void XFormNode::set_animation_name(const char *name) +{ + anm_set_active_animation_name(anm, name); +} + +const char *XFormNode::get_animation_name() const +{ + return anm_get_active_animation_name(anm); +} + + + void XFormNode::set_position(const Vector3 &pos, long tmsec) { anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); diff -r 9d911100935b -r 498ca7ac7047 src/xform_node.h --- a/src/xform_node.h Sun Dec 08 03:00:25 2013 +0200 +++ b/src/xform_node.h Sat Dec 28 06:47:39 2013 +0200 @@ -1,6 +1,3 @@ -/* -TODO: add multiple animations per node in libanim (i.e. multiple sets of tracks) -*/ #ifndef XFORM_NODE_H_ #define XFORM_NODE_H_ @@ -9,13 +6,16 @@ #include "vmath/quat.h" #include "vmath/matrix.h" -enum Interp { INTERP_STEP, INTERP_LINEAR, INTERP_CUBIC }; -enum Extrap { EXTRAP_EXTEND, EXTRAP_CLAMP, EXTRAP_REPEAT }; struct anm_node; struct anm_track; -// XXX all time arguments are milliseconds +namespace g3dimpl { + +enum Interp { INTERP_STEP, INTERP_LINEAR, INTERP_CUBIC }; +enum Extrap { EXTRAP_EXTEND, EXTRAP_CLAMP, EXTRAP_REPEAT }; + +// NOTE: all time arguments are milliseconds class XFormNode { private: @@ -36,6 +36,9 @@ XFormNode(); virtual ~XFormNode(); + // retrieve the pointer to the underlying libanim data structure + virtual struct anm_node *get_libanim_node() const; + virtual void set_name(const char *name); virtual const char *get_name() const; @@ -44,6 +47,9 @@ virtual void set_extrapolator(Extrap ex); virtual Extrap get_extrapolator() const; + virtual XFormNode *get_parent(); + virtual const XFormNode *get_parent() const; + // children management virtual void add_child(XFormNode *child); virtual void remove_child(XFormNode *child); @@ -52,7 +58,24 @@ virtual XFormNode *get_child(int idx); virtual const XFormNode *get_child(int idx) const; - virtual XFormNode *get_parent() const; + + virtual void use_animation(int idx); + virtual void use_animation(const char *name); + virtual void use_animation(int aidx, int bidx, float t); + virtual void use_animation(const char *aname, const char *bname, float t); + + virtual int get_active_animation_index(int which = 0) const; + virtual float get_active_animation_mix() const; + + virtual int get_animation_count() const; + + // add a new empty animation slot (recursive) + virtual void add_animation(const char *name = 0); + + // set/get the current animation name (set is recursive) + virtual void set_animation_name(const char *name); + virtual const char *get_animation_name() const; + virtual void set_position(const Vector3 &pos, long tmsec = 0); virtual Vector3 get_node_position(long tmsec = 0) const; @@ -133,4 +156,6 @@ Vector3 operator ()(long tmsec = 0) const; }; +} // namespace g3dimpl + #endif /* XFORM_NODE_H_ */