dae.c (14338B)
1 2 #include "xml.h" 3 #include "util.h" 4 #include "animation.h" 5 #include "debug.h" 6 #include "dae.h" 7 8 enum dae_state { 9 PARSING_START, 10 PARSING_NODE, 11 PARSING_FLOAT_ARRAY, 12 PARSING_POSE, 13 PARSING_JOINT, 14 PARSING_JOINT_MATRIX, 15 PARSING_WEIGHTS, 16 PARSING_POSITIONS, 17 PARSING_COLORS, 18 PARSING_COLOR_INDEX, 19 PARSING_TRIANGLES, 20 PARSING_INDICES, 21 PARSING_TEX_COORDS, 22 PARSING_NORMALS, 23 }; 24 25 enum semantic_type { 26 SEM_VERTEX, 27 SEM_NORMAL, 28 SEM_COLOR, 29 SEM_TEXCOORD, 30 N_SEMTYPES 31 }; 32 33 struct dae_data { 34 int node_level; 35 int state; 36 FILE *dae_file; 37 struct model *model; 38 struct make_geometry *geom; 39 40 u32 *indices; 41 float *colors; 42 float *normals; 43 44 int n_indices; 45 int prev_tris; 46 int n_tris; 47 48 enum semantic_type current_sem; 49 int offsets[N_SEMTYPES]; 50 int semflags; // 1 << semantic_type 51 52 int counter; 53 char current_name[JOINT_LABEL_SIZE]; 54 }; 55 56 static int n_attrs(int semflags) 57 { 58 int count = 0; 59 for (int i = 0; i < N_SEMTYPES; i++) 60 count += (semflags & (1 << i)) == (1 << i); 61 return count; 62 } 63 64 static void parse_joint(const char *t, int id, struct joint *joint) 65 { 66 struct node *node = get_node(&joint->node_id); 67 assert(node); 68 69 float *m = node->mat; 70 joint->id = id; 71 /* printf(" parsing joint %d: %s\n", id, t); */ 72 73 sscanf(t, "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f", 74 &m[0], &m[1], &m[2], &m[3], 75 &m[4], &m[5], &m[6], &m[7], 76 &m[8], &m[9], &m[10], &m[11], 77 &m[12], &m[13], &m[14], &m[15] 78 ); 79 } 80 81 82 static void dae_tag_start(struct xmlparser *x, const char *t, size_t tl) 83 { 84 struct dae_data *data = (struct dae_data*)x->user_data; 85 86 if (streq(t, "node")) { 87 data->state = PARSING_NODE; 88 data->node_level++; 89 } 90 else if (streq(t, "float_array")) { 91 data->state = PARSING_FLOAT_ARRAY; 92 } 93 else if (streq(t, "triangles")) { 94 data->state = PARSING_TRIANGLES; 95 } 96 else if (data->state == PARSING_TRIANGLES 97 && streq(t, "p")) { 98 data->state = PARSING_INDICES; 99 } 100 else if (data->state == PARSING_JOINT && streq(t, "matrix")) 101 data->state = PARSING_JOINT_MATRIX; 102 else 103 return; 104 } 105 106 107 static void dae_tag_end(struct xmlparser *x, const char *t, size_t tl, int what) 108 { 109 struct dae_data *data = (struct dae_data*)x->user_data; 110 111 if (streq(t, "node")) 112 data->node_level--; 113 114 if (data->state == PARSING_NODE) { 115 data->state = PARSING_START; 116 } 117 } 118 119 120 static void parse_array_with_offset(const char *d, int dl, u8 **elems, 121 const char *fmt, int nelems, 122 int elem_size, int elem_offset) 123 { 124 u8 buf[8]; 125 int i; 126 127 assert(elem_size <= 8); 128 assert(nelems > 0); 129 130 *elems = realloc(*elems, nelems * elem_size); 131 132 const char *p = d; 133 134 for (i = elem_offset; i < nelems; i++) { 135 sscanf(p, fmt, &buf); 136 memcpy(*elems + i*elem_size, &buf, elem_size); 137 138 assert(p-d < XML_BUFSIZ); 139 assert (p < d+dl); 140 while (p < d+dl) { 141 if (*(p++) == ' ') { 142 break; 143 } 144 } 145 } 146 147 assert(nelems == i); 148 } 149 150 static void parse_array(const char *d, int dl, u8 **elems, 151 const char *fmt, int nelems, int elem_size) 152 { 153 assert(*elems == NULL); 154 parse_array_with_offset(d, dl, elems, fmt, nelems, elem_size, 0); 155 } 156 157 static void parse_floats(const char *d, int dl, float **floats, int nfloats) 158 { 159 parse_array(d, dl, (u8**)floats, "%f", nfloats, sizeof(float)); 160 } 161 162 static void parse_ints_with_offset(const char *d, int dl, u32 **ints, 163 int nints, int offset) 164 { 165 parse_array_with_offset(d, dl, (u8**)ints, "%d", nints, 166 sizeof(u32), offset); 167 } 168 169 static void parse_ints(const char *d, int dl, u32 **ints, int nints) 170 { 171 parse_ints_with_offset(d, dl, ints, nints, 0); 172 } 173 174 175 static void parse_weights(struct dae_data *data, const char *d, int dl) 176 { 177 assert(data->counter != -1); 178 float *weights = NULL; 179 parse_floats(d, dl, &weights, data->counter); 180 struct model *model = data->model; 181 struct pose *pose = &model->poses[model->nposes]; 182 assert(pose); 183 pose->nweights = data->counter; 184 pose->weights = weights; 185 data->state = PARSING_POSE; 186 data->counter = -1; 187 } 188 189 static void parse_joint_matrix(struct dae_data *data, const char *d, 190 int dl) 191 { 192 assert(data->model->nposes); 193 194 struct model *model = data->model; 195 struct pose *pose = &model->poses[model->nposes - 1]; 196 assert(pose); 197 198 struct joint *joint = &pose->joints[pose->njoints]; 199 assert(joint); 200 201 struct node *node = new_node(&joint->node_id); 202 assert(node); 203 assert((int64_t)joint->node_id.id.uuid != -1); 204 assert(&joint->node_id == &pose->joints[pose->njoints].node_id); 205 206 parse_joint(d, pose->njoints, joint); 207 node_set_label(node, data->current_name); 208 joint->children_ids[0] = data->node_level; 209 pose->njoints++; 210 data->state = PARSING_POSE; 211 } 212 213 static void reset_parse_state(struct dae_data *data) 214 { 215 data->state = PARSING_POSE; 216 data->counter = -1; 217 } 218 219 static void parse_vertices(struct dae_data *data, const char *d, int dl) 220 { 221 assert(data->counter != -1); 222 parse_floats(d, dl, &data->geom->vertices, data->counter); 223 data->geom->num_verts = data->counter / 3; 224 reset_parse_state(data); 225 } 226 227 static void parse_normals(struct dae_data *data, const char *d, int dl) 228 { 229 assert(data->counter != -1); 230 parse_floats(d, dl, &data->normals, data->counter); 231 reset_parse_state(data); 232 } 233 234 static void parse_colors(struct dae_data *data, const char *d, int dl) 235 { 236 assert(data->counter != -1); 237 parse_floats(d, dl, &data->colors, data->counter); 238 reset_parse_state(data); 239 } 240 241 static void parse_indices(struct dae_data *data, const char *d, int dl) 242 { 243 assert(data->counter != -1); 244 int nattrs = n_attrs(data->semflags); 245 // debug("data->counters %d\n", data->counter); 246 // debug("prev_tris %d n_tris %d counter %d nattrs %d\n", 247 // data->prev_tris, 248 // data->n_tris, 249 // data->counter, 250 // nattrs); 251 252 parse_ints_with_offset(d, dl, &data->indices, 253 data->n_tris * 3 * nattrs, 254 data->prev_tris * 3 * nattrs ); 255 reset_parse_state(data); 256 } 257 258 static void dae_tagbody(struct xmlparser *x, const char *d, size_t dl) 259 { 260 static int count = 0; 261 struct dae_data *data = (struct dae_data*)x->user_data; 262 263 if (data->state == PARSING_JOINT_MATRIX) { 264 parse_joint_matrix(data, d, dl); 265 } 266 else if (data->geom && data->state == PARSING_POSITIONS) { 267 parse_vertices(data, d, dl); 268 } 269 else if (data->geom && data->state == PARSING_WEIGHTS) { 270 parse_weights(data, d, dl); 271 } 272 else if (data->geom && data->state == PARSING_NORMALS) { 273 parse_normals(data, d, dl); 274 } 275 else if (data->geom && data->state == PARSING_COLORS) { 276 parse_colors(data, d, dl); 277 } 278 else if (data->geom && data->state == PARSING_INDICES) { 279 parse_indices(data, d, dl); 280 } 281 /* else if (data->state == PARSING_TEX_COORDS) { */ 282 /* parse_tex_coords(data, d, dl); */ 283 /* } */ 284 } 285 286 static int dae_getc(struct xmlparser *x) 287 { 288 struct dae_data *data = (struct dae_data*)x->user_data; 289 return fgetc(data->dae_file); 290 } 291 292 void dae_attr(struct xmlparser *x, const char *t, size_t tl, 293 const char *a, size_t al, const char *v, size_t vl) 294 { 295 struct dae_data *data = (struct dae_data*)x->user_data; 296 297 if (data->state == PARSING_NODE 298 && streq(a, "id") 299 && streq(v, "Armature")) { 300 301 struct model *model = data->model; 302 struct pose *pose = &model->poses[model->nposes++]; 303 data->state = PARSING_POSE; 304 init_pose(pose); 305 } 306 else if (data->state == PARSING_FLOAT_ARRAY && streq(a, "id")) { 307 if (contains(v, "skin-weights-array")) { 308 data->state = PARSING_WEIGHTS; 309 } 310 else if (contains(v, "positions-array")) { 311 data->state = PARSING_POSITIONS; 312 } 313 else if (contains(v, "normals-array")) { 314 data->state = PARSING_NORMALS; 315 } 316 else if (contains(v, "mesh-colors")) { 317 data->state = PARSING_COLORS; 318 } 319 else if (contains(v, "mesh-map")) { 320 data->state = PARSING_TEX_COORDS; 321 } 322 } 323 // this is just for sanity checking the order of things 324 // if this ever asserts, we need to do proper offset parsing 325 else if (data->state == PARSING_TRIANGLES && streq(a, "semantic")) { 326 if (streq(v, "VERTEX")) 327 data->current_sem = SEM_VERTEX; 328 else if (streq(v, "NORMAL")) 329 data->current_sem = SEM_NORMAL; 330 else if (streq(v, "TEXCOORD")) 331 data->current_sem = SEM_TEXCOORD; 332 else if (streq(v, "COLOR")) 333 data->current_sem = SEM_COLOR; 334 else 335 assert(!"unhandled triangle attribute index"); 336 } 337 else if (data->state == PARSING_TRIANGLES 338 && streq(a, "offset")) { 339 int offset = atoi(v); 340 assert((int)data->current_sem != -1); 341 342 data->semflags |= 1 << data->current_sem; 343 data->offsets[data->current_sem] = offset; 344 } 345 else if (streq(a, "count")) { 346 data->counter = atoi(v); 347 if (data->state == PARSING_TRIANGLES) { 348 data->prev_tris = data->n_tris; 349 data->n_tris += data->counter; 350 } 351 } 352 else if (data->state == PARSING_NODE 353 && streq(a, "name")) { 354 strncpy(data->current_name, v, sizeof(data->current_name)-1); 355 } 356 else if (data->state == PARSING_NODE 357 && streq(a, "type") 358 && streq(v, "JOINT")) { 359 360 data->state = PARSING_JOINT; 361 } 362 } 363 364 static void process_joint_children(struct joint *joints, int njoints) 365 { 366 struct joint *joint, *j2; 367 for (int i = 0; i < njoints; i++) { 368 joint = &joints[i]; 369 370 // node level is stored in here on the first parser pass 371 int level = joint->children_ids[0]; 372 373 for (int j = i+1; j < njoints; j++) { 374 j2 = &joints[j]; 375 if (j2->children_ids[0] == level + 1) { 376 /* printf("%s(%d) assigning child %s(%d)\n", */ 377 /* joint->name, level, j2->name, j2->children[0]); */ 378 379 assert(joint->n_children_ids+1 < MAX_JOINT_CHILDREN); 380 joint->children_ids[joint->n_children_ids++] = j; 381 } 382 else if (j2->children_ids[0] <= level) 383 break; 384 } 385 } 386 } 387 388 static void print_indices(struct dae_data *data) 389 { 390 int nattrs = n_attrs(data->semflags); 391 for (int i = 0; i < data->n_tris * 3 * nattrs; i++) { 392 printf("%d ", data->indices[i]); 393 } 394 printf("\n"); 395 } 396 397 static void process_indices(struct dae_data *data) 398 { 399 int nattrs = n_attrs(data->semflags); 400 int num_indices = data->n_tris * 3; 401 bool has_color = data->semflags & (1 << SEM_COLOR); 402 403 assert(num_indices); 404 405 data->geom->num_indices = num_indices; 406 407 if (has_color) { 408 assert(data->offsets[SEM_COLOR] != -1); 409 data->geom->colors = calloc(num_indices, sizeof(float) * 3); 410 } 411 412 assert(data->semflags & (1 << SEM_NORMAL)); 413 assert(data->semflags & (1 << SEM_VERTEX)); 414 415 data->geom->normals = calloc(num_indices, sizeof(float) * 3); 416 data->geom->indices = calloc(num_indices, sizeof(int)); 417 418 // debug("offsets v:%d n:%d c:%d t:%d\n", 419 // data->offsets[SEM_VERTEX], 420 // data->offsets[SEM_NORMAL], 421 // data->offsets[SEM_COLOR], 422 // data->offsets[SEM_TEXCOORD]); 423 424 // debug("data->n_indices %d num_indices %d nattrs %d\n", 425 // data->n_indices, 426 // num_indices, 427 // nattrs); 428 429 /* print_indices(data); */ 430 431 assert(data->n_indices % nattrs == 0); 432 433 for (int i = 0; i < num_indices; i++) { 434 int v = i * nattrs; 435 436 int cind = 0; 437 int vind = data->indices[v + data->offsets[SEM_VERTEX]]; 438 int nind = data->indices[v + data->offsets[SEM_NORMAL]]; 439 440 assert(vind < data->geom->num_verts); 441 442 if (has_color) { 443 cind = data->indices[v + data->offsets[SEM_COLOR]]; 444 } 445 446 assert(cind < 50000); 447 448 data->geom->indices[i] = vind; 449 450 // if (i == 0) 451 // printf("first vert %f %f %f\n", 452 // (&data->geom->vertices[vind*3])[0], 453 // (&data->geom->vertices[vind*3])[1], 454 // (&data->geom->vertices[vind*3])[2]); 455 for (int j = 0; j < 3; j++) { 456 int ind = (i*3)+j; 457 458 if (has_color) { 459 data->geom->colors[ind] = (&data->colors[cind*3])[j]; 460 } 461 462 data->geom->normals[ind] = (&data->normals[nind*3])[j]; 463 } 464 } 465 466 assert(data->indices); 467 if (data->indices) 468 free(data->indices); 469 470 assert(data->normals); 471 if (data->normals) 472 free(data->normals); 473 474 assert(data->colors); 475 if (data->colors) 476 free(data->colors); 477 } 478 479 void load_dae(const char *filename, struct model *model, 480 struct make_geometry *geom) 481 { 482 struct xmlparser x = {0}; 483 struct dae_data data = { 484 .node_level = 0, 485 .state = PARSING_START, 486 .model = model, 487 .geom = geom, 488 .indices = NULL, 489 .colors = NULL, 490 .normals = NULL, 491 .n_indices = 0, 492 .n_tris = 0, 493 .prev_tris = 0, 494 .semflags = 0, 495 .current_sem = -1, 496 .counter = -1 497 }; 498 499 for (int i = 0; i < N_SEMTYPES; i++) 500 data.offsets[i] = -1; 501 502 data.dae_file = fopen(filename, "rb"); 503 if (data.dae_file == NULL) 504 exit(1); 505 506 x.user_data = &data; 507 x.xmltagstart = dae_tag_start; 508 x.xmltagend = dae_tag_end; 509 x.xmlattr = dae_attr; 510 x.xmldata = dae_tagbody; 511 /* x.xmlattrend = dae_attr_end; */ 512 x.getnext = dae_getc; 513 514 xml_parse(&x); 515 516 for (int i = 0; i < model->nposes; i++) { 517 struct pose *pose = &model->poses[i]; 518 process_joint_children(pose->joints, pose->njoints); 519 } 520 521 if (geom) 522 process_indices(&data); 523 524 fclose(data.dae_file); 525 }