reflection
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 26 Aug 2018 12:18:44 +0000 (15:18 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sun, 26 Aug 2018 12:18:44 +0000 (15:18 +0300)
src/3dgfx.c
src/3dgfx.h
src/parts/rtxonoff.c
src/polytmpl.h

index 044ab66..64fd604 100644 (file)
@@ -82,6 +82,7 @@ int g3d_init(void)
                fprintf(stderr, "failed to allocate G3D context\n");
                return -1;
        }
+       st->opt = G3D_CLIP_FRUSTUM;
        st->fill_mode = POLYFILL_FLAT;
 
        for(i=0; i<G3D_NUM_MATRICES; i++) {
@@ -438,17 +439,19 @@ void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size,
                }
 
                /* clipping */
-               for(i=0; i<6; i++) {
-                       memcpy(tmpv, v, vnum * sizeof *v);
-
-                       if(clip_frustum(v, &vnum, tmpv, vnum, i) < 0) {
-                               /* polygon completely outside of view volume. discard */
-                               vnum = 0;
-                               break;
+               if(st->opt & G3D_CLIP_FRUSTUM) {
+                       for(i=0; i<6; i++) {
+                               memcpy(tmpv, v, vnum * sizeof *v);
+
+                               if(clip_frustum(v, &vnum, tmpv, vnum, i) < 0) {
+                                       /* polygon completely outside of view volume. discard */
+                                       vnum = 0;
+                                       break;
+                               }
                        }
-               }
 
-               if(!vnum) continue;
+                       if(!vnum) continue;
+               }
 
                for(i=0; i<vnum; i++) {
                        if(v[i].w != 0.0f) {
index 2a82284..07a3aea 100644 (file)
@@ -19,16 +19,21 @@ enum {
 
 /* g3d_enable/g3d_disable bits */
 enum {
-       G3D_CULL_FACE   = 0x0001,
-       G3D_DEPTH_TEST  = 0x0002,       /* XXX not implemented */
-       G3D_LIGHTING    = 0x0004,
-       G3D_LIGHT0              = 0x0008,
-       G3D_LIGHT1              = 0x0010,
-       G3D_LIGHT2              = 0x0020,
-       G3D_LIGHT3              = 0x0040,
-       G3D_TEXTURE             = 0x0080,
-       G3D_BLEND               = 0x0100,
-       G3D_TEXTURE_GEN = 0x0200,
+       G3D_CULL_FACE   = 0x000001,
+       G3D_DEPTH_TEST  = 0x000002,     /* XXX not implemented */
+       G3D_LIGHTING    = 0x000004,
+       G3D_LIGHT0              = 0x000008,
+       G3D_LIGHT1              = 0x000010,
+       G3D_LIGHT2              = 0x000020,
+       G3D_LIGHT3              = 0x000040,
+       G3D_TEXTURE             = 0x000080,
+       G3D_BLEND               = 0x000100,
+       G3D_TEXTURE_GEN = 0x000200,
+       G3D_CLIP_FRUSTUM = 0x000800,/* when disabled, don't clip against the frustum */
+       G3D_CLIP_PLANE0 = 0x001000,     /* user-defined 3D clipping planes XXX not impl. */
+       G3D_CLIP_PLANE1 = 0x002000,
+       G3D_CLIP_PLANE2 = 0x004000,
+       G3D_CLIP_PLANE3 = 0x008000,
 
        G3D_ALL = 0x7fffffff
 };
index 14edf1c..bab4d98 100644 (file)
@@ -33,6 +33,10 @@ static const char *cartex_fname[2] = {"data/ldiablo.png", 0};
 static struct g3d_mesh mesh_car[2];
 static struct pimage tex_car[2];
 
+static int shading = G3D_TEX_GOURAUD;
+static int do_clip = 1;
+
+
 struct screen *rtxonoff_screen(void)
 {
        return &scr;
@@ -80,6 +84,8 @@ static void start(long trans_time)
        g3d_enable(G3D_CULL_FACE);
        g3d_enable(G3D_LIGHTING);
        g3d_enable(G3D_LIGHT0);
+
+       g3d_polygon_mode(shading);
 }
 
 static void update(void)
@@ -103,20 +109,50 @@ static void draw(void)
        g3d_rotate(cam_phi, 1, 0, 0);
        g3d_rotate(cam_theta, 0, 1, 0);
 
-       g3d_polygon_mode(G3D_TEX_GOURAUD);
+       g3d_set_texture(tex_car[0].width, tex_car[0].height, tex_car[0].pixels);
+       zsort_mesh(&mesh_car[0]);
 
-       for(i=0; i<sizeof mesh_car / sizeof mesh_car[0]; i++) {
-               if(mesh_car[i].varr) {
-                       g3d_set_texture(tex_car[i].width, tex_car[i].height, tex_car[i].pixels);
+       g3d_light_color(0, 0.3, 0.3, 0.3);
+       g3d_push_matrix();
+       g3d_scale(1, -1, 1);
+       g3d_front_face(G3D_CW);
+       draw_mesh(&mesh_car[0]);
+       g3d_front_face(G3D_CCW);
+       g3d_pop_matrix();
 
-                       zsort_mesh(&mesh_car[i]);
-                       draw_mesh(&mesh_car[i]);
-               }
-       }
+       g3d_light_color(0, 1, 1, 1);
+       draw_mesh(&mesh_car[0]);
 
        swap_buffers(fb_pixels);
 }
 
 static void keypress(int key)
 {
+       static int lighting = 1;
+       static int clipping = 1;
+
+       switch(key) {
+       case ' ':
+               shading = (shading + 1) % 5;
+               g3d_polygon_mode(shading);
+               break;
+
+       case 'l':
+               lighting = !lighting;
+               if(lighting) {
+                       g3d_enable(G3D_LIGHTING);
+               } else {
+                       g3d_disable(G3D_LIGHTING);
+               }
+               break;
+
+       case 'c':
+               clipping = !clipping;
+               if(clipping) {
+                       g3d_enable(G3D_CLIP_FRUSTUM);
+               } else {
+                       g3d_disable(G3D_CLIP_FRUSTUM);
+               }
+               break;
+       }
 }
index 12df420..d61ac8e 100644 (file)
@@ -93,6 +93,12 @@ void POLYFILL(struct pvertex *pv, int nverts)
                if(pv[i].y > pv[botidx].y) botidx = i;
        }
 
+       int winding = 0;
+       for(i=0; i<nverts; i++) {
+               int next = NEXTIDX(i);
+               winding += (pv[next].x - pv[i].x) * (pv[next].y + pv[i].y);
+       }
+
        /* +1 to avoid crashing due to off-by-one rounding errors in the rasterization */
        left = alloca((pfill_fb.height + 1) * sizeof *left);
        right = alloca((pfill_fb.height + 1) * sizeof *right);
@@ -133,9 +139,16 @@ void POLYFILL(struct pvertex *pv, int nverts)
                                if(idx < sltop) sltop = idx;
                        /*}*/
                } else {
-                       struct pvertex *edge = y0 > y1 ? left : right;
-                       uint32_t res = SCANEDGE(pv + i, pv + next, edge);
-                       uint32_t tmp = (res >> 16) & 0xffff;
+                       struct pvertex *edge;
+                       uint32_t res, tmp;
+
+                       if(winding < 0) {
+                               edge = y0 > y1 ? left : right;
+                       } else {
+                               edge = y0 > y1 ? right : left;
+                       }
+                       res = SCANEDGE(pv + i, pv + next, edge);
+                       tmp = (res >> 16) & 0xffff;
                        if(tmp > slbot) slbot = tmp;
                        if((tmp = res & 0xffff) < sltop) {
                                sltop = tmp;