diff options
-rw-r--r-- | include/kalmia.h | 13 | ||||
-rw-r--r-- | src/geometry/geometry.c | 104 | ||||
-rw-r--r-- | src/geometry/geometry.h | 3 | ||||
-rw-r--r-- | src/geometry/geometry.test.c | 71 | ||||
-rw-r--r-- | src/util/util.c | 20 | ||||
-rw-r--r-- | src/util/util.h | 2 |
6 files changed, 202 insertions, 11 deletions
diff --git a/include/kalmia.h b/include/kalmia.h index 4dd5d1d..7e0ab2f 100644 --- a/include/kalmia.h +++ b/include/kalmia.h @@ -119,4 +119,17 @@ struct ka_vertices_t { }; +struct ka_triangles_t { + char *name; + unsigned int count; /* required */ + char *material; + + unsigned int input_count; + struct ka_input_t *input; + + unsigned int p_count; + unsigned int *p; +}; + + #endif diff --git a/src/geometry/geometry.c b/src/geometry/geometry.c index ea04fd3..78fbaea 100644 --- a/src/geometry/geometry.c +++ b/src/geometry/geometry.c @@ -12,6 +12,14 @@ 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) { @@ -219,8 +227,8 @@ int kai_read_vertices(struct ka_vertices_t *dest, struct kai_tag_t *src) /* count input children */ int count = 0; struct kai_tag_t *child; - for (child = src->children; child != NULL; child = child->next) { - if (strcmp(child->type, "input") == 0) { count += 1; } + FOR_CHILD_OF_TYPE(src, child, "input") { + count += 1; } dest->input_count = count; @@ -231,16 +239,14 @@ int kai_read_vertices(struct ka_vertices_t *dest, struct kai_tag_t *src) } int i=0; - for (child = src->children; child != NULL; child = child->next) { - if (strcmp(child->type, "input") == 0) { - 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; + 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; @@ -258,3 +264,79 @@ void kai_release_vertices(struct ka_vertices_t v) } +int kai_read_triangles(struct ka_triangles_t *dest, struct kai_tag_t *src) +{ + CHECK_TAG_TYPE("triangles"); + + long count = kai_tag_attr_to_long(src, "count", -1); + if (count == -1) { return -1; } + + dest->name = 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<t.input_count; i++) { + kai_release_input(t.input[i]); + } + free(t.input); + free(t.p); +} + + diff --git a/src/geometry/geometry.h b/src/geometry/geometry.h index a5ebab7..26fc16b 100644 --- a/src/geometry/geometry.h +++ b/src/geometry/geometry.h @@ -23,4 +23,7 @@ void kai_release_input(struct ka_input_t i); int kai_read_vertices(struct ka_vertices_t *dest, struct kai_tag_t *src); void kai_release_vertices(struct ka_vertices_t v); +int kai_read_triangles(struct ka_triangles_t *dest, struct kai_tag_t *src); +void kai_release_triangles(struct ka_triangles_t t); + #endif diff --git a/src/geometry/geometry.test.c b/src/geometry/geometry.test.c index 968060d..d918ffa 100644 --- a/src/geometry/geometry.test.c +++ b/src/geometry/geometry.test.c @@ -408,6 +408,77 @@ LILY_TEST("read vertices tag") #include LILY_PUSH_TEST() +LILY_TEST("fail to read non-triangles tag") +{ + struct kai_tag_t *t = kai_parse_string( + "<tag />" + ); + + struct ka_triangles_t triangles; + int result = kai_read_triangles(&triangles, t); + CHECK_EQ(result, -1, "%d"); + + kai_tag_destroy(t); +} +#include LILY_PUSH_TEST() + + +LILY_TEST("fail to read triangles tag with no specified count") +{ + struct kai_tag_t *t = kai_parse_string( + "<triangles />" + ); + + struct ka_triangles_t triangles; + int result = kai_read_triangles(&triangles, t); + CHECK_EQ(result, -1, "%d"); + kai_tag_destroy(t); +} +#include LILY_PUSH_TEST() + + +LILY_TEST("read triangles tag") +{ + struct kai_tag_t *t = kai_parse_string( + "<triangles count=\"2\" material=\"Bricks\">" + " <input semantic=\"VERTEX\" source=\"#verts\" offset=\"0\"/>" + " <input semantic=\"NORMAL\" source=\"#normal\" offset=\"1\"/>" + " <p>" + " 0 0 1 3 2 1" + " 0 0 2 1 3 2" + " </p>" + "</triangles>" + ); + + struct ka_triangles_t triangles; + int result = kai_read_triangles(&triangles, t); + kai_tag_destroy(t); + + REQUIRE_EQ(result, 0, "%d"); + CHECK_EQ(triangles.name, NULL, "%p"); + CHECK_EQ(triangles.count, 2, "%d"); + CHECK_EQS(triangles.material, "Bricks"); + CHECK_EQ(triangles.input_count, 2, "%d"); + CHECK_EQS(triangles.input[1].semantic, "NORMAL"); + CHECK_EQ(triangles.p_count, 12, "%d"); + CHECK_EQ(triangles.p[0], 0, "%d"); + CHECK_EQ(triangles.p[1], 0, "%d"); + CHECK_EQ(triangles.p[2], 1, "%d"); + CHECK_EQ(triangles.p[3], 3, "%d"); + CHECK_EQ(triangles.p[4], 2, "%d"); + CHECK_EQ(triangles.p[5], 1, "%d"); + + CHECK_EQ(triangles.p[6], 0, "%d"); + CHECK_EQ(triangles.p[7], 0, "%d"); + CHECK_EQ(triangles.p[8], 2, "%d"); + CHECK_EQ(triangles.p[9], 1, "%d"); + CHECK_EQ(triangles.p[10], 3, "%d"); + CHECK_EQ(triangles.p[11], 2, "%d"); + + kai_release_triangles(triangles); +} +#include LILY_PUSH_TEST() + #define LILY_FILE_END diff --git a/src/util/util.c b/src/util/util.c index 4f79870..c113377 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -64,6 +64,26 @@ size_t kai_text_to_longs(long *dest, const char *str, size_t count) } +size_t kai_text_to_uints(unsigned int *dest, const char *str, size_t count) +{ + char *nptr = (char*) str; + char *end; + + size_t result = count; + + int i; + for (i=0; i<count; i++) { + dest[i] = strtol(nptr, &end, 10); + if (nptr == end) { + result -= 1; + } + nptr = end; + } + + return result; +} + + void *kai_alloc(size_t size, const char *purpose) { void *buf = malloc(size); diff --git a/src/util/util.h b/src/util/util.h index d5fa636..67d3922 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -34,6 +34,8 @@ size_t kai_text_to_reals(ka_real_t *dest, const char *str, size_t count); size_t kai_text_to_longs(long *dest, const char *str, size_t count); +size_t kai_text_to_uints(unsigned int *dest, const char *str, size_t count); + void *kai_alloc(size_t size, const char *purpose); |