#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
+#include <assert.h>
#include "demo.h"
#include "3dgfx.h"
#include "screen.h"
#include "cfgopt.h"
#include "polyfill.h"
#include "imago2.h"
+#include "util.h"
#include "gfxutil.h"
#include "mesh.h"
-#include "bsptree.h"
+#include "noise.h"
static int init(void);
static void destroy(void);
static float cam_theta = -29, cam_phi = 35;
static float cam_dist = 10;
-static int use_bsp = 1;
-
static const char *car_fname[2] = {"data/ldiablo.obj", 0};
static const char *cartex_fname[2] = {"data/ldiablo.png", 0};
static struct g3d_mesh mesh_car[2];
static struct pimage tex_car[2];
-static struct bsptree bsp_car[2];
+
+#define BGCOL_SIZE 128
+#define BGOFFS_SIZE 1024
+static uint16_t bgcol[BGCOL_SIZE];
+static uint16_t bgcol_mir[BGCOL_SIZE];
+static int bgoffs[BGOFFS_SIZE];
+static const int colzen[] = {98, 64, 192};
+static const int colhor[] = {128, 80, 64};
+static const int colmnt[] = {16, 9, 24};
+static uint16_t mountcol, mountcol_mir;
+
+static int shading = G3D_TEX_GOURAUD;
+static int do_clip = 1;
+
struct screen *rtxonoff_screen(void)
{
static int init(void)
{
int i;
+ int col[3];
+
+ mountcol = PACK_RGB16(colmnt[0], colmnt[1], colmnt[2]);
+ mountcol_mir = PACK_RGB16(colmnt[0] / 2, colmnt[1] / 2, colmnt[2] / 2);
+
+ for(i=0; i<BGCOL_SIZE; i++) {
+ int32_t t = (i << 8) / BGCOL_SIZE;
+ col[0] = colhor[0] + ((colzen[0] - colhor[0]) * t >> 8);
+ col[1] = colhor[1] + ((colzen[1] - colhor[1]) * t >> 8);
+ col[2] = colhor[2] + ((colzen[2] - colhor[2]) * t >> 8);
+ bgcol[i] = PACK_RGB16(col[0], col[1], col[2]);
+ bgcol_mir[i] = PACK_RGB16(col[0] / 2, col[1] / 2, col[2] / 2);
+ }
+
+ for(i=0; i<BGOFFS_SIZE; i++) {
+ float x = 8.0f * (float)i / (float)BGOFFS_SIZE;
+
+ bgoffs[i] = pfbm1(x, 8.0f, 5) * 32 + 16;
+ }
for(i=0; i<sizeof car_fname / sizeof car_fname[0]; i++) {
if(cartex_fname[i]) {
if(load_mesh(&mesh_car[i], car_fname[i]) == -1) {
return -1;
}
-
- init_bsp(&bsp_car[i]);
- if(bsp_add_mesh(&bsp_car[i], &mesh_car[i]) == -1) {
- fprintf(stderr, "failed to construct BSP tree %d\n", i);
- return -1;
- }
- bsp_build(&bsp_car[i]);
}
}
return 0;
for(i=0; i<2; i++) {
free(mesh_car[i].varr);
free(mesh_car[i].iarr);
- destroy_bsp(&bsp_car[i]);
}
}
+#define VFOV 60
static void start(long trans_time)
{
g3d_matrix_mode(G3D_PROJECTION);
g3d_load_identity();
- g3d_perspective(60.0, 1.3333333, 0.5, 100.0);
+ g3d_perspective(VFOV, 1.3333333, 0.5, 100.0);
g3d_enable(G3D_CULL_FACE);
g3d_enable(G3D_LIGHTING);
static void update(void)
{
mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist);
+
+ cam_theta = fmod(cam_theta, 360.0f);
+ if(cam_theta < 0) cam_theta += 360.0f;
+
+ if(cam_phi < 0) cam_phi = 0;
}
-static void draw(void)
+static void backdrop(void)
{
- int i;
- static float vdir[3];
- float t = (float)time_msec / 16.0f;
+ static const int colzen[] = {98, 64, 192};
+ static const int colhor[] = {128, 80, 64};
+ int i, j, hory, start[3], end[3], col[3];
+ uint16_t *fbptr, pcol;
+ int cidx, offs = -10;
+ int startidx;
+
+ startidx = cround64(cam_theta * (float)BGOFFS_SIZE) / 360;
+
+ hory = (fb_height - 2 * fb_height * cround64(cam_phi) / VFOV) / 2;
+ if(hory > fb_height) hory = fb_height;
+
+ if(hory > 0) {
+ fbptr = fb_pixels + (hory - 1) * fb_width;
+ cidx = offs;
+ i = 0;
+ while(fbptr >= fb_pixels) {
+ pcol = bgcol[cidx < 0 ? 0 : (cidx >= BGCOL_SIZE ? BGCOL_SIZE - 1 : cidx)];
+ for(j=0; j<fb_width; j++) {
+ if(cidx < bgoffs[(startidx + j) & (BGOFFS_SIZE - 1)]) {
+ fbptr[j] = mountcol;
+ } else {
+ fbptr[j] = pcol;
+ }
+ }
+ fbptr -= fb_width;
+ cidx++;
+ }
+ cidx = offs;
+ } else {
+ cidx = offs - hory;
+ hory = 0;
+ }
+ fbptr = fb_pixels + hory * fb_width;
+ for(i=hory; i<fb_height; i++) {
+ pcol = bgcol_mir[cidx < 0 ? 0 : (cidx >= BGCOL_SIZE ? BGCOL_SIZE - 1 : cidx)];
+ for(j=0; j<fb_width; j++) {
+ if(cidx < bgoffs[(startidx + j) & (BGOFFS_SIZE - 1)]) {
+ *fbptr++ = mountcol_mir;
+ } else {
+ *fbptr++ = pcol;
+ }
+ }
+ cidx++;
+ }
+}
+
+static void draw(void)
+{
update();
- memset(fb_pixels, 0, fb_width * fb_height * 2);
+ g3d_framebuffer_addr(fb_pixels);
+
+ backdrop();
g3d_matrix_mode(G3D_MODELVIEW);
g3d_load_identity();
g3d_rotate(cam_phi, 1, 0, 0);
g3d_rotate(cam_theta, 0, 1, 0);
- if(use_bsp) {
- const float *mat = g3d_get_matrix(G3D_MODELVIEW, 0);
- /* transform (0, 0, -1) with transpose(mat3x3) */
- vdir[0] = -mat[2];
- vdir[1] = -mat[6];
- vdir[2] = -mat[10];
- }
+ g3d_polygon_mode(shading);
+ g3d_set_texture(tex_car[0].width, tex_car[0].height, tex_car[0].pixels);
+ zsort_mesh(&mesh_car[0]);
- g3d_polygon_mode(G3D_TEX_GOURAUD);
+ 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();
- 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, 1, 1, 1);
+ draw_mesh(&mesh_car[0]);
- if(use_bsp) {
- draw_bsp(&bsp_car[i], vdir[0], vdir[1], vdir[2]);
- } else {
- zsort_mesh(&mesh_car[i]);
- draw_mesh(&mesh_car[i]);
- }
- }
- }
+ draw_mouse_pointer(fb_pixels);
swap_buffers(fb_pixels);
}
static void keypress(int key)
{
+ static int lighting = 1;
+ static int clipping = 1;
+
switch(key) {
- case 'b':
- use_bsp = !use_bsp;
- printf("drawing with %s\n", use_bsp ? "BSP tree" : "z-sorting");
+ 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;
}
}