/* draw everything */ void render(BITMAP *bmp) { char buf[80]; MATRIX_f roller, camera; int x, y, w, h; float xfront, yfront, zfront; float xup, yup, zup; /* clear the background */ clear(bmp); set_projection_viewport(0, 0, SCREEN_W, SCREEN_H); /* calculate the in-front vector */ xfront = sin(heading) * cos(pitch); yfront = sin(pitch); zfront = cos(heading) * cos(pitch); /* rotate the up vector around the in-front vector by the roll angle */ get_vector_rotation_matrix_f(&roller, xfront, yfront, zfront, roll*128.0/M_PI); apply_matrix_f(&roller, 0, -1, 0, &xup, &yup, &zup); /* build the camera matrix */ get_camera_matrix_f(&camera, xpos, ypos, zpos, /* camera position */ xfront, yfront, zfront, /* in-front vector */ xup, yup, zup, /* up vector */ fov, /* field of view */ aspect); /* aspect ratio */ /* draw the grid of squares */ for (x=0; x<GRID_SIZE; x++) for (y=0; y<GRID_SIZE; y++) draw_square(bmp, &camera, x * TILE_SIZE, y * TILE_SIZE); /* overlay some text */ set_clip_rect(bmp, 0, 0, bmp->w, bmp->h); sprintf(buf, "Field of view: %d (f/F changes)", fov); textout_ex(bmp, font, buf, 0, 16, 255, -1); sprintf(buf, "Aspect ratio: %.2f (a/A changes)", aspect); textout_ex(bmp, font, buf, 0, 24, 255, -1); sprintf(buf, "X position: %.2f (x/X changes)", xpos); textout_ex(bmp, font, buf, 0, 32, 255, -1); sprintf(buf, "Y position: %.2f (y/Y changes)", ypos); textout_ex(bmp, font, buf, 0, 40, 255, -1); sprintf(buf, "Z position: %.2f (z/Z changes)", zpos); textout_ex(bmp, font, buf, 0, 48, 255, -1); sprintf(buf, "Heading: %.2f deg (left/right changes)", DEG(heading)); textout_ex(bmp, font, buf, 0, 56, 255, -1); sprintf(buf, "Pitch: %.2f deg (pgup/pgdn changes)", DEG(pitch)); textout_ex(bmp, font, buf, 0, 64, 255, -1); sprintf(buf, "Roll: %.2f deg (r/R changes)", DEG(roll)); textout_ex(bmp, font, buf, 0, 72, 255, -1); sprintf(buf, "Front vector: %.2f, %.2f, %.2f", xfront, yfront, zfront); textout_ex(bmp, font, buf, 0, 80, 255, -1); sprintf(buf, "Up vector: %.2f, %.2f, %.2f", xup, yup, zup); textout_ex(bmp, font, buf, 0, 88, 255, -1); }
/* render a tile of the grid */ void draw_square(BITMAP *bmp, MATRIX_f *camera, int x, int z) { V3D_f v[4]; int c; /* set up four vertices with the world-space position of the tile */ v[0].x = x - GRID_SIZE/2; v[0].y = 0; v[0].z = z - GRID_SIZE/2; v[1].x = x - GRID_SIZE/2 + TILE_SIZE; v[1].y = 0; v[1].z = z - GRID_SIZE/2; v[2].x = x - GRID_SIZE/2 + TILE_SIZE; v[2].y = 0; v[2].z = z - GRID_SIZE/2 + TILE_SIZE; v[3].x = x - GRID_SIZE/2; v[3].y = 0; v[3].z = z - GRID_SIZE/2 + TILE_SIZE; /* for each vertex... */ for (c=0; c<4; c++) { /* apply the camera matrix, translating world space -> view space */ apply_matrix_f(camera, v[c].x, v[c].y, v[c].z, &v[c].x, &v[c].y, &v[c].z); /* reject anything too close to us or behind us. Really this ought * to do a proper 3d clip, but I have yet to write the code for that :-) */ if (v[c].z < 0.01) return; /* project view space -> screen space */ persp_project_f(v[c].x, v[c].y, v[c].z, &v[c].x, &v[c].y); } if (v[0].c = (((x + z) / TILE_SIZE) & 1)) { /* every second square */ v[0].c = 1; v[1].c = 43; v[2].c = 85; v[3].c = 127; } else { v[0].c = 127 + 1; v[1].c = 127 + 43; v[2].c = 127 + 85; v[3].c = 127 + 127; } /* render the square */ quad3d_f(bmp, POLYTYPE_GCOL, NULL, &v[0], &v[1], &v[2], &v[3]); }
/* outside of cylinder projection function */ static int project_cylinder(float *f, int *i, int c) { static MATRIX_f mtx; static int virgin = TRUE; if (virgin) { MATRIX_f m1, m2; get_z_rotate_matrix_f(&m1, -64); qtranslate_matrix_f(&m1, 0, 1.75, 0); get_scaling_matrix_f(&m2, 2.0, 1.0, 1.0); matrix_mul_f(&m1, &m2, &mtx); virgin = FALSE; } while (c > 0) { float ang = (f[0] - player_pos()) * M_PI * 2.0; float xsize = view_right - view_left; float ysize = view_bottom - view_top; float size = MIN(xsize, ysize) / 2.0; float x = cos(ang); float y = sin(ang); float z = 1.0 + (1.0 - f[1]) * 4.0; float xout, yout, zout; apply_matrix_f(&mtx, x, y, z, &xout, &yout, &zout); if (yout > 1.5) return FALSE; i[0] = xout/zout * size + (view_left + view_right) / 2.0; i[1] = (yout/zout * 2 - 1) * size + (view_top + view_bottom) / 2.0; f += 2; i += 2; c -= 2; } return TRUE; }
// UPDATE CAMERA MATERIX inline void update_camera_matrix(CAMERA *cam) { // INTERNAL VARIABLES static float cx, sx; static float cz, sz; static MATRIX_f temp; static VECTOR front, up; cx = cos(cam->dir.x * B2R); sx = sin(cam->dir.x * B2R); cz = cos(cam->dir.z * B2R); sz = sin(cam->dir.z * B2R); front.x = sz * cx; front.y = cz * cx; front.z = -sx; get_vector_rotation_matrix_f(&temp, front.x, front.y, front.z, cam->dir.y); apply_matrix_f(&temp, 0, 0, 1, &up.x, &up.y, &up.z); get_camera_matrix_f(&cam->matrix, 0, 0, 0, front.x, front.y, front.z, up.x, up.y, up.z, cam->fov, 1); }
int main(void) { BITMAP *textura, *back_buffer; int x, y, c; // para rellenar la textura int tecla; int nPol; int i; char angulo_x = 0, angulo_y = 0, angulo_z = 0; POLIGONO3D cara[6]; // un cubo PUNTO3D ver_t[4]; // v‚rtices transformados para un pol¡gono V3D_f ver_p[4]; // v‚rtices proyectados (2d) para un pol¡gono PUNTO3D cam_p; // posici¢n de la camara VECTOR cam_f; // vector frente de la camara VECTOR cam_a; // vector arriba de la camara MATRIX_f matriz; printf("\nEjemplo de c mara en un solo plano."); printf("\n\nControles:"); printf("\n Flechas: mover la camara."); printf("\n\n\nPresione una tecla para comenzar...\n"); getch(); // inicializar allegro y otras cosas allegro_init(); set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0); install_keyboard(); install_timer(); install_int(&cont_frames, 1000); LOCK_VARIABLE(nFrames); LOCK_VARIABLE(nFramesPorSegundo); LOCK_FUNCTION(cont_frames); back_buffer = create_bitmap(SCREEN_W, SCREEN_H); clear(back_buffer); // crear una textura textura = create_bitmap(TEX_W, TEX_H); clear(textura); c = 1; // color for(x = 0; x < TEX_W; x++) { for(y = 0; y < TEX_H; y++) { putpixel(textura, x, y, c); if(c++ > 64) c = 1; } } line(textura, 0, 0, TEX_W, TEX_H, 4); line(textura, TEX_W, 0, 0, TEX_H, 4); line(textura, 0, 0, 0, TEX_H, 4); line(textura, 0, 0, TEX_W, 0, 4); line(textura, 0, TEX_H - 1, TEX_W - 1, TEX_H - 1, 4); line(textura, TEX_W - 1, TEX_H - 1, TEX_W - 1, 0, 4); textprintf(textura, font, 1, 1, 13, "Textura"); // inicializar las coordenadas 3d del cubo cara[0].ver[0].x = -2; cara[0].ver[0].y = -2; cara[0].ver[0].z = -2; cara[0].ver[1].x = 2; cara[0].ver[1].y = -2; cara[0].ver[1].z = -2; cara[0].ver[2].x = 2; cara[0].ver[2].y = 2; cara[0].ver[2].z = -2; cara[0].ver[3].x = -2; cara[0].ver[3].y = 2; cara[0].ver[3].z = -2; cara[1].ver[0].x = 2; cara[1].ver[0].y = -2; cara[1].ver[0].z = 2; cara[1].ver[1].x = -2; cara[1].ver[1].y = -2; cara[1].ver[1].z = 2; cara[1].ver[2].x = -2; cara[1].ver[2].y = 2; cara[1].ver[2].z = 2; cara[1].ver[3].x = 2; cara[1].ver[3].y = 2; cara[1].ver[3].z = 2; cara[2].ver[0].x = -2; cara[2].ver[0].y = -2; cara[2].ver[0].z = 2; cara[2].ver[1].x = -2; cara[2].ver[1].y = -2; cara[2].ver[1].z = -2; cara[2].ver[2].x = -2; cara[2].ver[2].y = 2; cara[2].ver[2].z = -2; cara[2].ver[3].x = -2; cara[2].ver[3].y = 2; cara[2].ver[3].z = 2; cara[3].ver[0].x = 2; cara[3].ver[0].y = -2; cara[3].ver[0].z = -2; cara[3].ver[1].x = 2; cara[3].ver[1].y = -2; cara[3].ver[1].z = 2; cara[3].ver[2].x = 2; cara[3].ver[2].y = 2; cara[3].ver[2].z = 2; cara[3].ver[3].x = 2; cara[3].ver[3].y = 2; cara[3].ver[3].z = -2; cara[4].ver[0].x = -2; cara[4].ver[0].y = -2; cara[4].ver[0].z = 2; cara[4].ver[1].x = 2; cara[4].ver[1].y = -2; cara[4].ver[1].z = 2; cara[4].ver[2].x = 2; cara[4].ver[2].y = -2; cara[4].ver[2].z = -2; cara[4].ver[3].x = -2; cara[4].ver[3].y = -2; cara[4].ver[3].z = -2; cara[5].ver[0].x = -2; cara[5].ver[0].y = 2; cara[5].ver[0].z = -2; cara[5].ver[1].x = 2; cara[5].ver[1].y = 2; cara[5].ver[1].z = -2; cara[5].ver[2].x = 2; cara[5].ver[2].y = 2; cara[5].ver[2].z = 2; cara[5].ver[3].x = -2; cara[5].ver[3].y = 2; cara[5].ver[3].z = 2; // inicializar las coordenadas de la textura ver_p[0].u = 0; ver_p[0].v = 0; ver_p[1].u = TEX_W; ver_p[1].v = 0; ver_p[2].u = TEX_W; ver_p[2].v = TEX_H; ver_p[3].u = 0; ver_p[3].v = TEX_H; // inicializar c mara cam_p.x = 0; cam_p.y = 0; cam_p.z = -35; cam_f.x = 0; cam_f.y = 0; cam_f.z = 1; cam_a.x = 0; cam_a.y = -1; cam_a.z = 0; set_projection_viewport(0, 0, SCREEN_W, SCREEN_H); do { // teclado if(key[KEY_RIGHT]) { get_rotation_matrix_f(&matriz, 0, -1, 0); apply_matrix_f(&matriz, cam_f.x, cam_f.y, cam_f.z, &cam_f.x, &cam_f.y, &cam_f.z); } if(key[KEY_LEFT]) { get_rotation_matrix_f(&matriz, 0, 1, 0); apply_matrix_f(&matriz, cam_f.x, cam_f.y, cam_f.z, &cam_f.x, &cam_f.y, &cam_f.z); } if(key[KEY_UP]) { cam_p.x += cam_f.x; cam_p.y += cam_f.y; cam_p.z += cam_f.z; } if(key[KEY_DOWN]) { cam_p.x -= cam_f.x; cam_p.y -= cam_f.y; cam_p.z -= cam_f.z; } get_camera_matrix_f(&matriz, cam_p.x, cam_p.y, cam_p.z, cam_f.x, cam_f.y, cam_f.z, cam_a.x, cam_a.y, cam_a.z, 32, 1); for(nPol = 0; nPol < 6; nPol++) { // cada pol¡gono for(i = 0; i < 4; i++) { // cada v‚rtice del pol¡gono // transformaci¢n apply_matrix_f(&matriz, cara[nPol].ver[i].x, cara[nPol].ver[i].y, cara[nPol].ver[i].z, &ver_t[i].x, &ver_t[i].y, &ver_t[i].z); // proyecci¢n persp_project_f(ver_t[i].x, ver_t[i].y, ver_t[i].z, &ver_p[i].x, &ver_p[i].y); ver_p[i].z = ver_t[i].z; // requerido para renderizar la textura } // backface culling if(polygon_z_normal_f(&ver_p[0], &ver_p[1], &ver_p[2]) > 0) { quad3d_f(back_buffer, POLYTYPE_PTEX, textura, &ver_p[0], &ver_p[1], &ver_p[2], &ver_p[3]); } } textprintf(back_buffer, font, 0, 190, 2, "%d FPS", nFramesPorSegundo); blit(back_buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); nFrames++; clear(back_buffer); } while(!key[KEY_ESC]); allegro_exit(); return 0; }
int main(void) { BITMAP *textura, *back_buffer; int x, y, c; // para rellenar la textura int tecla; int nPol; int i; char angulo_x = 0, angulo_y = 0, angulo_z = 0; float trans_z = 12.1; POLIGONO3D cara[6]; // un cubo PUNTO3D ver_t[4]; // v‚rtices transformados para un pol¡gono V3D_f ver_p[4]; // v‚rtices proyectados (2d) para un pol¡gono MATRIX_f matriz; printf("\nEjemplo de: backface culling (eliminaci¢n de caras posteriores)"); printf("\n\nControles:"); printf("\n Q, W, flechas = rotar cubo."); printf("\n A, Z = z++, z--."); printf("\n\n\nPresione una tecla para comenzar...\n"); getch(); // inicializar allegro y otras cosas allegro_init(); set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0); install_keyboard(); install_timer(); install_int(&cont_frames, 1000); LOCK_VARIABLE(nFrames); LOCK_VARIABLE(nFramesPorSegundo); LOCK_FUNCTION(cont_frames); back_buffer = create_bitmap(SCREEN_W, SCREEN_H); clear(back_buffer); // crear una textura textura = create_bitmap(TEX_W, TEX_H); clear(textura); c = 1; // color for(x = 0; x < TEX_W; x++) { for(y = 0; y < TEX_H; y++) { putpixel(textura, x, y, c); if(c++ > 64) c = 1; } } line(textura, 0, 0, TEX_W, TEX_H, 4); line(textura, TEX_W, 0, 0, TEX_H, 4); line(textura, 0, 0, 0, TEX_H, 4); line(textura, 0, 0, TEX_W, 0, 4); line(textura, 0, TEX_H - 1, TEX_W - 1, TEX_H - 1, 4); line(textura, TEX_W - 1, TEX_H - 1, TEX_W - 1, 0, 4); textprintf(textura, font, 1, 1, 13, "Textura"); // inicializar las coordenadas 3d del cubo cara[0].ver[0].x = -2; cara[0].ver[0].y = -2; cara[0].ver[0].z = -2; cara[0].ver[1].x = 2; cara[0].ver[1].y = -2; cara[0].ver[1].z = -2; cara[0].ver[2].x = 2; cara[0].ver[2].y = 2; cara[0].ver[2].z = -2; cara[0].ver[3].x = -2; cara[0].ver[3].y = 2; cara[0].ver[3].z = -2; cara[1].ver[0].x = 2; cara[1].ver[0].y = -2; cara[1].ver[0].z = 2; cara[1].ver[1].x = -2; cara[1].ver[1].y = -2; cara[1].ver[1].z = 2; cara[1].ver[2].x = -2; cara[1].ver[2].y = 2; cara[1].ver[2].z = 2; cara[1].ver[3].x = 2; cara[1].ver[3].y = 2; cara[1].ver[3].z = 2; cara[2].ver[0].x = -2; cara[2].ver[0].y = -2; cara[2].ver[0].z = 2; cara[2].ver[1].x = -2; cara[2].ver[1].y = -2; cara[2].ver[1].z = -2; cara[2].ver[2].x = -2; cara[2].ver[2].y = 2; cara[2].ver[2].z = -2; cara[2].ver[3].x = -2; cara[2].ver[3].y = 2; cara[2].ver[3].z = 2; cara[3].ver[0].x = 2; cara[3].ver[0].y = -2; cara[3].ver[0].z = -2; cara[3].ver[1].x = 2; cara[3].ver[1].y = -2; cara[3].ver[1].z = 2; cara[3].ver[2].x = 2; cara[3].ver[2].y = 2; cara[3].ver[2].z = 2; cara[3].ver[3].x = 2; cara[3].ver[3].y = 2; cara[3].ver[3].z = -2; cara[4].ver[0].x = -2; cara[4].ver[0].y = -2; cara[4].ver[0].z = 2; cara[4].ver[1].x = 2; cara[4].ver[1].y = -2; cara[4].ver[1].z = 2; cara[4].ver[2].x = 2; cara[4].ver[2].y = -2; cara[4].ver[2].z = -2; cara[4].ver[3].x = -2; cara[4].ver[3].y = -2; cara[4].ver[3].z = -2; cara[5].ver[0].x = -2; cara[5].ver[0].y = 2; cara[5].ver[0].z = -2; cara[5].ver[1].x = 2; cara[5].ver[1].y = 2; cara[5].ver[1].z = -2; cara[5].ver[2].x = 2; cara[5].ver[2].y = 2; cara[5].ver[2].z = 2; cara[5].ver[3].x = -2; cara[5].ver[3].y = 2; cara[5].ver[3].z = 2; // inicializar las coordenadas de la textura ver_p[0].u = 0; ver_p[0].v = 0; ver_p[1].u = TEX_W; ver_p[1].v = 0; ver_p[2].u = TEX_W; ver_p[2].v = TEX_H; ver_p[3].u = 0; ver_p[3].v = TEX_H; set_projection_viewport(0, 0, SCREEN_W, SCREEN_H); do { // teclado if(key[KEY_UP]) { angulo_x++; } if(key[KEY_DOWN]) { angulo_x--; } if(key[KEY_RIGHT]) { angulo_y--; } if(key[KEY_LEFT]) { angulo_y++; } if(key[KEY_Q]) { angulo_z++; } if(key[KEY_W]) { angulo_z--; } if(key[KEY_A]) { trans_z+=0.2; } if(key[KEY_Z]) { trans_z-=0.2; } get_transformation_matrix_f(&matriz, 1, // escala angulo_x, // angulo rotaci¢n x angulo_y, // angulo rotaci¢n y angulo_z, // angulo rotaci¢n z 0, // translaci¢n x 0, // translaci¢n y trans_z); // translaci¢n z for(nPol = 0; nPol < 6; nPol++) { // cada pol¡gono for(i = 0; i < 4; i++) { // cada v‚rtice del pol¡gono // transformaci¢n apply_matrix_f(&matriz, cara[nPol].ver[i].x, cara[nPol].ver[i].y, cara[nPol].ver[i].z, &ver_t[i].x, &ver_t[i].y, &ver_t[i].z); // proyecci¢n persp_project_f(ver_t[i].x, ver_t[i].y, ver_t[i].z, &ver_p[i].x, &ver_p[i].y); ver_p[i].z = ver_t[i].z; // requerido para renderizar la textura } // si la normal al pol¡gono es positiva -> pintar if(polygon_z_normal_f(&ver_p[0], &ver_p[1], &ver_p[2]) > 0) { quad3d_f(back_buffer, POLYTYPE_PTEX, textura, &ver_p[0], &ver_p[1], &ver_p[2], &ver_p[3]); } } textprintf(back_buffer, font, 0, 190, 2, "%d FPS", nFramesPorSegundo); blit(back_buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); nFrames++; clear(back_buffer); } while(!key[KEY_ESC]); allegro_exit(); return 0; }
void view3d(MAPGEN &mapgen, float hflat, float lflat){ lc=0; MAP map(mapgen,hflat,lflat); BITMAP *buffer=create_bitmap(480,320); ZBUFFER *zbuf=create_zbuffer(buffer); set_zbuffer(zbuf); MATRIX_f roller,camera; // create_scene(4*(mapgen.size()*mapgen.size()), (mapgen.size()*mapgen.size())); set_projection_viewport(0, 0, buffer->w, buffer->h); float xfront, yfront, zfront; float xup, yup, zup; float heading=0,pitch=0,roll=0; int fov=32; float x=128,y=128,z=128; float xs=0,ys=0,zs=0; int fps=0,frames[101]; for(int i=0;i<101;i++) frames[i]=0; int mx,my,tc; //To get rid of that annoying roll I reset mickeys. get_mouse_mickeys(&mx,&my); while(!(mouse_b || key[KEY_ESC])){ tc=lc; lc=0; while(!mouse_b && tc){ tc--; fps-=frames[100]; for(int i=100;i>0;i--) frames[i]=frames[i-1]; frames[0]=0; fps+=frames[1]; /* if(key[KEY_Q]) y++; if(key[KEY_Z]) y--; if(key[KEY_W]){ x+=sin(heading); z+=cos(heading); } if(key[KEY_S]){ x-=sin(heading); z-=cos(heading); } if(key[KEY_A]){ x+=sin(heading+M_PI/2); z+=cos(heading+M_PI/2); } if(key[KEY_D]){ x-=sin(heading+M_PI/2); z-=cos(heading+M_PI/2); } */ if(key[KEY_Q]) ys++; if(key[KEY_Z]) ys--; if(key[KEY_W]){ xs+=sin(heading); zs+=cos(heading); } if(key[KEY_S]){ xs-=sin(heading); zs-=cos(heading); } if(key[KEY_A]){ xs+=sin(heading+M_PI/2); zs+=cos(heading+M_PI/2); roll+=.02; } if(key[KEY_D]){ xs-=sin(heading+M_PI/2); zs-=cos(heading+M_PI/2); roll-=.02; } xs*=.99; ys*=.9; zs*=.99; x+=xs; y+=ys; z+=zs; get_mouse_mickeys(&mx,&my); position_mouse(SCREEN_W/2,SCREEN_H/2); heading-=mx/100.; pitch-=my/100.; if(pitch>M_PI/3) pitch=M_PI/3; if(pitch<-M_PI/3) pitch=-M_PI/3; roll-=mx/100.; roll*=.95; /* if(x>=0 && z>=0 && x/tilesize<mapgen.size() && z/tilesize<mapgen.size()) y=200+mapgen.heightmap()[int(x/tilesize)][int(z/tilesize)]*tilesize; */ } /* calculate the in-front vector */ xfront = sin(heading) * cos(pitch); yfront = sin(pitch); zfront = cos(heading) * cos(pitch); /* rotate the up vector around the in-front vector by the roll angle */ get_vector_rotation_matrix_f(&roller, xfront, yfront, zfront, roll*128.0/M_PI); apply_matrix_f(&roller, 0, 1, 0, &xup, &yup, &zup); /* build the camera matrix */ get_camera_matrix_f(&camera, x, y, z, xfront, yfront, zfront, xup, yup, zup, fov, 1); polys_drawn=0; clear_bitmap(buffer); // clear_scene(buffer); clear_zbuffer(zbuf,0); map.render(buffer,&camera,int(x),int(y)); // render_scene(); textprintf_ex(buffer,font,8,8,-1,-1,"FPS: %i",fps); textprintf_ex(buffer,font,8,16,-1,-1,"Polygon count: %i",polys_drawn); blit(buffer, screen, 0, 0, 280, 8, buffer->w, buffer->h); frames[0]++; } destroy_bitmap(buffer); destroy_zbuffer(zbuf); // destroy_scene(); while(mouse_b || key[KEY_ESC]); clear_keybuf(); }