goat3d

changeset 47:498ca7ac7047

- placed all the implementation stuff in the g3dimpl namespace - added animation stuff to the public API - started writing animation saving/loading
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 28 Dec 2013 06:47:39 +0200
parents 9d911100935b
children 9ef9de80649c
files src/camera.cc src/camera.h src/chunk.cc src/chunk.h src/goat3d.cc src/goat3d.h src/goat3d_impl.h src/goat3d_readxml.cc src/goat3d_write.cc src/goat3d_writexml.cc src/light.cc src/light.h src/log.cc src/log.h src/material.cc src/material.h src/mesh.cc src/mesh.h src/node.cc src/node.h src/scene.cc src/xform_node.cc src/xform_node.h
diffstat 23 files changed, 426 insertions(+), 23 deletions(-) [+]
line diff
     1.1 --- a/src/camera.cc	Sun Dec 08 03:00:25 2013 +0200
     1.2 +++ b/src/camera.cc	Sat Dec 28 06:47:39 2013 +0200
     1.3 @@ -1,5 +1,7 @@
     1.4  #include "camera.h"
     1.5  
     1.6 +using namespace g3dimpl;
     1.7 +
     1.8  Camera::Camera()
     1.9  {
    1.10  	near_clip = 0.5;
     2.1 --- a/src/camera.h	Sun Dec 08 03:00:25 2013 +0200
     2.2 +++ b/src/camera.h	Sat Dec 28 06:47:39 2013 +0200
     2.3 @@ -3,6 +3,8 @@
     2.4  
     2.5  #include "object.h"
     2.6  
     2.7 +namespace g3dimpl {
     2.8 +
     2.9  class Camera : public Object {
    2.10  public:
    2.11  	float near_clip, far_clip;
    2.12 @@ -17,4 +19,6 @@
    2.13  	TargetCamera();
    2.14  };
    2.15  
    2.16 +}	// namespace g3dimpl
    2.17 +
    2.18  #endif	// CAMERA_H_
     3.1 --- a/src/chunk.cc	Sun Dec 08 03:00:25 2013 +0200
     3.2 +++ b/src/chunk.cc	Sat Dec 28 06:47:39 2013 +0200
     3.3 @@ -1,6 +1,8 @@
     3.4  #include "goat3d.h"
     3.5  #include "chunk.h"
     3.6  
     3.7 +using namespace g3dimpl;
     3.8 +
     3.9  ChunkHeader chunk_header(int id)
    3.10  {
    3.11  	ChunkHeader hdr;
    3.12 @@ -9,7 +11,7 @@
    3.13  	return hdr;
    3.14  }
    3.15  
    3.16 -bool write_chunk_header(const ChunkHeader *hdr, goat3d_io *io)
    3.17 +bool g3dimpl::write_chunk_header(const ChunkHeader *hdr, goat3d_io *io)
    3.18  {
    3.19  	io->seek(-(long)hdr->size, SEEK_CUR, io->cls);
    3.20  	if(io->write(hdr, sizeof *hdr, io->cls) < (long)sizeof *hdr) {
    3.21 @@ -18,7 +20,7 @@
    3.22  	return true;
    3.23  }
    3.24  
    3.25 -bool read_chunk_header(ChunkHeader *hdr, goat3d_io *io)
    3.26 +bool g3dimpl::read_chunk_header(ChunkHeader *hdr, goat3d_io *io)
    3.27  {
    3.28  	if(io->read(hdr, sizeof *hdr, io->cls) < (long)sizeof *hdr) {
    3.29  		return false;
    3.30 @@ -26,7 +28,7 @@
    3.31  	return true;
    3.32  }
    3.33  
    3.34 -void skip_chunk(const ChunkHeader *hdr, goat3d_io *io)
    3.35 +void g3dimpl::skip_chunk(const ChunkHeader *hdr, goat3d_io *io)
    3.36  {
    3.37  	io->seek(hdr->size - sizeof *hdr, SEEK_CUR, io->cls);
    3.38  }
     4.1 --- a/src/chunk.h	Sun Dec 08 03:00:25 2013 +0200
     4.2 +++ b/src/chunk.h	Sat Dec 28 06:47:39 2013 +0200
     4.3 @@ -7,6 +7,8 @@
     4.4  typedef unsigned __int32 uint32_t;
     4.5  #endif
     4.6  
     4.7 +namespace g3dimpl {
     4.8 +
     4.9  enum {
    4.10  	CNK_INVALID,		// this shouldn't appear in files
    4.11  	CNK_SCENE,			// the root chunk
    4.12 @@ -120,5 +122,6 @@
    4.13  bool read_chunk_header(ChunkHeader *hdr, goat3d_io *io);
    4.14  void skip_chunk(const ChunkHeader *hdr, goat3d_io *io);
    4.15  
    4.16 +}	// namespace g3dimpl
    4.17  
    4.18  #endif	// CHUNK_H_
     5.1 --- a/src/goat3d.cc	Sun Dec 08 03:00:25 2013 +0200
     5.2 +++ b/src/goat3d.cc	Sat Dec 28 06:47:39 2013 +0200
     5.3 @@ -12,6 +12,8 @@
     5.4  #include <malloc.h>
     5.5  #endif
     5.6  
     5.7 +using namespace g3dimpl;
     5.8 +
     5.9  struct goat3d {
    5.10  	Scene *scn;
    5.11  	unsigned int flags;
    5.12 @@ -147,6 +149,72 @@
    5.13  	return g->scn->save(io) ? 0 : -1;
    5.14  }
    5.15  
    5.16 +/* save/load animations */
    5.17 +GOAT3DAPI int goat3d_load_anim(struct goat3d *g, const char *fname)
    5.18 +{
    5.19 +	FILE *fp = fopen(fname, "rb");
    5.20 +	if(!fp) {
    5.21 +		return -1;
    5.22 +	}
    5.23 +
    5.24 +	int res = goat3d_load_anim_file(g, fp);
    5.25 +	fclose(fp);
    5.26 +	return res;
    5.27 +}
    5.28 +
    5.29 +GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const struct goat3d_node *root, const char *fname)
    5.30 +{
    5.31 +	FILE *fp = fopen(fname, "wb");
    5.32 +	if(!fp) {
    5.33 +		return -1;
    5.34 +	}
    5.35 +
    5.36 +	int res = goat3d_save_anim_file(g, root, fp);
    5.37 +	fclose(fp);
    5.38 +	return res;
    5.39 +}
    5.40 +
    5.41 +GOAT3DAPI int goat3d_load_anim_file(struct goat3d *g, FILE *fp)
    5.42 +{
    5.43 +	goat3d_io io;
    5.44 +	io.cls = fp;
    5.45 +	io.read = read_file;
    5.46 +	io.write = write_file;
    5.47 +	io.seek = seek_file;
    5.48 +
    5.49 +	return goat3d_load_anim_io(g, &io);
    5.50 +}
    5.51 +
    5.52 +GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, const struct goat3d_node *root, FILE *fp)
    5.53 +{
    5.54 +	goat3d_io io;
    5.55 +	io.cls = fp;
    5.56 +	io.read = read_file;
    5.57 +	io.write = write_file;
    5.58 +	io.seek = seek_file;
    5.59 +
    5.60 +	return goat3d_save_anim_io(g, root, &io);
    5.61 +}
    5.62 +
    5.63 +GOAT3DAPI int goat3d_load_anim_io(struct goat3d *g, struct goat3d_io *io)
    5.64 +{
    5.65 +	if(!g->scn->load_anim(io)) {
    5.66 +		if(!g->scn->load_anim_xml(io)) {
    5.67 +			return -1;
    5.68 +		}
    5.69 +	}
    5.70 +	return 0;
    5.71 +}
    5.72 +
    5.73 +GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, const struct goat3d_node *root, struct goat3d_io *io)
    5.74 +{
    5.75 +	if(goat3d_getopt(g, GOAT3D_OPT_SAVEXML)) {
    5.76 +		return g->scn->save_anim_xml(root, io) ? 0 : -1;
    5.77 +	}
    5.78 +	return g->scn->save_anim(root, io) ? 0 : -1;
    5.79 +}
    5.80 +
    5.81 +
    5.82  GOAT3DAPI int goat3d_set_name(struct goat3d *g, const char *name)
    5.83  {
    5.84  	g->scn->set_name(name);
    5.85 @@ -704,6 +772,61 @@
    5.86  	return (goat3d_node*)node->get_child(idx);
    5.87  }
    5.88  
    5.89 +GOAT3DAPI struct goat3d_node *goat3d_get_node_parent(const struct goat3d_node *node)
    5.90 +{
    5.91 +	return (goat3d_node*)node->get_parent();
    5.92 +}
    5.93 +
    5.94 +GOAT3DAPI void goat3d_use_anim(struct goat3d_node *node, int idx)
    5.95 +{
    5.96 +	node->use_animation(idx);
    5.97 +}
    5.98 +
    5.99 +GOAT3DAPI void goat3d_use_anims(struct goat3d_node *node, int aidx, int bidx, float t)
   5.100 +{
   5.101 +	node->use_animation(aidx, bidx, t);
   5.102 +}
   5.103 +
   5.104 +GOAT3DAPI void goat3d_use_anim_by_name(struct goat3d_node *node, const char *name)
   5.105 +{
   5.106 +	node->use_animation(name);
   5.107 +}
   5.108 +
   5.109 +GOAT3DAPI void goat3d_use_anims_by_name(struct goat3d_node *node, const char *aname, const char *bname, float t)
   5.110 +{
   5.111 +	node->use_animation(aname, bname, t);
   5.112 +}
   5.113 +
   5.114 +GOAT3DAPI int goat3d_get_active_anim(struct goat3d_node *node, int which)
   5.115 +{
   5.116 +	return node->get_active_animation_index(which);
   5.117 +}
   5.118 +
   5.119 +GOAT3DAPI float goat3d_get_active_anim_mix(struct goat3d_node *node)
   5.120 +{
   5.121 +	return node->get_active_animation_mix();
   5.122 +}
   5.123 +
   5.124 +GOAT3DAPI int goat3d_get_anim_count(struct goat3d_node *node)
   5.125 +{
   5.126 +	return node->get_animation_count();
   5.127 +}
   5.128 +
   5.129 +GOAT3DAPI void goat3d_add_anim(struct goat3d_node *root)
   5.130 +{
   5.131 +	root->add_animation();
   5.132 +}
   5.133 +
   5.134 +GOAT3DAPI void goat3d_set_anim_name(struct goat3d_node *root, const char *name)
   5.135 +{
   5.136 +	root->set_animation_name(name);
   5.137 +}
   5.138 +
   5.139 +GOAT3DAPI const char *goat3d_get_anim_name(struct goat3d_node *node)
   5.140 +{
   5.141 +	return node->get_animation_name();
   5.142 +}
   5.143 +
   5.144  GOAT3DAPI void goat3d_set_node_position(struct goat3d_node *node, float x, float y, float z, long tmsec)
   5.145  {
   5.146  	node->set_position(Vector3(x, y, z), tmsec);
     6.1 --- a/src/goat3d.h	Sun Dec 08 03:00:25 2013 +0200
     6.2 +++ b/src/goat3d.h	Sat Dec 28 06:47:39 2013 +0200
     6.3 @@ -88,6 +88,16 @@
     6.4  GOAT3DAPI int goat3d_load_io(struct goat3d *g, struct goat3d_io *io);
     6.5  GOAT3DAPI int goat3d_save_io(const struct goat3d *g, struct goat3d_io *io);
     6.6  
     6.7 +/* load/save animation files (g must already be loaded to load animations) */
     6.8 +GOAT3DAPI int goat3d_load_anim(struct goat3d *g, const char *fname);
     6.9 +GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const struct goat3d_node *root, const char *fname);
    6.10 +
    6.11 +GOAT3DAPI int goat3d_load_anim_file(struct goat3d *g, FILE *fp);
    6.12 +GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, const struct goat3d_node *root, FILE *fp);
    6.13 +
    6.14 +GOAT3DAPI int goat3d_load_anim_io(struct goat3d *g, struct goat3d_io *io);
    6.15 +GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, const struct goat3d_node *root, struct goat3d_io *io);
    6.16 +
    6.17  /* misc scene properties */
    6.18  GOAT3DAPI int goat3d_set_name(struct goat3d *g, const char *name);
    6.19  GOAT3DAPI const char *goat3d_get_name(const struct goat3d *g);
    6.20 @@ -147,9 +157,9 @@
    6.21  		const void *data, int vnum);
    6.22  GOAT3DAPI void goat3d_add_mesh_attrib1f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, float val);
    6.23  GOAT3DAPI void goat3d_add_mesh_attrib3f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib,
    6.24 - 		float x, float y, float z);
    6.25 +		float x, float y, float z);
    6.26  GOAT3DAPI void goat3d_add_mesh_attrib4f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib,
    6.27 - 		float x, float y, float z, float w);
    6.28 +		float x, float y, float z, float w);
    6.29  /* returns a pointer to the beginning of the requested mesh attribute array */
    6.30  GOAT3DAPI void *goat3d_get_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib);
    6.31  /* returns a pointer to the requested mesh attribute */
    6.32 @@ -216,6 +226,21 @@
    6.33  GOAT3DAPI void goat3d_add_node_child(struct goat3d_node *node, struct goat3d_node *child);
    6.34  GOAT3DAPI int goat3d_get_node_child_count(const struct goat3d_node *node);
    6.35  GOAT3DAPI struct goat3d_node *goat3d_get_node_child(const struct goat3d_node *node, int idx);
    6.36 +GOAT3DAPI struct goat3d_node *goat3d_get_node_parent(const struct goat3d_node *node);
    6.37 +
    6.38 +GOAT3DAPI void goat3d_use_anim(struct goat3d_node *node, int idx);
    6.39 +GOAT3DAPI void goat3d_use_anims(struct goat3d_node *node, int aidx, int bidx, float t);
    6.40 +GOAT3DAPI void goat3d_use_anim_by_name(struct goat3d_node *node, const char *name);
    6.41 +GOAT3DAPI void goat3d_use_anims_by_name(struct goat3d_node *node, const char *aname, const char *bname, float t);
    6.42 +
    6.43 +GOAT3DAPI int goat3d_get_active_anim(struct goat3d_node *node, int which);
    6.44 +GOAT3DAPI float goat3d_get_active_anim_mix(struct goat3d_node *node);
    6.45 +
    6.46 +GOAT3DAPI int goat3d_get_anim_count(struct goat3d_node *node);
    6.47 +GOAT3DAPI void goat3d_add_anim(struct goat3d_node *root);
    6.48 +
    6.49 +GOAT3DAPI void goat3d_set_anim_name(struct goat3d_node *root, const char *name);
    6.50 +GOAT3DAPI const char *goat3d_get_anim_name(struct goat3d_node *node);
    6.51  
    6.52  GOAT3DAPI void goat3d_set_node_position(struct goat3d_node *node, float x, float y, float z, long tmsec);
    6.53  GOAT3DAPI void goat3d_set_node_rotation(struct goat3d_node *node, float qx, float qy, float qz, float qw, long tmsec);
     7.1 --- a/src/goat3d_impl.h	Sun Dec 08 03:00:25 2013 +0200
     7.2 +++ b/src/goat3d_impl.h	Sat Dec 28 06:47:39 2013 +0200
     7.3 @@ -10,6 +10,8 @@
     7.4  #include "material.h"
     7.5  #include "node.h"
     7.6  
     7.7 +namespace g3dimpl {
     7.8 +
     7.9  extern int goat_log_level;
    7.10  
    7.11  #if __cplusplus >= 201103L
    7.12 @@ -77,9 +79,17 @@
    7.13  
    7.14  	bool loadxml(goat3d_io *io);
    7.15  	bool savexml(goat3d_io *io) const;
    7.16 +
    7.17 +	bool load_anim(goat3d_io *io);
    7.18 +	bool save_anim(const XFormNode *node, goat3d_io *io) const;
    7.19 +
    7.20 +	bool load_anim_xml(goat3d_io *io);
    7.21 +	bool save_anim_xml(const XFormNode *node, goat3d_io *io) const;
    7.22  };
    7.23  
    7.24  void io_fprintf(goat3d_io *io, const char *fmt, ...);
    7.25  void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap);
    7.26  
    7.27 +}	// namespace g3dimpl
    7.28 +
    7.29  #endif	// GOAT3D_IMPL_H_
     8.1 --- a/src/goat3d_readxml.cc	Sun Dec 08 03:00:25 2013 +0200
     8.2 +++ b/src/goat3d_readxml.cc	Sat Dec 28 06:47:39 2013 +0200
     8.3 @@ -4,6 +4,7 @@
     8.4  #include "tinyxml2.h"
     8.5  #include "log.h"
     8.6  
     8.7 +using namespace g3dimpl;
     8.8  using namespace tinyxml2;
     8.9  
    8.10  static Material *read_material(Scene *scn, XMLElement *xml_mtl);
     9.1 --- a/src/goat3d_write.cc	Sun Dec 08 03:00:25 2013 +0200
     9.2 +++ b/src/goat3d_write.cc	Sat Dec 28 06:47:39 2013 +0200
     9.3 @@ -1,6 +1,8 @@
     9.4  #include "goat3d_impl.h"
     9.5  #include "chunk.h"
     9.6  
     9.7 +using namespace g3dimpl;
     9.8 +
     9.9  /*
    9.10  static long save_env(const Scene *scn, long offset, goat3d_io *io);
    9.11  static long save_materials(const Scene *scn, long offset, goat3d_io *io);
    10.1 --- a/src/goat3d_writexml.cc	Sun Dec 08 03:00:25 2013 +0200
    10.2 +++ b/src/goat3d_writexml.cc	Sat Dec 28 06:47:39 2013 +0200
    10.3 @@ -1,12 +1,17 @@
    10.4 +#include <list>
    10.5  #include <stdarg.h>
    10.6  #include "goat3d_impl.h"
    10.7 +#include "anim/anim.h"
    10.8  #include "log.h"
    10.9  
   10.10 +using namespace g3dimpl;
   10.11 +
   10.12  static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level);
   10.13  static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level);
   10.14  static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level);
   10.15  static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level);
   10.16  static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level);
   10.17 +static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level);
   10.18  static void xmlout(goat3d_io *io, int level, const char *fmt, ...);
   10.19  
   10.20  bool Scene::savexml(goat3d_io *io) const
   10.21 @@ -38,6 +43,39 @@
   10.22  	return true;
   10.23  }
   10.24  
   10.25 +static void collect_nodes(std::list<const XFormNode*> *res, const XFormNode *node)
   10.26 +{
   10.27 +	if(!node) return;
   10.28 +
   10.29 +	res->push_back(node);
   10.30 +
   10.31 +	for(int i=0; i<node->get_children_count(); i++) {
   10.32 +		collect_nodes(res, node->get_child(i));
   10.33 +	}
   10.34 +}
   10.35 +
   10.36 +bool Scene::save_anim_xml(const XFormNode *node, goat3d_io *io) const
   10.37 +{
   10.38 +	xmlout(io, 0, "<anim>\n");
   10.39 +
   10.40 +	const char *anim_name = node->get_animation_name();
   10.41 +	if(anim_name && *anim_name) {
   10.42 +		xmlout(io, 1, "<name string=\"%s\"/>\n", anim_name);
   10.43 +	}
   10.44 +
   10.45 +	std::list<const XFormNode*> allnodes;
   10.46 +	collect_nodes(&allnodes, node);
   10.47 +
   10.48 +	std::list<const XFormNode*>::const_iterator it = allnodes.begin();
   10.49 +	while(it != allnodes.end()) {
   10.50 +		const XFormNode *n = *it++;
   10.51 +		write_node_anim(io, n, 1);
   10.52 +	}
   10.53 +
   10.54 +	xmlout(io, 0, "</anim>\n");
   10.55 +	return true;
   10.56 +}
   10.57 +
   10.58  static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level)
   10.59  {
   10.60  	xmlout(io, level, "<mtl>\n");
   10.61 @@ -100,7 +138,7 @@
   10.62  	xmlout(io, level, "<node>\n");
   10.63  	xmlout(io, level + 1, "<name string=\"%s\"/>\n", node->get_name());
   10.64  
   10.65 -	XFormNode *parent = node->get_parent();
   10.66 +	const XFormNode *parent = node->get_parent();
   10.67  	if(parent) {
   10.68  		xmlout(io, level + 1, "<parent string=\"%s\"/>\n", parent->get_name());
   10.69  	}
   10.70 @@ -140,6 +178,55 @@
   10.71  	return true;
   10.72  }
   10.73  
   10.74 +static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level)
   10.75 +{
   10.76 +	static const char *attr_names[] = { "position", "rotation", "scaling" };
   10.77 +	struct anm_node *anode = node->get_libanim_node();
   10.78 +	struct anm_animation *anim = anm_get_active_animation(anode, 0);
   10.79 +
   10.80 +	if(!anode || !anim) {
   10.81 +		return false;
   10.82 +	}
   10.83 +
   10.84 +	struct anm_track *trk[4];
   10.85 +
   10.86 +	for(int i=0; i<3; i++) {	// 3 attributes
   10.87 +		switch(i) {
   10.88 +		case 0:	// position
   10.89 +			trk[0] = anim->tracks + ANM_TRACK_POS_X;
   10.90 +			trk[1] = anim->tracks + ANM_TRACK_POS_Y;
   10.91 +			trk[2] = anim->tracks + ANM_TRACK_POS_Z;
   10.92 +			trk[3] = 0;
   10.93 +			break;
   10.94 +
   10.95 +		case 1:	// rotation
   10.96 +			trk[0] = anim->tracks + ANM_TRACK_ROT_X;
   10.97 +			trk[1] = anim->tracks + ANM_TRACK_ROT_Y;
   10.98 +			trk[2] = anim->tracks + ANM_TRACK_ROT_Z;
   10.99 +			trk[3] = anim->tracks + ANM_TRACK_ROT_W;
  10.100 +			break;
  10.101 +
  10.102 +		case 2:	// scaling
  10.103 +			trk[0] = anim->tracks + ANM_TRACK_SCL_X;
  10.104 +			trk[1] = anim->tracks + ANM_TRACK_SCL_Y;
  10.105 +			trk[2] = anim->tracks + ANM_TRACK_SCL_Z;
  10.106 +			trk[3] = 0;
  10.107 +		}
  10.108 +
  10.109 +		if(trk[0]->count <= 0) {
  10.110 +			continue;	// skip tracks without any keyframes
  10.111 +		}
  10.112 +
  10.113 +		xmlout(io, level + 1, "<track>\n");
  10.114 +		xmlout(io, level + 2, "<node string=\"%s\"/>\n", node->get_name());
  10.115 +		xmlout(io, level + 2, "<attr string=\"%s\"/>\n", attr_names[i]);
  10.116 +
  10.117 +		// TODO cont: move all the keyframe retreival to XFormNode and use that...
  10.118 +
  10.119 +		xmlout(io, level + 1, "</track>\n");
  10.120 +	}
  10.121 +	return true;
  10.122 +}
  10.123  
  10.124  static void xmlout(goat3d_io *io, int level, const char *fmt, ...)
  10.125  {
    11.1 --- a/src/light.cc	Sun Dec 08 03:00:25 2013 +0200
    11.2 +++ b/src/light.cc	Sat Dec 28 06:47:39 2013 +0200
    11.3 @@ -1,5 +1,7 @@
    11.4  #include "light.h"
    11.5  
    11.6 +using namespace g3dimpl;
    11.7 +
    11.8  Light::Light()
    11.9  	: color(1, 1, 1), attenuation(1, 0, 0)
   11.10  {
    12.1 --- a/src/light.h	Sun Dec 08 03:00:25 2013 +0200
    12.2 +++ b/src/light.h	Sat Dec 28 06:47:39 2013 +0200
    12.3 @@ -4,6 +4,8 @@
    12.4  #include <vmath/vmath.h>
    12.5  #include "object.h"
    12.6  
    12.7 +namespace g3dimpl {
    12.8 +
    12.9  class Light : public Object {
   12.10  public:
   12.11  	Vector3 color;
   12.12 @@ -27,4 +29,6 @@
   12.13  	SpotLight();
   12.14  };
   12.15  
   12.16 +}	// namespace g3dimpl
   12.17 +
   12.18  #endif	// LIGHT_H_
    13.1 --- a/src/log.cc	Sun Dec 08 03:00:25 2013 +0200
    13.2 +++ b/src/log.cc	Sat Dec 28 06:47:39 2013 +0200
    13.3 @@ -4,7 +4,7 @@
    13.4  
    13.5  int goat_log_level = 256;
    13.6  
    13.7 -void logmsg(int prio, const char *fmt, ...)
    13.8 +void g3dimpl::logmsg(int prio, const char *fmt, ...)
    13.9  {
   13.10  	va_list ap;
   13.11  
    14.1 --- a/src/log.h	Sun Dec 08 03:00:25 2013 +0200
    14.2 +++ b/src/log.h	Sat Dec 28 06:47:39 2013 +0200
    14.3 @@ -1,8 +1,12 @@
    14.4  #ifndef LOG_H_
    14.5  #define LOG_H_
    14.6  
    14.7 +namespace g3dimpl {
    14.8 +
    14.9  enum { LOG_ERROR, LOG_INFO };
   14.10  
   14.11  void logmsg(int prio, const char *fmt, ...);
   14.12  
   14.13 +}	// namespace g3dimpl
   14.14 +
   14.15  #endif	// LOG_H_
    15.1 --- a/src/material.cc	Sun Dec 08 03:00:25 2013 +0200
    15.2 +++ b/src/material.cc	Sat Dec 28 06:47:39 2013 +0200
    15.3 @@ -1,5 +1,7 @@
    15.4  #include "material.h"
    15.5  
    15.6 +using namespace g3dimpl;
    15.7 +
    15.8  MaterialAttrib Material::def_attr;
    15.9  
   15.10  int Material::get_attrib_count() const
    16.1 --- a/src/material.h	Sun Dec 08 03:00:25 2013 +0200
    16.2 +++ b/src/material.h	Sat Dec 28 06:47:39 2013 +0200
    16.3 @@ -5,6 +5,8 @@
    16.4  #include <map>
    16.5  #include <vmath/vmath.h>
    16.6  
    16.7 +namespace g3dimpl {
    16.8 +
    16.9  struct MaterialAttrib {
   16.10  	Vector4 value;
   16.11  	std::string map;
   16.12 @@ -31,4 +33,6 @@
   16.13  	const MaterialAttrib &operator [](const std::string &name) const;
   16.14  };
   16.15  
   16.16 +}	// namespace g3dimpl
   16.17 +
   16.18  #endif	// MATERIAL_H_
    17.1 --- a/src/mesh.cc	Sun Dec 08 03:00:25 2013 +0200
    17.2 +++ b/src/mesh.cc	Sat Dec 28 06:47:39 2013 +0200
    17.3 @@ -3,6 +3,8 @@
    17.4  #include "openctm.h"
    17.5  #include "log.h"
    17.6  
    17.7 +using namespace g3dimpl;
    17.8 +
    17.9  Int4::Int4()
   17.10  {
   17.11  	x = y = z = w = 0;
    18.1 --- a/src/mesh.h	Sun Dec 08 03:00:25 2013 +0200
    18.2 +++ b/src/mesh.h	Sat Dec 28 06:47:39 2013 +0200
    18.3 @@ -5,6 +5,8 @@
    18.4  #include "object.h"
    18.5  #include "material.h"
    18.6  
    18.7 +namespace g3dimpl {
    18.8 +
    18.9  class Node;
   18.10  
   18.11  struct Face {
   18.12 @@ -43,4 +45,6 @@
   18.13  	const Material *get_material() const;
   18.14  };
   18.15  
   18.16 +}	// namespace g3dimpl
   18.17 +
   18.18  #endif	// MESH_H_
    19.1 --- a/src/node.cc	Sun Dec 08 03:00:25 2013 +0200
    19.2 +++ b/src/node.cc	Sat Dec 28 06:47:39 2013 +0200
    19.3 @@ -2,6 +2,8 @@
    19.4  #include <string.h>
    19.5  #include "node.h"
    19.6  
    19.7 +using namespace g3dimpl;
    19.8 +
    19.9  Node::Node()
   19.10  {
   19.11  	obj = 0;
   19.12 @@ -22,7 +24,7 @@
   19.13  	return obj;
   19.14  }
   19.15  
   19.16 -void delete_node_tree(Node *n)
   19.17 +void g3dimpl::delete_node_tree(Node *n)
   19.18  {
   19.19  	for(int i=0; i<n->get_children_count(); i++) {
   19.20  		delete_node_tree((Node*)n->get_child(i));
    20.1 --- a/src/node.h	Sun Dec 08 03:00:25 2013 +0200
    20.2 +++ b/src/node.h	Sat Dec 28 06:47:39 2013 +0200
    20.3 @@ -4,6 +4,8 @@
    20.4  #include "xform_node.h"
    20.5  #include "object.h"
    20.6  
    20.7 +namespace g3dimpl {
    20.8 +
    20.9  class Node : public XFormNode {
   20.10  private:
   20.11  	Object *obj;
   20.12 @@ -18,4 +20,6 @@
   20.13  
   20.14  void delete_node_tree(Node *n);
   20.15  
   20.16 +}	// namespace g3dimpl
   20.17 +
   20.18  #endif	// NODE_H_
    21.1 --- a/src/scene.cc	Sun Dec 08 03:00:25 2013 +0200
    21.2 +++ b/src/scene.cc	Sat Dec 28 06:47:39 2013 +0200
    21.3 @@ -3,6 +3,8 @@
    21.4  #include "goat3d_impl.h"
    21.5  #include "chunk.h"
    21.6  
    21.7 +using namespace g3dimpl;
    21.8 +
    21.9  Scene::Scene()
   21.10  	: name("unnamed"), ambient(0.05, 0.05, 0.05)
   21.11  {
   21.12 @@ -213,7 +215,7 @@
   21.13  // Scene::savexml is defined in goat3d_writexml.cc
   21.14  
   21.15  
   21.16 -void io_fprintf(goat3d_io *io, const char *fmt, ...)
   21.17 +void g3dimpl::io_fprintf(goat3d_io *io, const char *fmt, ...)
   21.18  {
   21.19  	va_list ap;
   21.20  
   21.21 @@ -223,7 +225,7 @@
   21.22  }
   21.23  
   21.24  
   21.25 -void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap)
   21.26 +void g3dimpl::io_vfprintf(goat3d_io *io, const char *fmt, va_list ap)
   21.27  {
   21.28  	char smallbuf[256];
   21.29  	char *buf = smallbuf;
    22.1 --- a/src/xform_node.cc	Sun Dec 08 03:00:25 2013 +0200
    22.2 +++ b/src/xform_node.cc	Sat Dec 28 06:47:39 2013 +0200
    22.3 @@ -1,8 +1,10 @@
    22.4  #include <assert.h>
    22.5  #include <algorithm>
    22.6  #include "xform_node.h"
    22.7 -#include "anim.h"
    22.8 -#include "track.h"
    22.9 +#include "anim/anim.h"
   22.10 +#include "anim/track.h"
   22.11 +
   22.12 +using namespace g3dimpl;
   22.13  
   22.14  static inline anm_interpolator track_interpolator(Interp in);
   22.15  static inline anm_extrapolator track_extrapolator(Extrap ex);
   22.16 @@ -11,8 +13,11 @@
   22.17  {
   22.18  	anm = new anm_node;
   22.19  	anm_init_node(anm);
   22.20 +	parent = 0;
   22.21  
   22.22 -	parent = 0;
   22.23 +	// TODO read them from anm to get the correct initial values
   22.24 +	interp = INTERP_LINEAR;
   22.25 +	extrap = EXTRAP_EXTEND;
   22.26  }
   22.27  
   22.28  XFormNode::~XFormNode()
   22.29 @@ -21,6 +26,11 @@
   22.30  	delete anm;
   22.31  }
   22.32  
   22.33 +struct anm_node *XFormNode::get_libanim_node() const
   22.34 +{
   22.35 +	return anm;
   22.36 +}
   22.37 +
   22.38  void XFormNode::set_name(const char *name)
   22.39  {
   22.40  	anm_set_node_name(anm, name);
   22.41 @@ -53,6 +63,16 @@
   22.42  	return extrap;
   22.43  }
   22.44  
   22.45 +XFormNode *XFormNode::get_parent()
   22.46 +{
   22.47 +	return parent;
   22.48 +}
   22.49 +
   22.50 +const XFormNode *XFormNode::get_parent() const
   22.51 +{
   22.52 +	return parent;
   22.53 +}
   22.54 +
   22.55  void XFormNode::add_child(XFormNode *child)
   22.56  {
   22.57  	children.push_back(child);
   22.58 @@ -67,8 +87,11 @@
   22.59  	if(it != children.end()) {
   22.60  		children.erase(it);
   22.61  		anm_unlink_node(anm, child->anm);
   22.62 +
   22.63 +		if(child->parent == this) {
   22.64 +			child->parent = 0;
   22.65 +		}
   22.66  	}
   22.67 -	child->parent = 0;
   22.68  }
   22.69  
   22.70  int XFormNode::get_children_count() const
   22.71 @@ -92,11 +115,77 @@
   22.72  	return 0;
   22.73  }
   22.74  
   22.75 -XFormNode *XFormNode::get_parent() const
   22.76 +
   22.77 +void XFormNode::use_animation(int idx)
   22.78  {
   22.79 -	return parent;
   22.80 +	if(idx >= 0) {
   22.81 +		anm_use_animation(anm, idx);
   22.82 +	}
   22.83  }
   22.84  
   22.85 +void XFormNode::use_animation(const char *name)
   22.86 +{
   22.87 +	anm_use_animation(anm, anm_find_animation(anm, name));
   22.88 +}
   22.89 +
   22.90 +void XFormNode::use_animation(int aidx, int bidx, float t)
   22.91 +{
   22.92 +	anm_use_animations(anm, aidx, bidx, t);
   22.93 +}
   22.94 +
   22.95 +void XFormNode::use_animation(const char *aname, const char *bname, float t)
   22.96 +{
   22.97 +	int aidx = anm_find_animation(anm, aname);
   22.98 +	int bidx = anm_find_animation(anm, bname);
   22.99 +
  22.100 +	if(aidx == -1) {
  22.101 +		use_animation(bidx);
  22.102 +	}
  22.103 +	if(bidx == -1) {
  22.104 +		use_animation(aidx);
  22.105 +	}
  22.106 +	anm_use_animations(anm, aidx, bidx, t);
  22.107 +}
  22.108 +
  22.109 +int XFormNode::get_active_animation_index(int which) const
  22.110 +{
  22.111 +	return anm_get_active_animation_index(anm, which);
  22.112 +}
  22.113 +
  22.114 +float XFormNode::get_active_animation_mix() const
  22.115 +{
  22.116 +	return anm_get_active_animation_mix(anm);
  22.117 +}
  22.118 +
  22.119 +int XFormNode::get_animation_count() const
  22.120 +{
  22.121 +	return anm_get_animation_count(anm);
  22.122 +}
  22.123 +
  22.124 +void XFormNode::add_animation(const char *name)
  22.125 +{
  22.126 +	int idx = get_animation_count();
  22.127 +
  22.128 +	anm_add_animation(anm);
  22.129 +	use_animation(idx);
  22.130 +
  22.131 +	if(name) {
  22.132 +		set_animation_name(name);
  22.133 +	}
  22.134 +}
  22.135 +
  22.136 +void XFormNode::set_animation_name(const char *name)
  22.137 +{
  22.138 +	anm_set_active_animation_name(anm, name);
  22.139 +}
  22.140 +
  22.141 +const char *XFormNode::get_animation_name() const
  22.142 +{
  22.143 +	return anm_get_active_animation_name(anm);
  22.144 +}
  22.145 +
  22.146 +
  22.147 +
  22.148  void XFormNode::set_position(const Vector3 &pos, long tmsec)
  22.149  {
  22.150  	anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec));
    23.1 --- a/src/xform_node.h	Sun Dec 08 03:00:25 2013 +0200
    23.2 +++ b/src/xform_node.h	Sat Dec 28 06:47:39 2013 +0200
    23.3 @@ -1,6 +1,3 @@
    23.4 -/*
    23.5 -TODO: add multiple animations per node in libanim (i.e. multiple sets of tracks)
    23.6 -*/
    23.7  #ifndef XFORM_NODE_H_
    23.8  #define XFORM_NODE_H_
    23.9  
   23.10 @@ -9,13 +6,16 @@
   23.11  #include "vmath/quat.h"
   23.12  #include "vmath/matrix.h"
   23.13  
   23.14 -enum Interp { INTERP_STEP, INTERP_LINEAR, INTERP_CUBIC };
   23.15 -enum Extrap { EXTRAP_EXTEND, EXTRAP_CLAMP, EXTRAP_REPEAT };
   23.16  
   23.17  struct anm_node;
   23.18  struct anm_track;
   23.19  
   23.20 -// XXX all time arguments are milliseconds
   23.21 +namespace g3dimpl {
   23.22 +
   23.23 +enum Interp { INTERP_STEP, INTERP_LINEAR, INTERP_CUBIC };
   23.24 +enum Extrap { EXTRAP_EXTEND, EXTRAP_CLAMP, EXTRAP_REPEAT };
   23.25 +
   23.26 +// NOTE: all time arguments are milliseconds
   23.27  
   23.28  class XFormNode {
   23.29  private:
   23.30 @@ -36,6 +36,9 @@
   23.31  	XFormNode();
   23.32  	virtual ~XFormNode();
   23.33  
   23.34 +	// retrieve the pointer to the underlying libanim data structure
   23.35 +	virtual struct anm_node *get_libanim_node() const;
   23.36 +
   23.37  	virtual void set_name(const char *name);
   23.38  	virtual const char *get_name() const;
   23.39  
   23.40 @@ -44,6 +47,9 @@
   23.41  	virtual void set_extrapolator(Extrap ex);
   23.42  	virtual Extrap get_extrapolator() const;
   23.43  
   23.44 +	virtual XFormNode *get_parent();
   23.45 +	virtual const XFormNode *get_parent() const;
   23.46 +
   23.47  	// children management
   23.48  	virtual void add_child(XFormNode *child);
   23.49  	virtual void remove_child(XFormNode *child);
   23.50 @@ -52,7 +58,24 @@
   23.51  	virtual XFormNode *get_child(int idx);
   23.52  	virtual const XFormNode *get_child(int idx) const;
   23.53  
   23.54 -	virtual XFormNode *get_parent() const;
   23.55 +
   23.56 +	virtual void use_animation(int idx);
   23.57 +	virtual void use_animation(const char *name);
   23.58 +	virtual void use_animation(int aidx, int bidx, float t);
   23.59 +	virtual void use_animation(const char *aname, const char *bname, float t);
   23.60 +
   23.61 +	virtual int get_active_animation_index(int which = 0) const;
   23.62 +	virtual float get_active_animation_mix() const;
   23.63 +
   23.64 +	virtual int get_animation_count() const;
   23.65 +
   23.66 +	// add a new empty animation slot (recursive)
   23.67 +	virtual void add_animation(const char *name = 0);
   23.68 +
   23.69 +	// set/get the current animation name (set is recursive)
   23.70 +	virtual void set_animation_name(const char *name);
   23.71 +	virtual const char *get_animation_name() const;
   23.72 +
   23.73  
   23.74  	virtual void set_position(const Vector3 &pos, long tmsec = 0);
   23.75  	virtual Vector3 get_node_position(long tmsec = 0) const;
   23.76 @@ -133,4 +156,6 @@
   23.77  	Vector3 operator ()(long tmsec = 0) const;
   23.78  };
   23.79  
   23.80 +}	// namespace g3dimpl
   23.81 +
   23.82  #endif	/* XFORM_NODE_H_ */