#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; for (child = src->children; child != NULL; child = child->next) { if (strcmp(child->type, "float_array") == 0) { kai_read_float_array(&(dest->float_array), child); } else if (strcmp(child->type, "technique_common") == 0) { kai_read_accessor(&(dest->accessor), child->children); } /* ignore others */ } 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; i