goat3d

changeset 55:af1310ed212b

not done yet
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 19 Jan 2014 14:56:44 +0200
parents 6d514398a728
children ca549434dc95
files converters/ass2goat/.clang_complete converters/ass2goat/src/main.c src/goat3d.cc src/goat3d.h src/goat3d_impl.h src/goat3d_write.cc src/goat3d_writexml.cc
diffstat 7 files changed, 211 insertions(+), 50 deletions(-) [+]
line diff
     1.1 --- a/converters/ass2goat/.clang_complete	Fri Jan 17 18:30:35 2014 +0200
     1.2 +++ b/converters/ass2goat/.clang_complete	Sun Jan 19 14:56:44 2014 +0200
     1.3 @@ -1,2 +1,3 @@
     1.4  -I../../src
     1.5  -I/usr/local/include
     1.6 +-I/usr/local/include/assimp
     2.1 --- a/converters/ass2goat/src/main.c	Fri Jan 17 18:30:35 2014 +0200
     2.2 +++ b/converters/ass2goat/src/main.c	Sun Jan 19 14:56:44 2014 +0200
     2.3 @@ -5,28 +5,51 @@
     2.4  #include "assimp/postprocess.h"
     2.5  #include "assimp/scene.h"
     2.6  
     2.7 -int convert(const char *infname, const char *outfname);
     2.8 +enum {
     2.9 +	CONV_SCENE,
    2.10 +	CONV_ANIM
    2.11 +};
    2.12 +
    2.13 +int convert(const char *infname);
    2.14 +int convert_anim(const char *infname);
    2.15  void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl);
    2.16  void process_node(struct goat3d *goat, struct goat3d_node *parent, struct aiNode *ainode);
    2.17 +int process_anim(struct goat3d *goat, struct aiAnimation *aianim);
    2.18 +static int output_filename(char *buf, int bufsz, const char *fname, const char *suffix);
    2.19 +static long assimp_time(const struct aiAnimation *anim, double aitime);
    2.20  
    2.21  int main(int argc, char **argv)
    2.22  {
    2.23  	int i, num_done = 0;
    2.24 +	int conv_targ = CONV_SCENE;
    2.25  
    2.26  	for(i=1; i<argc; i++) {
    2.27  		if(argv[i][0] == '-') {
    2.28 +			if(argv[i][2] != 0) {
    2.29 +				fprintf(stderr, "invalid option: %s\n", argv[i]);
    2.30 +				return 1;
    2.31 +			}
    2.32 +
    2.33 +			switch(argv[i][1]) {
    2.34 +			case 'a':
    2.35 +				conv_targ = CONV_ANIM;
    2.36 +				break;
    2.37 +
    2.38 +			case 's':
    2.39 +				conv_targ = CONV_SCENE;
    2.40 +				break;
    2.41 +
    2.42 +			default:
    2.43 +				fprintf(stderr, "invalid option: %s\n", argv[i]);
    2.44 +				return 1;
    2.45 +			}
    2.46 +
    2.47  		} else {
    2.48 -			char *lastdot;
    2.49 -			char *outfname = malloc(strlen(argv[i]) + 4);
    2.50 -			strcpy(outfname, argv[i]);
    2.51 -
    2.52 -			if((lastdot = strrchr(outfname, '.'))) {
    2.53 -				*lastdot = 0;
    2.54 +			if(conv_targ == CONV_SCENE) {
    2.55 +				convert(argv[i]);
    2.56 +			} else {
    2.57 +				convert_anim(argv[i]);
    2.58  			}
    2.59 -			strcat(outfname, ".xml");
    2.60 -
    2.61 -			printf("converting %s -> %s\n", argv[i], outfname);
    2.62 -			convert(argv[i], outfname);
    2.63  			num_done++;
    2.64  		}
    2.65  	}
    2.66 @@ -39,7 +62,7 @@
    2.67  	return 0;
    2.68  }
    2.69  
    2.70 -#define PPFLAGS	\
    2.71 +#define SCE_PPFLAGS	\
    2.72  	(aiProcess_Triangulate | \
    2.73  	 aiProcess_GenNormals | \
    2.74  	 aiProcess_JoinIdenticalVertices | \
    2.75 @@ -47,13 +70,23 @@
    2.76  	 aiProcess_LimitBoneWeights | \
    2.77  	 aiProcess_GenUVCoords)
    2.78  
    2.79 -int convert(const char *infname, const char *outfname)
    2.80 +#define ANM_PPFLAGS \
    2.81 +	(aiProcess_LimitBoneWeights)
    2.82 +
    2.83 +int convert(const char *infname)
    2.84  {
    2.85 -	int i;
    2.86 +	int i, bufsz;
    2.87  	const struct aiScene *aiscn;
    2.88  	struct goat3d *goat;
    2.89 +	char *outfname;
    2.90  
    2.91 -	if(!(aiscn = aiImportFile(infname, PPFLAGS))) {
    2.92 +	bufsz = output_filename(0, 0, infname, "goat3d");
    2.93 +	outfname = alloca(bufsz);
    2.94 +	output_filename(outfname, bufsz, infname, "goat3d");
    2.95 +	printf("converting %s -> %s\n", infname, outfname);
    2.96 +
    2.97 +
    2.98 +	if(!(aiscn = aiImportFile(infname, SCE_PPFLAGS))) {
    2.99  		fprintf(stderr, "failed to import %s\n", infname);
   2.100  		return -1;
   2.101  	}
   2.102 @@ -78,6 +111,42 @@
   2.103  	return 0;
   2.104  }
   2.105  
   2.106 +int convert_anim(const char *infname)
   2.107 +{
   2.108 +	int i, bufsz;
   2.109 +	const struct aiScene *aiscn;
   2.110 +	struct goat3d *goat;
   2.111 +	char *outfname;
   2.112 +
   2.113 +	bufsz = output_filename(0, 0, infname, "goatanim");
   2.114 +	outfname = alloca(bufsz);
   2.115 +	output_filename(outfname, bufsz, infname, "goatanim");
   2.116 +	printf("converting %s -> %s\n", infname, outfname);
   2.117 +
   2.118 +
   2.119 +	if(!(aiscn = aiImportFile(infname, ANM_PPFLAGS))) {
   2.120 +		fprintf(stderr, "failed to import %s\n", infname);
   2.121 +		return -1;
   2.122 +	}
   2.123 +
   2.124 +	goat = goat3d_create();
   2.125 +
   2.126 +	for(i=0; i<(int)aiscn->mRootNode->mNumChildren; i++) {
   2.127 +		process_node(goat, 0, aiscn->mRootNode->mChildren[i]);
   2.128 +	}
   2.129 +
   2.130 +	for(i=0; i<aiscn->mNumAnimations; i++) {
   2.131 +		if(process_anim(goat, aiscn->mAnimations[i]) == -1) {
   2.132 +			return -1;
   2.133 +		}
   2.134 +	}
   2.135 +
   2.136 +	goat3d_save_anim(goat, outfname);
   2.137 +	goat3d_free(goat);
   2.138 +	aiReleaseImport(aiscn);
   2.139 +	return 0;
   2.140 +}
   2.141 +
   2.142  void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl)
   2.143  {
   2.144  	struct aiString aistr;
   2.145 @@ -145,3 +214,108 @@
   2.146  
   2.147  	goat3d_add_node(goat, node);
   2.148  }
   2.149 +
   2.150 +int process_anim(struct goat3d *goat, struct aiAnimation *aianim)
   2.151 +{
   2.152 +	int i, j, num_nodes, rnodes_count;
   2.153 +	const char *anim_name;
   2.154 +
   2.155 +	if(aianim->mName.length <= 0) {
   2.156 +		anim_name = "unnamed";
   2.157 +	} else {
   2.158 +		anim_name = aianim->mName.data;
   2.159 +	}
   2.160 +
   2.161 +	num_nodes = goat3d_get_node_count(goat);
   2.162 +
   2.163 +	rnodes_count = 0;
   2.164 +	for(i=0; i<num_nodes; i++) {
   2.165 +		int anim_idx;
   2.166 +		struct goat3d_node *n = goat3d_get_node(goat, i);
   2.167 +		/* skip non-root nodes */
   2.168 +		if(goat3d_get_node_parent(n)) {
   2.169 +			break;
   2.170 +		}
   2.171 +
   2.172 +		/* then add another animation to those root nodes */
   2.173 +		anim_idx = goat3d_get_anim_count(n);
   2.174 +		goat3d_add_anim(n);
   2.175 +		goat3d_use_anim(n, anim_idx);
   2.176 +
   2.177 +		goat3d_set_anim_name(n, anim_name);
   2.178 +	}
   2.179 +
   2.180 +	/* for each animation "channel" ... */
   2.181 +	for(i=0; i<(int)aianim->mNumChannels; i++) {
   2.182 +		struct goat3d_node *node;
   2.183 +		struct aiNodeAnim *ainodeanim = aianim->mChannels[i];
   2.184 +
   2.185 +		/* find the node it refers to */
   2.186 +		const char *nodename = ainodeanim->mNodeName.data;
   2.187 +		if(!(node = goat3d_get_node_by_name(goat, nodename))) {
   2.188 +			fprintf(stderr, "failed to process animation for unknown node: %s\n", nodename);
   2.189 +			return -1;
   2.190 +		}
   2.191 +
   2.192 +		/* add all the keys ... */
   2.193 +		for(j=0; j<(int)ainodeanim->mNumPositionKeys; j++) {
   2.194 +			struct aiVectorKey *key = ainodeanim->mPositionKeys + j;
   2.195 +			long tm = assimp_time(aianim, key->mTime);
   2.196 +			goat3d_set_node_position(node, key->mValue.x, key->mValue.y, key->mValue.z, tm);
   2.197 +		}
   2.198 +
   2.199 +		for(j=0; j<(int)ainodeanim->mNumRotationKeys; j++) {
   2.200 +			struct aiQuatKey *key = ainodeanim->mRotationKeys + j;
   2.201 +			long tm = assimp_time(aianim, key->mTime);
   2.202 +			goat3d_set_node_rotation(node, key->mValue.x, key->mValue.y, key->mValue.z, key->mValue.w, tm);
   2.203 +		}
   2.204 +
   2.205 +		for(j=0; j<(int)ainodeanim->mNumScalingKeys; j++) {
   2.206 +			struct aiVectorKey *key = ainodeanim->mScalingKeys + j;
   2.207 +			long tm = assimp_time(aianim, key->mTime);
   2.208 +			goat3d_set_node_scaling(node, key->mValue.x, key->mValue.y, key->mValue.z, tm);
   2.209 +		}
   2.210 +	}
   2.211 +
   2.212 +	return 0;
   2.213 +}
   2.214 +
   2.215 +static int output_filename(char *buf, int bufsz, const char *fname, const char *suffix)
   2.216 +{
   2.217 +	int reqsz, namesz;
   2.218 +	char *tmpfname;
   2.219 +	const char *fname_end, *lastdot;
   2.220 +
   2.221 +	lastdot = strrchr(fname, '.');
   2.222 +
   2.223 +	fname_end = lastdot ? lastdot + 1 : fname + strlen(fname);
   2.224 +	namesz = fname_end - fname;
   2.225 +	reqsz = namesz + strlen(suffix) + 2;	/* plus 1 for the dot */
   2.226 +
   2.227 +	if(buf && bufsz) {
   2.228 +		tmpfname = alloca(namesz + 1);
   2.229 +		memcpy(tmpfname, fname, namesz);
   2.230 +		tmpfname[namesz] = 0;
   2.231 +
   2.232 +		if(suffix) {
   2.233 +			snprintf(buf, bufsz, "%s.%s", tmpfname, suffix);
   2.234 +		} else {
   2.235 +			strncpy(buf, tmpfname, bufsz);
   2.236 +		}
   2.237 +		buf[bufsz - 1] = 0;
   2.238 +	}
   2.239 +
   2.240 +	return reqsz;
   2.241 +}
   2.242 +
   2.243 +static long assimp_time(const struct aiAnimation *anim, double aitime)
   2.244 +{
   2.245 +	double sec;
   2.246 +	if(anim->mTicksPerSecond < 1e-6) {
   2.247 +		/* assume time in frames? */
   2.248 +		sec = aitime / 30.0;
   2.249 +	} else {
   2.250 +		sec = aitime / anim->mTicksPerSecond;
   2.251 +	}
   2.252 +	return (long)(sec * 1000.0);
   2.253 +}
     3.1 --- a/src/goat3d.cc	Fri Jan 17 18:30:35 2014 +0200
     3.2 +++ b/src/goat3d.cc	Sun Jan 19 14:56:44 2014 +0200
     3.3 @@ -162,14 +162,14 @@
     3.4  	return res;
     3.5  }
     3.6  
     3.7 -GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const struct goat3d_node *root, const char *fname)
     3.8 +GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const char *fname)
     3.9  {
    3.10  	FILE *fp = fopen(fname, "wb");
    3.11  	if(!fp) {
    3.12  		return -1;
    3.13  	}
    3.14  
    3.15 -	int res = goat3d_save_anim_file(g, root, fp);
    3.16 +	int res = goat3d_save_anim_file(g, fp);
    3.17  	fclose(fp);
    3.18  	return res;
    3.19  }
    3.20 @@ -185,7 +185,7 @@
    3.21  	return goat3d_load_anim_io(g, &io);
    3.22  }
    3.23  
    3.24 -GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, const struct goat3d_node *root, FILE *fp)
    3.25 +GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, FILE *fp)
    3.26  {
    3.27  	goat3d_io io;
    3.28  	io.cls = fp;
    3.29 @@ -193,7 +193,7 @@
    3.30  	io.write = write_file;
    3.31  	io.seek = seek_file;
    3.32  
    3.33 -	return goat3d_save_anim_io(g, root, &io);
    3.34 +	return goat3d_save_anim_io(g, &io);
    3.35  }
    3.36  
    3.37  GOAT3DAPI int goat3d_load_anim_io(struct goat3d *g, struct goat3d_io *io)
    3.38 @@ -206,12 +206,12 @@
    3.39  	return 0;
    3.40  }
    3.41  
    3.42 -GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, const struct goat3d_node *root, struct goat3d_io *io)
    3.43 +GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, struct goat3d_io *io)
    3.44  {
    3.45  	if(goat3d_getopt(g, GOAT3D_OPT_SAVEXML)) {
    3.46 -		return g->scn->save_anim_xml(root, io) ? 0 : -1;
    3.47 +		return g->scn->save_anim_xml(io) ? 0 : -1;
    3.48  	}
    3.49 -	return g->scn->save_anim(root, io) ? 0 : -1;
    3.50 +	return g->scn->save_anim(io) ? 0 : -1;
    3.51  }
    3.52  
    3.53  
     4.1 --- a/src/goat3d.h	Fri Jan 17 18:30:35 2014 +0200
     4.2 +++ b/src/goat3d.h	Sun Jan 19 14:56:44 2014 +0200
     4.3 @@ -90,13 +90,13 @@
     4.4  
     4.5  /* load/save animation files (g must already be loaded to load animations) */
     4.6  GOAT3DAPI int goat3d_load_anim(struct goat3d *g, const char *fname);
     4.7 -GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const struct goat3d_node *root, const char *fname);
     4.8 +GOAT3DAPI int goat3d_save_anim(const struct goat3d *g, const char *fname);
     4.9  
    4.10  GOAT3DAPI int goat3d_load_anim_file(struct goat3d *g, FILE *fp);
    4.11 -GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, const struct goat3d_node *root, FILE *fp);
    4.12 +GOAT3DAPI int goat3d_save_anim_file(const struct goat3d *g, FILE *fp);
    4.13  
    4.14  GOAT3DAPI int goat3d_load_anim_io(struct goat3d *g, struct goat3d_io *io);
    4.15 -GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, const struct goat3d_node *root, struct goat3d_io *io);
    4.16 +GOAT3DAPI int goat3d_save_anim_io(const struct goat3d *g, struct goat3d_io *io);
    4.17  
    4.18  /* misc scene properties */
    4.19  GOAT3DAPI int goat3d_set_name(struct goat3d *g, const char *name);
     5.1 --- a/src/goat3d_impl.h	Fri Jan 17 18:30:35 2014 +0200
     5.2 +++ b/src/goat3d_impl.h	Sun Jan 19 14:56:44 2014 +0200
     5.3 @@ -81,10 +81,10 @@
     5.4  	bool savexml(goat3d_io *io) const;
     5.5  
     5.6  	bool load_anim(goat3d_io *io);
     5.7 -	bool save_anim(const XFormNode *node, goat3d_io *io) const;
     5.8 +	bool save_anim(goat3d_io *io) const;
     5.9  
    5.10  	bool load_anim_xml(goat3d_io *io);
    5.11 -	bool save_anim_xml(const XFormNode *node, goat3d_io *io) const;
    5.12 +	bool save_anim_xml(goat3d_io *io) const;
    5.13  };
    5.14  
    5.15  void io_fprintf(goat3d_io *io, const char *fmt, ...);
     6.1 --- a/src/goat3d_write.cc	Fri Jan 17 18:30:35 2014 +0200
     6.2 +++ b/src/goat3d_write.cc	Sun Jan 19 14:56:44 2014 +0200
     6.3 @@ -68,7 +68,7 @@
     6.4  	return false;
     6.5  }
     6.6  
     6.7 -bool Scene::save_anim(const XFormNode *node, goat3d_io *io) const
     6.8 +bool Scene::save_anim(goat3d_io *io) const
     6.9  {
    6.10  	return false;
    6.11  }
     7.1 --- a/src/goat3d_writexml.cc	Fri Jan 17 18:30:35 2014 +0200
     7.2 +++ b/src/goat3d_writexml.cc	Sun Jan 19 14:56:44 2014 +0200
     7.3 @@ -43,33 +43,19 @@
     7.4  	return true;
     7.5  }
     7.6  
     7.7 -static void collect_nodes(std::list<const XFormNode*> *res, const XFormNode *node)
     7.8 -{
     7.9 -	if(!node) return;
    7.10 -
    7.11 -	res->push_back(node);
    7.12 -
    7.13 -	for(int i=0; i<node->get_children_count(); i++) {
    7.14 -		collect_nodes(res, node->get_child(i));
    7.15 -	}
    7.16 -}
    7.17 -
    7.18 -bool Scene::save_anim_xml(const XFormNode *node, goat3d_io *io) const
    7.19 +bool Scene::save_anim_xml(goat3d_io *io) const
    7.20  {
    7.21  	xmlout(io, 0, "<anim>\n");
    7.22  
    7.23 -	const char *anim_name = node->get_animation_name();
    7.24 -	if(anim_name && *anim_name) {
    7.25 -		xmlout(io, 1, "<name string=\"%s\"/>\n", anim_name);
    7.26 +	if(!nodes.empty()) {
    7.27 +		const char *anim_name = nodes[0]->get_animation_name();
    7.28 +		if(anim_name && *anim_name) {
    7.29 +			xmlout(io, 1, "<name string=\"%s\"/>\n", anim_name);
    7.30 +		}
    7.31  	}
    7.32  
    7.33 -	std::list<const XFormNode*> allnodes;
    7.34 -	collect_nodes(&allnodes, node);
    7.35 -
    7.36 -	std::list<const XFormNode*>::const_iterator it = allnodes.begin();
    7.37 -	while(it != allnodes.end()) {
    7.38 -		const XFormNode *n = *it++;
    7.39 -		write_node_anim(io, n, 1);
    7.40 +	for(size_t i=0; i<nodes.size(); i++) {
    7.41 +		write_node_anim(io, nodes[i], 1);
    7.42  	}
    7.43  
    7.44  	xmlout(io, 0, "</anim>\n");