/* 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); }
/* get_vector_rotation_matrix: * Constructs a 3d transformation matrix, which will rotate points around * the specified x,y,z vector by the specified angle (given in the Allegro * fixed point, 256 degrees to a circle format), in a clockwise direction. */ void get_vector_rotation_matrix(MATRIX *m, fixed x, fixed y, fixed z, fixed a) { MATRIX_f rotation; int i, j; ASSERT(m); get_vector_rotation_matrix_f(&rotation, fixtof(x), fixtof(y), fixtof(z), fixtof(a)); for (i=0; i<3; i++) for (j=0; j<3; j++) m->v[i][j] = ftofix(rotation.v[i][j]); m->t[0] = m->t[1] = m->t[2] = 0; }
// 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); }
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(); }