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++) {
}
/* 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) {
/* 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
};
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;
g3d_enable(G3D_CULL_FACE);
g3d_enable(G3D_LIGHTING);
g3d_enable(G3D_LIGHT0);
+
+ g3d_polygon_mode(shading);
}
static void update(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;
+ }
}
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);
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;