#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; \ } 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); int result; KAI_FILL_ARRAY_FROM_TAGS( result, dest->param, dest->param_count, struct ka_param_t, src, "param", kai_read_param, kai_release_param ); if (result != 0) { free(source); return -1; } 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"); int result; KAI_FILL_ARRAY_FROM_TAGS( result, dest->input, dest->input_count, struct ka_input_t, src, "input", kai_read_input_unshared, kai_release_input ); if (result != 0) { kai_release_vertices(*dest); return -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 result; KAI_FILL_ARRAY_FROM_TAGS( result, dest->input, dest->input_count, struct ka_input_t, src, "input", kai_read_input_shared, kai_release_input ); if (result != 0) { kai_release_triangles(*dest); return -1; } /* 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 */ KAI_FILL_ARRAY_FROM_TAGS( result, dest->source, dest->source_count, struct ka_source_t, src, "source", kai_read_source, kai_release_source ); if (result != 0) { kai_release_mesh(*dest); return -1; } /* load triangles */ KAI_FILL_ARRAY_FROM_TAGS( result, dest->triangles, dest->triangles_count, struct ka_triangles_t, src, "triangles", kai_read_triangles, kai_release_triangles ); if (result != 0) { kai_release_mesh(*dest); return -1; } 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); } int kai_read_library_geometries(struct ka_library_geometries_t *dest, struct kai_tag_t *src) { CHECK_TAG_TYPE("library_geometries"); dest->id = kai_tag_attr_to_dup(src, "id"); dest->name = kai_tag_attr_to_dup(src, "name"); int result; KAI_FILL_ARRAY_FROM_TAGS( result, dest->geometry, dest->geometry_count, struct ka_geometry_t, src, "geometry", kai_read_geometry, kai_release_geometry ); if (result != 0) { kai_release_library_geometries(*dest); return -1; } return 0; } void kai_release_library_geometries(struct ka_library_geometries_t l) { free(l.id); free(l.name); int i; for (i=0; i