#include #include #include "util/util.h" #include "xml/xml.h" #include "geometry.h" /* macro to ensure tag type matches what we expect */ #define CHECK_TAG_TYPE(expected) \ if (strcmp(src->type, expected) != 0) { \ return -1; \ } /* helper macro for iterating over tag children of a particular type */ #define FOR_CHILD_OF_TYPE(parent, child, type) \ for ( \ child = kai_tag_get_first_child_with_type(parent, type); \ child != NULL; \ child = kai_tag_get_next_sibling_with_type(child, type) \ ) int kai_read_float_array(struct ka_float_array_t *dest, struct kai_tag_t *src) { CHECK_TAG_TYPE("float_array"); long count = kai_tag_attr_to_long(src, "count", -1); if (count == -1) { /* count not present */ return -1; } dest->count = count; dest->id = kai_tag_attr_to_dup(src, "id"); dest->digits = kai_tag_attr_to_long(src, "digits", 6); dest->magnitude = kai_tag_attr_to_long(src, "magnitude", 38); /* allocate & fill buffer */ dest->buf = kai_alloc( dest->count * sizeof(ka_real_t), "float_array buffer" ); if (dest->buf == NULL) { free(dest->id); return -1; } kai_text_to_reals(dest->buf, src->content, dest->count); return 0; } void kai_release_float_array(struct ka_float_array_t fa) { free(fa.id); free(fa.buf); } int kai_read_param(struct ka_param_t *dest, struct kai_tag_t *src) { CHECK_TAG_TYPE("param"); char *type = kai_tag_attr_to_dup(src, "type"); if (type == NULL) { return -1; } dest->name = kai_tag_attr_to_dup(src, "name"); dest->sid = kai_tag_attr_to_dup(src, "sid"); dest->type = type; dest->semantic = kai_tag_attr_to_dup(src, "semantic"); return 0; } void kai_release_param(struct ka_param_t p) { free(p.name); free(p.sid); free(p.type); free(p.semantic); } int kai_read_accessor(struct ka_accessor_t *dest, struct kai_tag_t *src) { CHECK_TAG_TYPE("accessor"); long count = kai_tag_attr_to_long(src, "count", -1); if (count == -1) { return -1; } char *source = kai_tag_attr_to_dup(src, "source"); if (source == NULL) { return -1; } dest->count = count; dest->offset = kai_tag_attr_to_long(src, "offset", 0); dest->source = source; dest->stride = kai_tag_attr_to_long(src, "stride", 1); dest->param_count = kai_tag_num_children(src); dest->param = kai_alloc( dest->param_count * sizeof(struct ka_param_t), "accessor tag param array" ); if (dest->param == NULL) { free(source); return -1; } struct kai_tag_t *t = src->children; int i; for (i=0; iparam_count; i++) { int result = kai_read_param(dest->param + i, t); if (result != 0) { free(dest->param); free(dest->source); return -1; } t = t->next; } return 0; } void kai_release_accessor(struct ka_accessor_t a) { free(a.source); int i; for (i=0; iid = id; dest->name = kai_tag_attr_to_dup(src, "name"); struct kai_tag_t *child; int result; child = kai_tag_get_first_child_with_type(src, "float_array"); result = kai_read_float_array(&(dest->float_array), child); if (result != 0) { free(dest->id); free(dest->name); return -1; } child = kai_tag_get_first_child_with_type(src, "technique_common"); if (child == NULL) { free(dest->id); free(dest->name); kai_release_float_array(dest->float_array); return -1; } child = kai_tag_get_first_child_with_type(child, "accessor"); if (child == NULL) { free(dest->id); free(dest->name); kai_release_float_array(dest->float_array); return -1; } result = kai_read_accessor(&(dest->accessor), child); if (result != 0) { free(dest->id); free(dest->name); kai_release_float_array(dest->float_array); return -1; } return 0; } void kai_release_source(struct ka_source_t s) { free(s.id); free(s.name); kai_release_float_array(s.float_array); kai_release_accessor(s.accessor); } int kai_read_input_unshared(struct ka_input_t *dest, struct kai_tag_t *src) { CHECK_TAG_TYPE("input"); char *semantic = kai_tag_attr_to_dup(src, "semantic"); if (semantic == NULL) { return -1; } char *source = kai_tag_attr_to_dup(src, "source"); if (source == NULL) { free(semantic); return -1; } dest->shared = false; dest->offset = 0; dest->semantic = semantic; dest->source = source; dest->set = 0; return 0; } int kai_read_input_shared(struct ka_input_t *dest, struct kai_tag_t *src) { int result = kai_read_input_unshared(dest, src); if (result != 0) { return result; } long offset = kai_tag_attr_to_long(src, "offset", -1); if (offset == -1) { return -1; } dest->shared = true; dest->offset = offset; long set = kai_tag_attr_to_long(src, "set", -1); if (set != -1) { dest->use_set = true; dest->set = set; } else { dest->use_set = false; } return 0; } void kai_release_input(struct ka_input_t i) { free(i.semantic); free(i.source); } int kai_read_vertices(struct ka_vertices_t *dest, struct kai_tag_t *src) { CHECK_TAG_TYPE("vertices"); char *id = kai_tag_attr_to_dup(src, "id"); if (id == NULL) { return -1; } dest->id = id; dest->name = kai_tag_attr_to_dup(src, "name"); /* count input children */ int count = 0; struct kai_tag_t *child; FOR_CHILD_OF_TYPE(src, child, "input") { count += 1; } dest->input_count = count; dest->input = malloc(count * sizeof(struct ka_input_t)); if (dest->input == NULL) { kai_release_vertices(*dest); return -1; } int i=0; FOR_CHILD_OF_TYPE(src, child, "input") { int result = kai_read_input_unshared(dest->input + i, child); if (result != 0) { dest->input_count = i; kai_release_vertices(*dest); return -1; } i += 1; } return 0; } void kai_release_vertices(struct ka_vertices_t v) { free(v.id); free(v.name); int i; for (i=0; iname = kai_tag_attr_to_dup(src, "name"); dest->count = count; dest->material = kai_tag_attr_to_dup(src, "material"); /* zero these out so that any error-related calls to kai_release_triangles * won't cause an invalid free */ dest->input_count = 0; dest->input = NULL; dest->p_count = 0; dest->p = NULL; /* load the child inputs into the structure */ int input_count = 0; struct kai_tag_t *child; FOR_CHILD_OF_TYPE(src, child, "input") { input_count += 1; } dest->input = kai_alloc(input_count * sizeof(struct ka_input_t), "triangles input array"); if (dest->input == NULL) { kai_release_triangles(*dest); return -1; } int i=0; FOR_CHILD_OF_TYPE(src, child, "input") { int result = kai_read_input_shared(dest->input + i, child); if (result != 0) { dest->input_count = i; kai_release_triangles(*dest); return -1; } i += 1; } dest->input_count = input_count; /* load the child p tag */ struct kai_tag_t *p = kai_tag_get_first_child_with_type(src, "p"); if (p != NULL) { dest->p_count = 3 * dest->count * dest->input_count; dest->p = kai_alloc(dest->p_count * sizeof(unsigned int), "triangles primitive array"); if (dest->p == NULL) { dest->p_count = 0; kai_release_triangles(*dest); return -1; } kai_text_to_uints(dest->p, p->content, dest->p_count); } return 0; } void kai_release_triangles(struct ka_triangles_t t) { free(t.name); free(t.material); int i; for (i=0; isource_count = 0; dest->source = NULL; dest->triangles_count = 0; dest->triangles = NULL; /* load vertices first bc if we don't kai_release_mesh will do bad things if we hit an error */ struct kai_tag_t *child; int result; child = kai_tag_get_first_child_with_type(src, "vertices"); if (child == NULL) { return -1; } result = kai_read_vertices(&(dest->vertices), child); if (result != 0) { return -1; } /* load sources */ unsigned int source_count = 0; FOR_CHILD_OF_TYPE(src, child, "source") { source_count += 1; } dest->source = kai_alloc(source_count * sizeof(struct ka_source_t), "mesh source array"); if (dest->source == NULL) { return -1; } int i = 0; FOR_CHILD_OF_TYPE(src, child, "source") { result = kai_read_source(dest->source + i, child); if (result != 0) { dest->source_count = i; kai_release_mesh(*dest); return -1; } i += 1; } dest->source_count = source_count; /* load triangles */ unsigned int triangles_count = 0; FOR_CHILD_OF_TYPE(src, child, "triangles") { triangles_count += 1; } dest->triangles = kai_alloc(triangles_count * sizeof(struct ka_triangles_t), "mesh triangles array"); if (dest->triangles == NULL) { kai_release_mesh(*dest); return -1; } i = 0; FOR_CHILD_OF_TYPE(src, child, "triangles") { result = kai_read_triangles(dest->triangles + i, child); if (result != 0) { dest->triangles_count = i; kai_release_mesh(*dest); return -1; } i += 1; } dest->triangles_count = triangles_count; return 0; } void kai_release_mesh(struct ka_mesh_t m) { int i; for (i=0; iid = kai_tag_attr_to_dup(src, "id"); dest->name = kai_tag_attr_to_dup(src, "name"); struct kai_tag_t *mesh = kai_tag_get_first_child_with_type(src, "mesh"); if (mesh == NULL) { free(dest->id); free(dest->name); return -1; } int result = kai_read_mesh(&(dest->mesh), mesh); if (result != 0) { free(dest->id); free(dest->name); return -1; } return 0; } void kai_release_geometry(struct ka_geometry_t g) { free(g.id); free(g.name); kai_release_mesh(g.mesh); }