|
Setting up projection and camera matrices correctly for bitmaps in 3D |
bitrex
Member #16,587
November 2016
|
New user here, I've been really enjoying my time experimenting with Allegro 5. I'm trying to accomplish the following using 3D projection matrices but I'm not sure how to proceed. Here's the setup: I have some bitmaps stored in a class along with 3D position information that I'd like to project into a 3D space. Then I'd like to create a camera transform which allows me to move around these projected bitmaps within the 3D space. Remember the game "Wing Commander"? Something like that. I understand that since the objects are bitmaps they'll always have the same "face" projected towards me, sort of like how objects in "Wolfenstein 3D" were as you moved around a level. For this application, that's OK. I'm just having trouble figuring out how to set up the appropriate projection matrices and camera transform to render the bitmaps. The thread here: https://www.allegro.cc/forums/thread/615276 gives an example where first a projection matrix is set up, and then a a camera transform is applied, but I'm not sure if this technique also applies to rendering bitmaps instead of 3D verticies. If there's another thread which covers this topic, a reference would be appreciated. |
Edgar Reynaldo
Major Reynaldo
May 2007
|
The view matrix and the projection matrix are separate, but they are used in combination in the renderer. The view matrix is your camera matrix, that defines your view point and orientation on the world. The projection matrix defines the way the view is rendered, either through perspective projection, or through orthographic projection. Here is a simple tutorial to display a texture on the screen using view and projection matrices in OpenGL. Get allegro ready to draw to the backbuffer : /// NOTE : This changes the view and projection matrices al_set_target_bitmap(al_get_backbuffer(display)); Setup a camera on the world at (0,0,1500) looking at (0,0,0) with the up vector (0,1,0) : glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0,0,1500 , 0,0,0 , 0,1,0); Now setup our perspective. We can use glFrustum, gluPerspective, or glOrtho to setup a perspective or orthographic projection respectively. Setup a perspective projection with a field of view equivalent to half our screen size at a distance of 500 along the negative z-axis. The left and right and top and bottom parameters of glFrustum define the size of the near clipping plane (the top of the frustum). We are setting up our perspective so that the screen will be full size at a distance of 1000 from the camera which is at 500. Drawing 3D textures is mostly the same as drawing 3D vertices. The only difference is that you attach a texture coordinate to a vertex by using glBindTexture and glTexCoord after creating a bitmap and getting its opengl texture id from allegro. Load a texture. ALLEGRO_BITMAP* bmp = al_load_bitmap("texture.png"); GLuint texture_id = al_get_opengl_texture(bmp); Draw a simple texture to fill our virtual screen. glEnable(GL_TEXTURE_2D); glFrontFace(GL_CW);// Define winding order as clockwise glBindTexture(GL_TEXTURE_2D , texture_id); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(1.0 , 0.0);glVertex3f(SCREEN_W/2 , SCREEN_H/2 , 500);// upper right vertex glTexCoord2f(1.0 , 1.0);glVertex3f(SCREEN_W/2 , -SCREEN_H/2 , 500);// lower right vertex glTexCoord2f(0.0 , 1.0);glVertex3f(-SCREEN_W/2 , -SCREEN_H/2 , 500);// lower left vertex glTexCoord2f(0.0 , 0.0);glVertex3f(-SCREEN_W/2 , SCREEN_H/2 , 500);// upper left vertex glEnd(); And tell allegro to display everything : This is untested, but it should work, or at least give you an idea what you need to do to render a 3D texture. EDIT You can also use allegro's transforms to build a camera transform or a perspective transform and then use them as well. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Kev Callahan
Member #6,022
July 2005
|
This (my) recent thread may be of interest as well .. either that or it'll confuse things |
bitrex
Member #16,587
November 2016
|
Thanks guys. The approach I been working with was attempting to use the built-in Allegro transforms such as al_perspective_transform and al_build_camera_transform to accomplish something similar, using the ex_camera.c example code as a guide. I don't completely understand that example, it seems to use a lot of auxiliary static functions to compute dot products etc. that complicates things. I'm not familiar with those gl* functions yet, but it seems more straightforward than what I was attempting - maybe I should go with that method? |
Edgar Reynaldo
Major Reynaldo
May 2007
|
ex_camera uses cross products to generate vectors at right angles to a plane. It's what allows them to roll the camera from any orientation. Right now, just focus on getting a camera setup, and then try moving it and rotating it around a central point. Worry about things like the up vector later. You can use OpenGL directly, or Allegro's transforms. Allegro's transforms are probably a bit easier to use and understand as long as you're aware that you need both a view (camera) and a projection matrix set up. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
bitrex
Member #16,587
November 2016
|
Okay, great. If it's not too much to ask, could you provide a code proof-of-concept of how that method would be applied to the problem? |
Edgar Reynaldo
Major Reynaldo
May 2007
|
Sure, I'll explain how to achieve the same thing with Allegro instead of OpenGL. Setup a camera on the world at (0,0,1500) looking at (0,0,0) with the up vector (0,1,0) : (note that al_build_camera_transform is exactly equivalent to gluLookAt). ALLEGRO_TRANSFORM cam_transform; al_identity_transform(&cam_transform); al_build_camera_transform(&cam_transform , 0 , 0 , 1500 , 0 , 0 , 0 , 0 , 1 , 0); al_use_transform(&cam_transform); Setting up an equivalent projection transform to the one before, that makes the screen full size at -1000 relative distance on the z-axis : (note that al_perspective_transform is semantically equivalent to a glFrustum call, but with the parameters in a different order). ALLEGRO_TRANSFORM proj_transform; al_identity_transform(&proj_transform); al_perspective_transform(&proj_transform , -SCREEN_W/4 , -SCREEN_H/4 , 500 , SCREEN_W/4 , SCREEN_H/4 , 1500); al_use_projection_transform(&proj_transform); And now draw our texture screen sized using al_draw_prim and ALLEGRO_VERTEXs. ALLEGRO_COLOR white = al_map_rgb(255,255,255); int rx = al_get_bitmap_width(texture); int by = al_get_bitmap_height(texture); ALLEGRO_VERTEX v[4] = { {.x = SCREEN_W/2 , .y = SCREEN_H/2 , .z = 500, .color = white, .u = rx, .v = 0 }, {.x = SCREEN_W/2 , .y = -SCREEN_H/2, .z = 500, .color = white, .u = rx, .v = by}, {.x = -SCREEN_W/2, .y = -SCREEN_H/2, .z = 500, .color = white, .u = 0 , .v = by}, {.x = -SCREEN_W/2, .y = SCREEN_H/2 , .z = 500, .color = white, .u = 0 , .v = 0 } }; al_draw_prim(v , NULL , texture , 0 , 4 , ALLEGRO_PRIM_TRIANGLE_FAN);
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
bitrex
Member #16,587
November 2016
|
A huge help! Thanks so much gents, I really appreciate it. |
|