summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2023-02-06 11:59:28 -0600
committersanine <sanine.not@pm.me>2023-02-06 11:59:28 -0600
commitea530015e97e5280b61f3a8bc2d2ddee5c0e2dff (patch)
tree205c7d51a24927f45e21ef98a3213b120150649a
parent3d1afa579c9ce045c87e4b68a6d6068a389251a0 (diff)
implement kai_read_triangles
-rw-r--r--include/kalmia.h13
-rw-r--r--src/geometry/geometry.c104
-rw-r--r--src/geometry/geometry.h3
-rw-r--r--src/geometry/geometry.test.c71
-rw-r--r--src/util/util.c20
-rw-r--r--src/util/util.h2
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);