Implement hidden face removal, although there are some artifacts I need to fix
authorNick Downing <nick@ndcode.org>
Tue, 19 Apr 2022 13:06:17 +0000 (23:06 +1000)
committerNick Downing <nick@ndcode.org>
Tue, 19 Apr 2022 13:06:17 +0000 (23:06 +1000)
render.c

index e79d0bf..21cab0e 100644 (file)
--- a/render.c
+++ b/render.c
@@ -6,7 +6,7 @@
 
 #define WINDOW_WIDTH 1024
 #define WINDOW_HEIGHT 768
-#define CAMERA_DISTANCE 100.f
+#define CAMERA_DISTANCE 2.5f
 
 #define EPSILON 1e-6f
 
@@ -175,6 +175,34 @@ struct array *gather(struct array *A, int n_cols, int *cols) {
   return B; 
 }
 
+struct array *vec_add(struct array *a, struct array *b) {
+  assert(a->n_dims == 2);
+  assert(a->dim[1] == sizeof(float));
+  assert(b->n_dims == 2);
+  assert(b->dim[1] == sizeof(float));
+  size_t I = a->dim[0];
+  assert(I == b->dim[0]);
+  struct array *c = array_new2(I, sizeof(float));
+  for (size_t i = 0; i < I; ++i)
+    *(float *)array_index1(c, i) =
+      *(float *)array_index1(a, i) + *(float *)array_index1(b, i);
+  return c;
+}
+
+struct array *vec_sub(struct array *a, struct array *b) {
+  assert(a->n_dims == 2);
+  assert(a->dim[1] == sizeof(float));
+  assert(b->n_dims == 2);
+  assert(b->dim[1] == sizeof(float));
+  size_t I = a->dim[0];
+  assert(I == b->dim[0]);
+  struct array *c = array_new2(I, sizeof(float));
+  for (size_t i = 0; i < I; ++i)
+    *(float *)array_index1(c, i) =
+      *(float *)array_index1(a, i) - *(float *)array_index1(b, i);
+  return c;
+}
+
 int main(void) {
   if (SDL_Init(SDL_INIT_VIDEO) < 0) {
     fprintf(stderr, "SDL_Init(): %s\n\n", SDL_GetError());
@@ -266,7 +294,7 @@ int main(void) {
 
   // model
 #if 1
-  obj *o = obj_create("grey_bliss_set.obj"); //"Chest.obj");
+  obj *o = obj_create("Chest.obj"); //"grey_bliss_set.obj");
   struct array *model_vertices;
   {
     int I = obj_num_vert(o);
@@ -499,6 +527,38 @@ int main(void) {
         for (int j = 0; j < J; ++j) {
           int v[3];
           obj_get_poly(o, i, j, v);
+
+#if 1
+          // check face visibility
+          struct array *pug = gather(pu, 3, v);
+          struct array *pug0 = array_dup1(pug, 0);
+          struct array *pug1 = array_dup1(pug, 1);
+          struct array *pug2 = array_dup1(pug, 2);
+          struct array *dir1 = vec_sub(pug1, pug0);
+          struct array *dir2 = vec_sub(pug2, pug0);
+          struct array *norm = vec_cross(dir1, dir2); // outward pointing
+          if (
+            /*vec_dot(norm, norm) < EPSILON ||*/ // degenerate face
+            vec_dot(norm, pug0) >= -EPSILON // origin is on underside of face
+          ) {
+            array_free(norm);
+            array_free(dir2);
+            array_free(dir1);
+            array_free(pug2);
+            array_free(pug1);
+            array_free(pug0);
+            array_free(pug);
+            continue;
+          }
+          array_free(norm);
+          array_free(dir2);
+          array_free(dir1);
+          array_free(pug2);
+          array_free(pug1);
+          array_free(pug0);
+          array_free(pug);
+#endif
+
           struct array *qug = gather(qu, 3, v);
           SDL_RenderDrawLine(
             renderer,