Some effort to fix a bug where pyramidal studs of chest are shown inside out
authorNick Downing <nick@ndcode.org>
Wed, 20 Apr 2022 09:38:59 +0000 (19:38 +1000)
committerNick Downing <nick@ndcode.org>
Wed, 20 Apr 2022 09:38:59 +0000 (19:38 +1000)
obj.c
render.c

diff --git a/obj.c b/obj.c
index 5fb48ff..0863d73 100644 (file)
--- a/obj.c
+++ b/obj.c
@@ -593,6 +593,7 @@ static void read_f(const char *line, struct obj *O, int si, int gi)
         for (i = 0; i < ic; ++i)
             if (_iv[i0 + 0]._ni < 0)
             {
+ assert(0);
                 obj_get_vert_n(O, _iv[i0 + i]._vi, t);
                 t[0] += n[0];
                 t[1] += n[1];
index 83a77e5..70c11d0 100644 (file)
--- a/render.c
+++ b/render.c
@@ -6,7 +6,7 @@
 
 #define WINDOW_WIDTH 1024
 #define WINDOW_HEIGHT 768
-#define CAMERA_DISTANCE 2.5f
+#define CAMERA_DISTANCE 5.f
 
 #define EPSILON 1e-6f
 
@@ -323,6 +323,75 @@ int main(void) {
       *(float *)array_index2(model_vertices_t, 1, i) = obj->vv[i].t[1];
     }
   }
+
+  // for some reason the vertex ordering is screwed up in Chest model,
+  // fix it by comparing our calculated normal with average vertex normal
+  {
+    int I = obj->sc;
+    for (int i = 0; i < I; ++i) {
+      int J = obj->sv[i].pc;
+      for (int j = 0; j < J; ++j) {
+        size_t v[3] = {
+          obj->sv[i].pv[j].vi[0],
+          obj->sv[i].pv[j].vi[1],
+          obj->sv[i].pv[j].vi[2]
+        };
+
+        struct array *v0 = array_new2_init(
+          3,
+          sizeof(float),
+          (float[3]){
+            obj->vv[v[0]].v[0],
+            obj->vv[v[0]].v[1],
+            obj->vv[v[0]].v[2]
+          }
+        );
+        struct array *v1 = array_new2_init(
+          3,
+          sizeof(float),
+          (float[3]){
+            obj->vv[v[1]].v[0],
+            obj->vv[v[1]].v[1],
+            obj->vv[v[1]].v[2]
+          }
+        );
+        struct array *v2 = array_new2_init(
+          3,
+          sizeof(float),
+          (float[3]){
+            obj->vv[v[2]].v[0],
+            obj->vv[v[2]].v[1],
+            obj->vv[v[2]].v[2]
+          }
+        );
+        struct array *dir1 = vec_sub(v1, v0);
+        struct array *dir2 = vec_sub(v2, v0);
+        struct array *norm = vec_cross(dir1, dir2); // outward pointing
+
+        struct array *ave_norm = array_new2_zero(3, sizeof(float));
+        for (int k = 0; k < 3; ++k) {
+          *(float *)array_index1(ave_norm, 0) += obj->vv[v[k]].n[0];
+          *(float *)array_index1(ave_norm, 1) += obj->vv[v[k]].n[1];
+          *(float *)array_index1(ave_norm, 2) += obj->vv[v[k]].n[2];
+        }
+
+        // if norms are opposite, reverse vertex order
+        if (vec_dot(norm, ave_norm) < 0.f) {
+ assert(false);
+          obj->sv[i].pv[j].vi[1] = (int)v[2];
+          obj->sv[i].pv[j].vi[2] = (int)v[1];
+        }
+
+        array_free(ave_norm);
+        array_free(norm);
+        array_free(dir2);
+        array_free(dir1);
+        array_free(v2);
+        array_free(v1);
+        array_free(v0);
+      }
+    }
+  }
 #else
   struct array *model_vertices = array_new3(4, 8, sizeof(float));
   for (int i = 0; i < 2; ++i)