Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » First person camera using transformations

Credits go to Edgar Reynaldo for helping out!
This thread is locked; no one can reply to it. rss feed Print
First person camera using transformations
DontKnow3D
Member #16,883
July 2018

i have tried to implement a first person camera, but as you might guess: It don't work. everything works fine in the whole 3d department of my code, except for the camera. if you look forwards everything works, but if you look 90 degrees to the side instead of the camera looking up and down when you move the mouse it spins in a circle and if you look 180 degrees behind yourself the camera is inverted. how do i fix this? i have tried many different formulas but none of them work.

mouse processing:

#SelectExpand
1switch (ev.type) { 2 case ALLEGRO_EVENT_MOUSE_AXES: 3 p.m.x += ev.mouse.dx; 4 p.m.y += ev.mouse.dy; 5 p.m.ax = p.m.x / MOUSE_SPEED;//angle x: 1 rotation = 2*PI 6 p.m.ay = p.m.y / -MOUSE_SPEED;//angle y: goes from -PI/2 to PI/2 7 al_set_mouse_xy(display, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); 8 if (p.m.ay > PI / 2) { 9 p.m.ay = PI / 2; 10 p.m.y = ((PI / 2)*-MOUSE_SPEED); 11 } 12 if (p.m.ay < -PI / 2) { 13 p.m.ay = -PI / 2; 14 p.m.y = ((-PI / 2)*-MOUSE_SPEED); 15 } 16//------------------------------------------------ 17//----------calculate camera rotation------------- 18//------------------------------------------------ 19//-------------how do i do this?------------------ 20//------------------------------------------------ 21 p.m.cax = p.m.ay; 22 p.m.cay = p.m.ax; 23 p.m.caz = 0; 24 25 /*p.m.cax = cos(p.m.ax) * cos(p.m.ay)*PI; 26 p.m.cay = sin(p.m.ay)*PI; 27 p.m.caz = sin(p.m.ax) * cos(p.m.ay)*PI;*/ 28 break;

camera transformation code:

#SelectExpand
1 al_identity_transform(&tra); 2 al_translate_transform_3d(&tra, p.x, p.y, p.z); 3 al_rotate_transform_3d(&tra, 1, 0, 0, p.m.cax); 4 al_rotate_transform_3d(&tra, 0, 1, 0, p.m.cay); 5 al_rotate_transform_3d(&tra, 0, 0, 1, p.m.caz); 6 al_perspective_transform(&tra, -SCREEN_WIDTH / 2, -SCREEN_HEIGHT / 2, 1000, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 100000); 7 al_use_projection_transform(&tra); 8 9 al_flip_display();

whole code:

#SelectExpand
1#include<allegro5\allegro.h> 2#include<allegro5\allegro_font.h> 3#include<allegro5\allegro_ttf.h> 4#include<allegro5\allegro_color.h> 5#include<allegro5\allegro_primitives.h> 6#include<allegro5\allegro_image.h> 7#include<cmath> 8 9 10#define LOOP(var,max) for(var=0;var<max;++var) 11#define KD(keycode) al_key_down(&key,ALLEGRO_KEY_##keycode) 12 13#define SCREEN_WIDTH (100 * 16) 14#define SCREEN_HEIGHT (100 * 9) 15#define PI 3.141592653589793238462643 16 17#define MOVE_SPEED 30 18#define MOUSE_SPEED 500. //higher = lower speed 19 20typedef struct { 21 int x, y;//xy location of mouse 22 float ax, ay;//xy angle of mouse 23 float cax, cay, caz;//camera angle 24}mouse_t; 25 26class player_t { 27public: 28 mouse_t m = { 0 }; 29 float x = 0, y = 0, z = 0; 30}; 31 32void process_keyboard(player_t& p) { 33 ALLEGRO_KEYBOARD_STATE key; 34 al_get_keyboard_state(&key); 35 36 //move the player 37 if (KD(A)) { 38 p.x += MOVE_SPEED * cos(p.m.ax); 39 p.z += MOVE_SPEED * sin(p.m.ax); 40 } 41 if (KD(D)) { 42 p.x -= MOVE_SPEED * cos(p.m.ax); 43 p.z -= MOVE_SPEED * sin(p.m.ax); 44 } 45 if (KD(W)) { 46 p.z += MOVE_SPEED * cos(-p.m.ax); 47 p.x += MOVE_SPEED * sin(-p.m.ax); 48 } 49 if (KD(S)) { 50 p.z -= MOVE_SPEED * cos(-p.m.ax); 51 p.x -= MOVE_SPEED * sin(-p.m.ax); 52 } 53 if (KD(SPACE)) 54 p.y += MOVE_SPEED; 55 if (KD(CAPSLOCK) || KD(LSHIFT)) 56 p.y -= MOVE_SPEED; 57 if (KD(ESCAPE)) 58 exit(0); 59} 60 61void init() { 62 al_init(); 63 al_init_image_addon(); 64 al_init_primitives_addon(); 65 al_init_ttf_addon(); 66 al_init_font_addon(); 67 al_install_keyboard(); 68 al_install_mouse(); 69 al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 16, ALLEGRO_SUGGEST); 70} 71 72int main() { 73 init(); 74 int i, j; 75 auto display = al_create_display(SCREEN_WIDTH, SCREEN_HEIGHT); 76 auto q = al_create_event_queue(); 77 auto fps = al_create_timer(1 / 60.); 78 ALLEGRO_EVENT ev; 79 ALLEGRO_TRANSFORM tra; 80 player_t p; 81 auto font = al_load_ttf_font("fonts/DeansgateCondensed-Bold.ttf", 64, 0);//just a generic font for testing 82 al_register_event_source(q, al_get_timer_event_source(fps)); 83 al_register_event_source(q, al_get_mouse_event_source()); 84 al_register_event_source(q, al_get_display_event_source(display)); 85 al_start_timer(fps); 86 al_set_render_state(ALLEGRO_DEPTH_TEST, 1); 87 auto image = al_load_bitmap("images/ground.jpeg");//random picture of some ground 88 /*p.m.x = SCREEN_WIDTH / 2; 89 p.m.y = SCREEN_HEIGHT / 2;*/ 90 al_set_mouse_xy(display, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); 91 ALLEGRO_VERTEX cube[] = { 92 {-1000,-1000,-1000, 0,0,al_map_rgb_f(1,1,1)}, 93 {-1000,-1000, 1000, 0,0,al_map_rgb_f(1,1,1)}, 94 {-1000, 1000, 1000, 0,0,al_map_rgb_f(1,1,1)}, 95 96 {1000, 1000,-1000, 0,0,al_map_rgb_f(0,1,1)}, 97 {-1000,-1000,-1000, 0,0,al_map_rgb_f(0,1,1)}, 98 {-1000, 1000,-1000, 0,0,al_map_rgb_f(0,1,1)}, 99 100 {1000,-1000, 1000, 0,0,al_map_rgb_f(1,0,1)}, 101 {-1000,-1000,-1000, 0,0,al_map_rgb_f(1,0,1)}, 102 {1000,-1000,-1000, 0,0,al_map_rgb_f(1,0,1)}, 103 104 {1000, 1000,-1000, 0,0,al_map_rgb_f(1,1,0)}, 105 {1000,-1000,-1000, 0,0,al_map_rgb_f(1,1,0)}, 106 {-1000,-1000,-1000, 0,0,al_map_rgb_f(1,1,0)}, 107 108 {-1000,-1000,-1000, 0,0,al_map_rgb_f(0,0,1)}, 109 {-1000, 1000, 1000, 0,0,al_map_rgb_f(0,0,1)}, 110 {-1000, 1000,-1000, 0,0,al_map_rgb_f(0,0,1)}, 111 112 {1000,-1000, 1000, 0,0,al_map_rgb_f(0,1,0)}, 113 {-1000,-1000, 1000, 0,0,al_map_rgb_f(0,1,0)}, 114 {-1000,-1000,-1000, 0,0,al_map_rgb_f(0,1,0)}, 115 116 {-1000, 1000, 1000, 0,0,al_map_rgb_f(1,0,0)}, 117 {-1000,-1000, 1000, 0,0,al_map_rgb_f(1,0,0)}, 118 {1000,-1000, 1000, 0,0,al_map_rgb_f(1,0,0)}, 119 120 {1000, 1000, 1000, 0,0,al_map_rgb_f(0,0,0)}, 121 {1000,-1000,-1000, 0,0,al_map_rgb_f(0,0,0)}, 122 {1000, 1000,-1000, 0,0,al_map_rgb_f(0,0,0)}, 123 124 {1000,-1000,-1000, 0,0,al_map_rgb_f(1,1,1)}, 125 {1000, 1000, 1000, 0,0,al_map_rgb_f(1,1,1)}, 126 {1000,-1000, 1000, 0,0,al_map_rgb_f(1,1,1)}, 127 128 {1000, 1000, 1000, 0,0,al_map_rgb_f(0,1,1)}, 129 {1000, 1000,-1000, 0,0,al_map_rgb_f(0,1,1)}, 130 {-1000, 1000,-1000, 0,0,al_map_rgb_f(0,1,1)}, 131 132 {1000, 1000, 1000, 0,0,al_map_rgb_f(1,0,1)}, 133 {-1000, 1000,-1000, 0,0,al_map_rgb_f(1,0,1)}, 134 {-1000, 1000, 1000, 0,0,al_map_rgb_f(1,0,1)}, 135 136 {1000, 1000, 1000, 0,0,al_map_rgb_f(1,1,0)}, 137 {-1000, 1000, 1000, 0,0,al_map_rgb_f(1,1,0)}, 138 {1000,-1000, 1000, 0,0,al_map_rgb_f(1,1,0)}, 139 }; 140 ALLEGRO_VERTEX ground[] = { 141 { 1000,0,1000,al_get_bitmap_width(image),al_get_bitmap_height(image),al_map_rgb_f(1,1,1) }, 142 { -1000,0,1000,0,al_get_bitmap_height(image),al_map_rgb_f(1,1,1) }, 143 { -1000,0,-1000,0,0,al_map_rgb_f(1,1,1) }, 144 145 { 1000,0,1000,al_get_bitmap_width(image),al_get_bitmap_height(image),al_map_rgb_f(1,1,1) }, 146 { 1000,0,-1000,al_get_bitmap_width(image),0,al_map_rgb_f(1,1,1) }, 147 { -1000,0,-1000,0,0,al_map_rgb_f(1,1,1) }, 148 }; 149 while (1) { 150 al_wait_for_event(q, &ev); 151 switch (ev.type) { 152 case ALLEGRO_EVENT_MOUSE_AXES: 153 p.m.x += ev.mouse.dx; 154 p.m.y += ev.mouse.dy; 155 p.m.ax = p.m.x / MOUSE_SPEED;//angle x: 1 rotation = 2*PI 156 p.m.ay = p.m.y / -MOUSE_SPEED;//angle y: goes from -PI/2 to PI/2 157 al_set_mouse_xy(display, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); 158 if (p.m.ay > PI / 2) { 159 p.m.ay = PI / 2; 160 p.m.y = ((PI / 2)*-MOUSE_SPEED); 161 } 162 if (p.m.ay < -PI / 2) { 163 p.m.ay = -PI / 2; 164 p.m.y = ((-PI / 2)*-MOUSE_SPEED); 165 } 166//------------------------------------------------ 167//----------calculate camera rotation------------- 168//------------------------------------------------ 169//-------------how do i do this?------------------ 170//------------------------------------------------ 171 p.m.cax = p.m.ay; 172 p.m.cay = p.m.ax; 173 p.m.caz = 0; //ev.mouse.z / 100.; 174 175 /*p.m.cax = cos(p.m.ax) * cos(p.m.ay)*PI; 176 p.m.cay = sin(p.m.ay)*PI; 177 p.m.caz = sin(p.m.ax) * cos(p.m.ay)*PI;*/ 178 179 break; 180 case ALLEGRO_EVENT_TIMER: 181 //key input 182 process_keyboard(p); 183 184 //clear display 185 al_clear_to_color(al_map_rgb_f(0.5, 0.5, 0.5)); 186 al_clear_depth_buffer(10000); 187 188 //draw the normalized angles (floating text around you) (2*PI = 1) 189 al_identity_transform(&tra); 190 al_translate_transform_3d(&tra, -p.x, -p.y, -p.z - 2000); 191 al_use_transform(&tra); 192 LOOP(j, 12) { 193 al_rotate_transform_3d(&tra, 0, 1, 0, PI / 6); 194 LOOP(i, 12) { 195 al_rotate_transform_3d(&tra, 1, 0, 0, PI / 6); 196 al_use_transform(&tra); 197 al_draw_multiline_textf(font, al_map_rgb_f(0, 1, 0.5), 50, 50, 0, 0, 0, "ax_%.4f ay_%.4f cax_%.4f cay_%.4f caz_%.4f", p.m.ax / PI / 2, p.m.ay / PI / 2, p.m.cax / PI / 2, p.m.cay / PI / 2, p.m.caz / PI / 2); 198 } 199 } 200 //draw the ground 201 al_identity_transform(&tra); 202 al_scale_transform_3d(&tra, 10, 0, 10); 203 al_translate_transform_3d(&tra, 0, 6000, 0); 204 al_use_transform(&tra); 205 al_draw_prim(ground, NULL, image, 0, 6, ALLEGRO_PRIM_TRIANGLE_LIST); 206 207 //draw the 5 floating cubes 208 al_identity_transform(&tra); 209 al_translate_transform_3d(&tra, 0, 0, -4000); 210 al_use_transform(&tra); 211 al_draw_prim(cube, NULL, NULL, 0, sizeof(cube) / sizeof(cube[0]), ALLEGRO_PRIM_TRIANGLE_LIST); 212 al_translate_transform_3d(&tra, 0, 5000, 0); 213 al_use_transform(&tra); 214 al_draw_prim(cube, NULL, NULL, 0, sizeof(cube) / sizeof(cube[0]), ALLEGRO_PRIM_TRIANGLE_LIST); 215 al_translate_transform_3d(&tra, 5000, -5000, 5000); 216 al_use_transform(&tra); 217 al_draw_prim(cube, NULL, NULL, 0, sizeof(cube) / sizeof(cube[0]), ALLEGRO_PRIM_TRIANGLE_LIST); 218 al_translate_transform_3d(&tra, -5000, -5000, 5000); 219 al_use_transform(&tra); 220 al_draw_prim(cube, NULL, NULL, 0, sizeof(cube) / sizeof(cube[0]), ALLEGRO_PRIM_TRIANGLE_LIST); 221 al_translate_transform_3d(&tra, -5000, 5000, 5000); 222 al_use_transform(&tra); 223 al_draw_prim(cube, NULL, NULL, 0, sizeof(cube) / sizeof(cube[0]), ALLEGRO_PRIM_TRIANGLE_LIST); 224 225 //do the camera transforms 226 al_identity_transform(&tra); 227 al_translate_transform_3d(&tra, p.x, p.y, p.z); 228 al_rotate_transform_3d(&tra, 1, 0, 0, p.m.cax); 229 al_rotate_transform_3d(&tra, 0, 1, 0, p.m.cay); 230 al_rotate_transform_3d(&tra, 0, 0, 1, p.m.caz); 231 al_perspective_transform(&tra, -SCREEN_WIDTH / 2, -SCREEN_HEIGHT / 2, 1000, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 100000); 232 al_use_projection_transform(&tra); 233 234 al_flip_display(); 235 break; 236 } 237 } 238}

(and i also cant manage to figure out how to draw a 'hud' or just simple things right on the display after the transformations)

Edgar Reynaldo
Member #8,592
May 2007
avatar

You have to understand there are two matrices involved. The projection matrix, and the view matrix. You're mixing the two, and you still aren't even trying to do what I showed you in the other thread.

https://www.allegro.cc/forums/thread/617512/1038669#target

Also, you are mixing 2D and 3D drawing without resetting your projection matrices properly.

You should read over the manual entry for transformations.

https://liballeg.org/a5docs/trunk/transformations.html

Specifically, look at the docs for al_build_camera_transform , al_orthographic_transform, and al_perspective_transform.

For 2D you use the orthographic transform for the projection matrix. For 3D you use the perspective transform for the projection matrix. For 2D view matrix, all you need is the identity. For 3D, you need to apply a camera transform to the view matrix.

First, see https://liballeg.org/a5docs/trunk/transformations.html#al_use_projection_transform for the difference between 2D and 3D projection matrices.

Second, see https://liballeg.org/a5docs/trunk/transformations.html#al_build_camera_transform for how to set up your camera. As I told you before, you need to use a forward, right, and up vector to define the orientation of the camera. You also need a position for the camera. Then the lookAt parameter becomes camera.position + forward_vector.

EDIT
You can also 'cheat' and calculate the look vector yourself using a little trig.

The compass heading becomes the rotation around the y-axis on the xz plane.

      +Y   -Z
       |   /
       |  /
       | /
-X_____|/____ +X
      /|
     / |
    /  |
  +Z  -Y

And then the pitch become the rotation around the right vector.

double heading = atan2(-dz,dx);
double pitch = acos((dist(xz)/dist(xyz));

I think that's right but I'm tired.

DontKnow3D
Member #16,883
July 2018

OK so; I have majorly rewritten how everything about my perspective/transformation/drawing works. I now first generate 1 mesh, where everything 3d is stored and then draw all of that at once to the screen. 2d operations work now too and i think i have gotten a much better grasp on how the perspective transformations work. i now also use the camera transformation. the only thing that doesent work now is: the camera. I think I'm using the camera correctly, but apparently I'm not. and if you see anything I'm doing wrong now with the transformations, pleas tell me.

#SelectExpand
1#include<allegro5\allegro.h> 2#include<allegro5\allegro_font.h> 3#include<allegro5\allegro_ttf.h> 4#include<allegro5\allegro_color.h> 5#include<allegro5\allegro_primitives.h> 6#include<allegro5\allegro_image.h> 7#include<cmath> 8#include<cstdlib> 9#include<iostream> 10 11#define FOV (PI/2) //90 degrees (vertical not horizontal) 12 13#define KD(keycode) al_key_down(&key,ALLEGRO_KEY_##keycode) 14#define LOOP(var,max) for(var=0;var<max;++var) 15 16#define PI 3.141592653589793238462643 17#define SCREEN_WIDTH (100 * 16) 18#define SCREEN_HEIGHT (100 * 9) 19 20#define MOVE_SPEED .03 21#define MOUSE_SPEED 500. //higher = lower speed 22 23typedef struct { 24 int x, y;//xy location of mouse 25 float ax, ay;//xy angle of mouse 26 float cax, cay, caz;//camera "location" 27}mouse_t; 28 29class player_t { 30public: 31 mouse_t m = { 0 }; 32 float x = 0, y = 0, z = 3; 33}; 34 35class mesh_t { 36public: 37 size_t size_of_mesh = 0; 38 ALLEGRO_VERTEX * mesh = NULL; 39 void add_to_mesh_transform(ALLEGRO_VERTEX*add, size_t amount_of_vertices, ALLEGRO_TRANSFORM*transform) { 40 ALLEGRO_VERTEX*v = (ALLEGRO_VERTEX*)malloc(sizeof(ALLEGRO_VERTEX)*amount_of_vertices); 41 if (v == NULL) { 42 std::cout << "EVERYTHING HAS FAILED! ABORT NOW OR COMPUTER WILL EXPLODE!" << std::endl; 43 al_rest(5); 44 exit(1); 45 } 46 memcpy(v, add, amount_of_vertices * sizeof(ALLEGRO_VERTEX)); 47 int i; 48 LOOP(i, amount_of_vertices) { 49 al_transform_coordinates_3d(transform, &v[i].x, &v[i].y, &v[i].z); 50 } 51 mesh = (ALLEGRO_VERTEX*)realloc(mesh, sizeof(ALLEGRO_VERTEX)*(amount_of_vertices + size_of_mesh)); 52 memcpy(&(mesh[size_of_mesh]), v, amount_of_vertices * sizeof(ALLEGRO_VERTEX)); 53 size_of_mesh += amount_of_vertices; 54 free(v); 55 } 56 void reset_mesh() { 57 free(mesh); 58 mesh = NULL; 59 size_of_mesh = 0; 60 } 61 //size_t size() { 62 // return size_of_mesh; 63 //} 64}; 65 66void process_keyboard(player_t& p) { 67 ALLEGRO_KEYBOARD_STATE key; 68 al_get_keyboard_state(&key); 69 70 //move the player 71 if (KD(A)) { 72 p.x += MOVE_SPEED * cos(p.m.ax); 73 p.z += MOVE_SPEED * sin(p.m.ax); 74 } 75 if (KD(D)) { 76 p.x -= MOVE_SPEED * cos(p.m.ax); 77 p.z -= MOVE_SPEED * sin(p.m.ax); 78 } 79 if (KD(W)) { 80 p.z += MOVE_SPEED * cos(-p.m.ax); 81 p.x += MOVE_SPEED * sin(-p.m.ax); 82 } 83 if (KD(S)) { 84 p.z -= MOVE_SPEED * cos(-p.m.ax); 85 p.x -= MOVE_SPEED * sin(-p.m.ax); 86 } 87 if (KD(SPACE)) 88 p.y += MOVE_SPEED; 89 if (KD(CAPSLOCK) || KD(LSHIFT)) 90 p.y -= MOVE_SPEED; 91 if (KD(ESCAPE)) 92 exit(0); 93} 94 95void init() { 96 al_init(); 97 al_init_image_addon(); 98 al_init_primitives_addon(); 99 al_init_ttf_addon(); 100 al_init_font_addon(); 101 al_install_keyboard(); 102 al_install_mouse(); 103 al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 16, ALLEGRO_SUGGEST); 104} 105 106void setup_3d_projection() { 107 ALLEGRO_TRANSFORM projection; 108 al_identity_transform(&projection); 109 al_translate_transform_3d(&projection, 0, 0, 0); 110 double fov = tan(FOV / 2); 111 al_perspective_transform(&projection, -1 * SCREEN_WIDTH / SCREEN_HEIGHT * fov, fov, 1, fov*SCREEN_WIDTH / SCREEN_HEIGHT, -fov, 1000); 112 al_use_projection_transform(&projection); 113} 114 115int main() { 116 init(); 117 int i, j; 118 auto display = al_create_display(SCREEN_WIDTH, SCREEN_HEIGHT); 119 auto q = al_create_event_queue(); 120 auto fps = al_create_timer(1 / 60.); 121 mesh_t mesh; 122 ALLEGRO_EVENT ev; 123 ALLEGRO_TRANSFORM tra, cam, curprotra; 124 player_t p; 125 auto font = al_load_ttf_font("fonts/DeansgateCondensed-Bold.ttf", 16, 0);//just a generic font for testing 126 al_register_event_source(q, al_get_timer_event_source(fps)); 127 al_register_event_source(q, al_get_mouse_event_source()); 128 al_register_event_source(q, al_get_display_event_source(display)); 129 al_start_timer(fps); 130 auto image = al_load_bitmap("images/ground.jpeg");//random picture of some ground 131 al_set_mouse_xy(display, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); 132 ALLEGRO_VERTEX cube[] = { 133 {-1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(1,1,1)}, 134 {-1.0f,-1.0f, 1.0f, 0,0,al_map_rgb_f(1,1,1)}, 135 {-1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(1,1,1)}, 136 137 {1.0f, 1.0f,-1.0f, 0,0,al_map_rgb_f(0,1,1)}, 138 {-1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(0,1,1)}, 139 {-1.0f, 1.0f,-1.0f, 0,0,al_map_rgb_f(0,1,1)}, 140 141 {1.0f,-1.0f, 1.0f, 0,0,al_map_rgb_f(1,0,1)}, 142 {-1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(1,0,1)}, 143 {1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(1,0,1)}, 144 145 {1.0f, 1.0f,-1.0f, 0,0,al_map_rgb_f(1,1,0)}, 146 {1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(1,1,0)}, 147 {-1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(1,1,0)}, 148 149 {-1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(0,0,1)}, 150 {-1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(0,0,1)}, 151 {-1.0f, 1.0f,-1.0f, 0,0,al_map_rgb_f(0,0,1)}, 152 153 {1.0f,-1.0f, 1.0f, 0,0,al_map_rgb_f(0,1,0)}, 154 {-1.0f,-1.0f, 1.0f, 0,0,al_map_rgb_f(0,1,0)}, 155 {-1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(0,1,0)}, 156 157 {-1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(1,0,0)}, 158 {-1.0f,-1.0f, 1.0f, 0,0,al_map_rgb_f(1,0,0)}, 159 {1.0f,-1.0f, 1.0f, 0,0,al_map_rgb_f(1,0,0)}, 160 161 {1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(0,0,0)}, 162 {1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(0,0,0)}, 163 {1.0f, 1.0f,-1.0f, 0,0,al_map_rgb_f(0,0,0)}, 164 165 {1.0f,-1.0f,-1.0f, 0,0,al_map_rgb_f(1,1,1)}, 166 {1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(1,1,1)}, 167 {1.0f,-1.0f, 1.0f, 0,0,al_map_rgb_f(1,1,1)}, 168 169 {1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(0,1,1)}, 170 {1.0f, 1.0f,-1.0f, 0,0,al_map_rgb_f(0,1,1)}, 171 {-1.0f, 1.0f,-1.0f, 0,0,al_map_rgb_f(0,1,1)}, 172 173 {1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(1,0,1)}, 174 {-1.0f, 1.0f,-1.0f, 0,0,al_map_rgb_f(1,0,1)}, 175 {-1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(1,0,1)}, 176 177 {1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(1,1,0)}, 178 {-1.0f, 1.0f, 1.0f, 0,0,al_map_rgb_f(1,1,0)}, 179 {1.0f,-1.0f, 1.0f, 0,0,al_map_rgb_f(1,1,0)}, 180 }; 181 ALLEGRO_VERTEX ground[] = { 182 { 1.0f,0,1.0f,al_get_bitmap_width(image),al_get_bitmap_height(image),al_map_rgb_f(0,1,1) }, 183 { -1.0f,0,1.0f,0,al_get_bitmap_height(image),al_map_rgb_f(1,0,1) }, 184 { -1.0f,0,-1.0f,0,0,al_map_rgb_f(1,1,0) }, 185 186 { 1.0f,0,1.0f,al_get_bitmap_width(image),al_get_bitmap_height(image),al_map_rgb_f(0,0,1) }, 187 { 1.0f,0,-1.0f,al_get_bitmap_width(image),0,al_map_rgb_f(1,0,0) }, 188 { -1.0f,0,-1.0f,0,0,al_map_rgb_f(0,1,0) }, 189 }; 190 191 //initialize the mesh 192 al_identity_transform(&tra); 193 mesh.add_to_mesh_transform(cube, std::size(cube), &tra); 194 al_translate_transform_3d(&tra, 3, 0, 0); 195 mesh.add_to_mesh_transform(cube, std::size(cube), &tra); 196 al_identity_transform(&tra); 197 al_scale_transform_3d(&tra, 10, 1, 10); 198 al_translate_transform_3d(&tra, 0, 6, 0); 199 mesh.add_to_mesh_transform(ground, std::size(ground), &tra); 200 201 while (1) { 202 al_wait_for_event(q, &ev); 203 switch (ev.type) { 204 case ALLEGRO_EVENT_MOUSE_AXES: 205 p.m.x += ev.mouse.dx; 206 p.m.y += ev.mouse.dy; 207 p.m.ax = p.m.x / MOUSE_SPEED;//angle x: 1 rotation = 2*PI 208 p.m.ay = p.m.y / -MOUSE_SPEED;//angle y: goes from -PI/2 to PI/2 209 al_set_mouse_xy(display, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2); 210 /*if (p.m.ay > PI / 2) { 211 p.m.ay = PI / 2; 212 p.m.y = ((PI / 2)*-MOUSE_SPEED); 213 } 214 if (p.m.ay < -PI / 2) { 215 p.m.ay = -PI / 2; 216 p.m.y = ((-PI / 2)*-MOUSE_SPEED); 217 }*/ 218 219//--------------camera calculations---------------- 220 p.m.cax = cos(p.m.ay)*sin(p.m.ax); 221 p.m.cay = cos(p.m.ay)*cos(p.m.ax); 222 p.m.caz = sin(p.m.ay); 223 224 std::cout << "cax=" << p.m.cax << '\t' << "cay=" << p.m.cay << '\t' << "caz=" << p.m.caz << '\t' << std::endl; 225 break; 226 case ALLEGRO_EVENT_TIMER: 227 //key input 228 process_keyboard(p); 229 230 curprotra = *al_get_current_projection_transform(); 231 setup_3d_projection(); 232 233 al_clear_to_color(al_map_rgb_f(0.5, 0.5, 0.5)); 234 al_set_render_state(ALLEGRO_DEPTH_TEST, 1); 235 al_clear_depth_buffer(1); 236 237// ----------------camera transform--------------- 238 al_build_camera_transform(&cam, p.x, p.y, p.z, 239 p.x + p.m.cax, p.y + p.m.cay, p.z + p.m.caz, 240 0, 1, 0); 241 al_use_transform(&cam); 242 //draw 3d things 243 al_draw_prim(mesh.mesh, NULL, NULL, 0, mesh.size_of_mesh, ALLEGRO_PRIM_TRIANGLE_LIST); 244 245 //restore projection 246 al_identity_transform(&tra); 247 al_use_transform(&tra); 248 al_use_projection_transform(&curprotra); 249 al_set_render_state(ALLEGRO_DEPTH_TEST, 0); 250 251 //draw 2d things 252 al_draw_multiline_textf(font, al_map_rgb_f(0.8, 0.1, 0.2), 50, 50, 0, 0, 0, "normalized(2PI=1) ax_%.4f ay_%.4f not_normalized cax_%.4f cay_%.4f caz_%.4f", p.m.ax / PI / 2, p.m.ay / PI / 2, p.m.cax, p.m.cay, p.m.caz); 253 al_flip_display(); 254 break; 255 } 256 } 257}

Edgar Reynaldo
Member #8,592
May 2007
avatar

I think your formula is just a bit off. You have z and y reversed. It should be :

   fw.x = cos(pitch)*cos(yaw);
   fw.z = cos(pitch)*-sin(yaw);
   fw.y = sin(pitch);

{"name":"611674","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/4\/94b598fff0562e56a5c7bf072c62b984.png","w":800,"h":600,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/4\/94b598fff0562e56a5c7bf072c62b984"}611674

Or you can build your forward vector using transforms :

#SelectExpand
1 void RebuildTransform() { 2 fw = Vec(0,0,-1); 3 rt = Vec(1,0,0); 4 up = Vec(0,1,0); 5 /// Apply yaw 6 ALLEGRO_TRANSFORM t1; 7 al_identity_transform(&t1); 8 al_rotate_transform(&t1 , up.x , up.y , up.z , yaw); 9 al_transform_coordinates(&t1 , &rt.x , &rt.y , &rt.z); 10 al_transform_coordinates(&t1 , &fw.x , &fw.y , &fw.z); 11 12 /// Apply pitch 13 al_identity_transform(&t1); 14 al_rotate_transform(&t1 , rt.x , rt.y , rt.z , yaw); 15 al_transform_coordinates(&t1 , &up.x , &up.y , &up.z); 16 al_transform_coordinates(&t1 , &fw.x , &fw.y , &fw.z); 17 18 /// Apply roll 19 //... 20 Vec look = pos + fw; 21 al_build_camera_transform(&t , pos.x , pos.y , pos.z , look.x , look.y , look.z , up.x , up.y , up.z); 22 }

DontKnow3D
Member #16,883
July 2018

ok thank you! you've been a great help in all of this. there is just 1 more thing id like to figure out. in my code right after i use the camera transformation, i draw the whole map mesh. now i would like to also draw other things and use transformations on them. but if i trie to do that, it doesent really work. the things i draw after the new transformations move with the camera rotation. how would i fix that?

#SelectExpand
1// ----------------camera transform--------------- 2 al_build_camera_transform(&cam, p.x, p.y, p.z, 3 p.x + p.m.cax, p.y + p.m.cay, p.z + p.m.caz, 4 0, 1, 0); 5 al_use_transform(&cam); 6 7 //draw 3d things 8 al_draw_prim(mesh.mesh, NULL, NULL, 0, mesh.size_of_mesh, ALLEGRO_PRIM_TRIANGLE_LIST);//drawing the mesh as before 9 10//now draw an extra cube 3 units below 0,0,0 11 ALLEGRO_TRANSFORM copy_of_cam, transform; 12 al_identity_transform(&transform); 13 al_copy_transform(&copy_of_cam, &cam); 14 15 al_translate_transform_3d(&transform,0, -3, 0); 16 al_compose_transform(&copy_of_cam, &transform); 17 al_use_transform(&copy_of_cam); 18 19 al_draw_prim(cube, NULL, NULL, 0, std::size(cube), ALLEGRO_PRIM_TRIANGLE_LIST); 20 21 //restore projection 22 //...

Edgar Reynaldo
Member #8,592
May 2007
avatar

You need to transform your objects first, before applying the camera transform.

Do the same thing, but swap the order.

DontKnow3D
Member #16,883
July 2018

thank you! you've been a great help!
if anybody wants the full source code:https://github.com/dontknow3d/fps-camera-using-allegro-5

Go to: