nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "mesh.h" nuclear@0: nuclear@0: #define XSZ 640 nuclear@0: #define YSZ 480 nuclear@0: nuclear@0: void display(unsigned int msec); nuclear@0: void process_vertex(Vertex *vres, const Vertex &vin); nuclear@0: void draw_mesh(const std::vector &varr); nuclear@0: void draw_triangle(const Vertex *v); nuclear@0: nuclear@0: unsigned int start_time; nuclear@0: Matrix4x4 mv_matrix, proj_matrix, norm_matrix; nuclear@0: Vector4 mat_diffuse; nuclear@0: Vector3 light_dir; nuclear@0: std::vector torus; nuclear@0: nuclear@0: int main(void) nuclear@0: { nuclear@0: GrHwConfiguration hwcfg; nuclear@0: nuclear@0: if(!grSstQueryBoards(&hwcfg)) { nuclear@0: fprintf(stderr, "No 3dfx graphics boards detected!\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: printf("Found %d 3dfx graphics boards!\n", hwcfg.num_sst); nuclear@0: nuclear@0: grGlideInit(); nuclear@0: if(!grSstQueryHardware(&hwcfg)) { nuclear@0: fprintf(stderr, "No 3dfx graphics hardware detected!\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: grSstSelect(0); nuclear@0: nuclear@0: if(!grSstWinOpen(0, GR_RESOLUTION_640x480, GR_REFRESH_60Hz, GR_COLORFORMAT_RGBA, nuclear@0: GR_ORIGIN_UPPER_LEFT, 2, 1)) { nuclear@0: fprintf(stderr, "Failed to initialize glide device\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: printf("Voodoo graphics initialized sucessfully!\n"); nuclear@0: nuclear@0: // setup projection matrix nuclear@0: proj_matrix.perspective(45.0f, 1.3333333f, 0.5, 250.0); nuclear@0: nuclear@0: // generate torus mesh nuclear@0: gen_torus(torus, 1.5, 0.5, 24, 12); nuclear@0: nuclear@0: // light nuclear@0: light_dir = normalize(Vector3(-0.6f, 1.0f, 2.0f)); nuclear@0: nuclear@0: // enable W-buffer (depth buffer) nuclear@0: grDepthBufferMode(GR_DEPTHBUFFER_WBUFFER); nuclear@0: grDepthMask(1); nuclear@0: grDepthBufferFunction(GR_CMP_LESS); nuclear@0: nuclear@0: // main loop nuclear@0: start_time = GetTickCount(); nuclear@0: unsigned int msec = 0; nuclear@0: while((msec = GetTickCount() - start_time) < 8000) { nuclear@0: display(msec); nuclear@0: } nuclear@0: nuclear@0: grGlideShutdown(); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: void display(unsigned int msec) nuclear@0: { nuclear@0: float t = (float)msec / 1000.0f; nuclear@0: nuclear@0: grBufferClear(0x103060ff, 255, GR_WDEPTHVALUE_FARTHEST); nuclear@0: nuclear@0: mv_matrix.set_identity(); nuclear@0: mv_matrix.translate(0, 0, -8); nuclear@0: mv_matrix.rotate(t * 100.0f, 1, 0, 0); nuclear@0: mv_matrix.rotate(t * 80.0f, 0, 0, 1); nuclear@0: nuclear@0: norm_matrix = mv_matrix; nuclear@0: norm_matrix[0][3] = norm_matrix[1][3] = norm_matrix[2][3] = 0.0f; nuclear@0: norm_matrix[3][0] = norm_matrix[3][1] = norm_matrix[3][2] = 0.0f; nuclear@0: norm_matrix[3][3] = 1.0f; nuclear@0: nuclear@0: mat_diffuse = Vector4(1.0f, 0.6f, 0.2f, 1.0f); nuclear@0: draw_mesh(torus); nuclear@0: nuclear@0: grBufferSwap(1); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: void process_vertex(Vertex *vres, const Vertex &vin) nuclear@0: { nuclear@0: // transform with the modelview matrix nuclear@0: vres->pos = transform(vin.pos, mv_matrix); nuclear@0: vres->normal = transform(vin.normal, norm_matrix); nuclear@0: nuclear@0: // calculate lighting nuclear@0: float ndotl = dot(vres->normal, light_dir); nuclear@0: if(ndotl < 0.0) ndotl = 0.0; nuclear@0: nuclear@0: Vector3 vdir(0, 0, 1); nuclear@0: Vector3 half_dir = normalize(vdir + light_dir); nuclear@0: float ndoth = dot(vres->normal, half_dir); nuclear@0: if(ndoth < 0.0) ndoth = 0.0; nuclear@0: float spec = pow(ndoth, 32.0); nuclear@0: nuclear@0: float red = mat_diffuse.x * ndotl + spec; nuclear@0: float green = mat_diffuse.y * ndotl + spec; nuclear@0: float blue = mat_diffuse.z * ndotl + spec; nuclear@0: nuclear@0: nuclear@0: vres->color.x = red > 1.0 ? 1.0 : red; nuclear@0: vres->color.y = green > 1.0 ? 1.0 : green; nuclear@0: vres->color.z = blue > 1.0 ? 1.0 : blue; nuclear@0: vres->color.w = mat_diffuse.w; nuclear@0: nuclear@0: nuclear@0: // transform with the projection matrix nuclear@0: vres->pos = transform(vres->pos, proj_matrix); nuclear@0: nuclear@0: // perspective division nuclear@0: vres->pos.x = vres->pos.x / vres->pos.w; nuclear@0: vres->pos.y = vres->pos.y / vres->pos.w; nuclear@0: vres->pos.z = vres->pos.z / vres->pos.w; nuclear@0: nuclear@0: // viewport transformation nuclear@0: vres->pos.x = (vres->pos.x * 0.5 + 0.5) * (float)XSZ; nuclear@0: vres->pos.y = (vres->pos.y * 0.5 + 0.5) * (float)YSZ; nuclear@0: } nuclear@0: nuclear@0: nuclear@0: void draw_mesh(const std::vector &varr) nuclear@0: { nuclear@0: static Vertex face_vert[3]; nuclear@0: size_t num = varr.size(); nuclear@0: nuclear@0: int face_vert_idx = 0; nuclear@0: nuclear@0: for(int i=0; i= 3) { nuclear@0: draw_triangle(face_vert); nuclear@0: face_vert_idx = 0; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void draw_triangle(const Vertex *v) nuclear@0: { nuclear@0: GrVertex face[3]; nuclear@0: nuclear@0: for(int i=0; i<3; i++) { nuclear@0: face[i].x = v[i].pos.x; nuclear@0: face[i].y = v[i].pos.y; nuclear@0: face[i].r = v[i].color.x * 255.0; nuclear@0: face[i].g = v[i].color.y * 255.0; nuclear@0: face[i].b = v[i].color.z * 255.0; nuclear@0: face[i].a = v[i].color.w * 255.0; nuclear@0: face[i].oow = 1.0f / v[i].pos.w; nuclear@0: } nuclear@0: nuclear@0: grDrawTriangle(face, face + 1, face + 2); nuclear@0: }