From ea530015e97e5280b61f3a8bc2d2ddee5c0e2dff Mon Sep 17 00:00:00 2001 From: sanine Date: Mon, 6 Feb 2023 11:59:28 -0600 Subject: implement kai_read_triangles --- include/kalmia.h | 13 ++++++ src/geometry/geometry.c | 104 ++++++++++++++++++++++++++++++++++++++----- src/geometry/geometry.h | 3 ++ src/geometry/geometry.test.c | 71 +++++++++++++++++++++++++++++ src/util/util.c | 20 +++++++++ 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" + ); + + 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( + "" + ); + + 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( + "" + " " + " " + "

" + " 0 0 1 3 2 1" + " 0 0 2 1 3 2" + "

" + "
" + ); + + 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