goat3d
diff converters/ass2goat/src/main.c @ 55:af1310ed212b
not done yet
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 19 Jan 2014 14:56:44 +0200 |
parents | 3d669155709d |
children | ca549434dc95 |
line diff
1.1 --- a/converters/ass2goat/src/main.c Fri Jan 17 18:30:35 2014 +0200 1.2 +++ b/converters/ass2goat/src/main.c Sun Jan 19 14:56:44 2014 +0200 1.3 @@ -5,28 +5,51 @@ 1.4 #include "assimp/postprocess.h" 1.5 #include "assimp/scene.h" 1.6 1.7 -int convert(const char *infname, const char *outfname); 1.8 +enum { 1.9 + CONV_SCENE, 1.10 + CONV_ANIM 1.11 +}; 1.12 + 1.13 +int convert(const char *infname); 1.14 +int convert_anim(const char *infname); 1.15 void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl); 1.16 void process_node(struct goat3d *goat, struct goat3d_node *parent, struct aiNode *ainode); 1.17 +int process_anim(struct goat3d *goat, struct aiAnimation *aianim); 1.18 +static int output_filename(char *buf, int bufsz, const char *fname, const char *suffix); 1.19 +static long assimp_time(const struct aiAnimation *anim, double aitime); 1.20 1.21 int main(int argc, char **argv) 1.22 { 1.23 int i, num_done = 0; 1.24 + int conv_targ = CONV_SCENE; 1.25 1.26 for(i=1; i<argc; i++) { 1.27 if(argv[i][0] == '-') { 1.28 + if(argv[i][2] != 0) { 1.29 + fprintf(stderr, "invalid option: %s\n", argv[i]); 1.30 + return 1; 1.31 + } 1.32 + 1.33 + switch(argv[i][1]) { 1.34 + case 'a': 1.35 + conv_targ = CONV_ANIM; 1.36 + break; 1.37 + 1.38 + case 's': 1.39 + conv_targ = CONV_SCENE; 1.40 + break; 1.41 + 1.42 + default: 1.43 + fprintf(stderr, "invalid option: %s\n", argv[i]); 1.44 + return 1; 1.45 + } 1.46 + 1.47 } else { 1.48 - char *lastdot; 1.49 - char *outfname = malloc(strlen(argv[i]) + 4); 1.50 - strcpy(outfname, argv[i]); 1.51 - 1.52 - if((lastdot = strrchr(outfname, '.'))) { 1.53 - *lastdot = 0; 1.54 + if(conv_targ == CONV_SCENE) { 1.55 + convert(argv[i]); 1.56 + } else { 1.57 + convert_anim(argv[i]); 1.58 } 1.59 - strcat(outfname, ".xml"); 1.60 - 1.61 - printf("converting %s -> %s\n", argv[i], outfname); 1.62 - convert(argv[i], outfname); 1.63 num_done++; 1.64 } 1.65 } 1.66 @@ -39,7 +62,7 @@ 1.67 return 0; 1.68 } 1.69 1.70 -#define PPFLAGS \ 1.71 +#define SCE_PPFLAGS \ 1.72 (aiProcess_Triangulate | \ 1.73 aiProcess_GenNormals | \ 1.74 aiProcess_JoinIdenticalVertices | \ 1.75 @@ -47,13 +70,23 @@ 1.76 aiProcess_LimitBoneWeights | \ 1.77 aiProcess_GenUVCoords) 1.78 1.79 -int convert(const char *infname, const char *outfname) 1.80 +#define ANM_PPFLAGS \ 1.81 + (aiProcess_LimitBoneWeights) 1.82 + 1.83 +int convert(const char *infname) 1.84 { 1.85 - int i; 1.86 + int i, bufsz; 1.87 const struct aiScene *aiscn; 1.88 struct goat3d *goat; 1.89 + char *outfname; 1.90 1.91 - if(!(aiscn = aiImportFile(infname, PPFLAGS))) { 1.92 + bufsz = output_filename(0, 0, infname, "goat3d"); 1.93 + outfname = alloca(bufsz); 1.94 + output_filename(outfname, bufsz, infname, "goat3d"); 1.95 + printf("converting %s -> %s\n", infname, outfname); 1.96 + 1.97 + 1.98 + if(!(aiscn = aiImportFile(infname, SCE_PPFLAGS))) { 1.99 fprintf(stderr, "failed to import %s\n", infname); 1.100 return -1; 1.101 } 1.102 @@ -78,6 +111,42 @@ 1.103 return 0; 1.104 } 1.105 1.106 +int convert_anim(const char *infname) 1.107 +{ 1.108 + int i, bufsz; 1.109 + const struct aiScene *aiscn; 1.110 + struct goat3d *goat; 1.111 + char *outfname; 1.112 + 1.113 + bufsz = output_filename(0, 0, infname, "goatanim"); 1.114 + outfname = alloca(bufsz); 1.115 + output_filename(outfname, bufsz, infname, "goatanim"); 1.116 + printf("converting %s -> %s\n", infname, outfname); 1.117 + 1.118 + 1.119 + if(!(aiscn = aiImportFile(infname, ANM_PPFLAGS))) { 1.120 + fprintf(stderr, "failed to import %s\n", infname); 1.121 + return -1; 1.122 + } 1.123 + 1.124 + goat = goat3d_create(); 1.125 + 1.126 + for(i=0; i<(int)aiscn->mRootNode->mNumChildren; i++) { 1.127 + process_node(goat, 0, aiscn->mRootNode->mChildren[i]); 1.128 + } 1.129 + 1.130 + for(i=0; i<aiscn->mNumAnimations; i++) { 1.131 + if(process_anim(goat, aiscn->mAnimations[i]) == -1) { 1.132 + return -1; 1.133 + } 1.134 + } 1.135 + 1.136 + goat3d_save_anim(goat, outfname); 1.137 + goat3d_free(goat); 1.138 + aiReleaseImport(aiscn); 1.139 + return 0; 1.140 +} 1.141 + 1.142 void process_material(struct goat3d_material *mtl, struct aiMaterial *aimtl) 1.143 { 1.144 struct aiString aistr; 1.145 @@ -145,3 +214,108 @@ 1.146 1.147 goat3d_add_node(goat, node); 1.148 } 1.149 + 1.150 +int process_anim(struct goat3d *goat, struct aiAnimation *aianim) 1.151 +{ 1.152 + int i, j, num_nodes, rnodes_count; 1.153 + const char *anim_name; 1.154 + 1.155 + if(aianim->mName.length <= 0) { 1.156 + anim_name = "unnamed"; 1.157 + } else { 1.158 + anim_name = aianim->mName.data; 1.159 + } 1.160 + 1.161 + num_nodes = goat3d_get_node_count(goat); 1.162 + 1.163 + rnodes_count = 0; 1.164 + for(i=0; i<num_nodes; i++) { 1.165 + int anim_idx; 1.166 + struct goat3d_node *n = goat3d_get_node(goat, i); 1.167 + /* skip non-root nodes */ 1.168 + if(goat3d_get_node_parent(n)) { 1.169 + break; 1.170 + } 1.171 + 1.172 + /* then add another animation to those root nodes */ 1.173 + anim_idx = goat3d_get_anim_count(n); 1.174 + goat3d_add_anim(n); 1.175 + goat3d_use_anim(n, anim_idx); 1.176 + 1.177 + goat3d_set_anim_name(n, anim_name); 1.178 + } 1.179 + 1.180 + /* for each animation "channel" ... */ 1.181 + for(i=0; i<(int)aianim->mNumChannels; i++) { 1.182 + struct goat3d_node *node; 1.183 + struct aiNodeAnim *ainodeanim = aianim->mChannels[i]; 1.184 + 1.185 + /* find the node it refers to */ 1.186 + const char *nodename = ainodeanim->mNodeName.data; 1.187 + if(!(node = goat3d_get_node_by_name(goat, nodename))) { 1.188 + fprintf(stderr, "failed to process animation for unknown node: %s\n", nodename); 1.189 + return -1; 1.190 + } 1.191 + 1.192 + /* add all the keys ... */ 1.193 + for(j=0; j<(int)ainodeanim->mNumPositionKeys; j++) { 1.194 + struct aiVectorKey *key = ainodeanim->mPositionKeys + j; 1.195 + long tm = assimp_time(aianim, key->mTime); 1.196 + goat3d_set_node_position(node, key->mValue.x, key->mValue.y, key->mValue.z, tm); 1.197 + } 1.198 + 1.199 + for(j=0; j<(int)ainodeanim->mNumRotationKeys; j++) { 1.200 + struct aiQuatKey *key = ainodeanim->mRotationKeys + j; 1.201 + long tm = assimp_time(aianim, key->mTime); 1.202 + goat3d_set_node_rotation(node, key->mValue.x, key->mValue.y, key->mValue.z, key->mValue.w, tm); 1.203 + } 1.204 + 1.205 + for(j=0; j<(int)ainodeanim->mNumScalingKeys; j++) { 1.206 + struct aiVectorKey *key = ainodeanim->mScalingKeys + j; 1.207 + long tm = assimp_time(aianim, key->mTime); 1.208 + goat3d_set_node_scaling(node, key->mValue.x, key->mValue.y, key->mValue.z, tm); 1.209 + } 1.210 + } 1.211 + 1.212 + return 0; 1.213 +} 1.214 + 1.215 +static int output_filename(char *buf, int bufsz, const char *fname, const char *suffix) 1.216 +{ 1.217 + int reqsz, namesz; 1.218 + char *tmpfname; 1.219 + const char *fname_end, *lastdot; 1.220 + 1.221 + lastdot = strrchr(fname, '.'); 1.222 + 1.223 + fname_end = lastdot ? lastdot + 1 : fname + strlen(fname); 1.224 + namesz = fname_end - fname; 1.225 + reqsz = namesz + strlen(suffix) + 2; /* plus 1 for the dot */ 1.226 + 1.227 + if(buf && bufsz) { 1.228 + tmpfname = alloca(namesz + 1); 1.229 + memcpy(tmpfname, fname, namesz); 1.230 + tmpfname[namesz] = 0; 1.231 + 1.232 + if(suffix) { 1.233 + snprintf(buf, bufsz, "%s.%s", tmpfname, suffix); 1.234 + } else { 1.235 + strncpy(buf, tmpfname, bufsz); 1.236 + } 1.237 + buf[bufsz - 1] = 0; 1.238 + } 1.239 + 1.240 + return reqsz; 1.241 +} 1.242 + 1.243 +static long assimp_time(const struct aiAnimation *anim, double aitime) 1.244 +{ 1.245 + double sec; 1.246 + if(anim->mTicksPerSecond < 1e-6) { 1.247 + /* assume time in frames? */ 1.248 + sec = aitime / 30.0; 1.249 + } else { 1.250 + sec = aitime / anim->mTicksPerSecond; 1.251 + } 1.252 + return (long)(sec * 1000.0); 1.253 +}