Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Allegro 3d functions

This thread is locked; no one can reply to it. rss feed Print
Allegro 3d functions
ngiacomelli
Member #5,114
October 2004

I was looking at the Allegro camera example and am considering using the code to render a flat plane, which I would use with a static camera.

I'm not very good when it comes to visualising 3d projection (or math in general). Having never used Allegro's 3d routines before, I assume to render a billboard sprite, I would do something like this:

apply_matrix_f(&camera, p_x, p_y, p_z, &p_x2, &p_y2, &p_z2);
persp_project_f(p_x2, p_y2, p_z2, &t_x, &t_y);

draw_sprite( bmp, sprite, (int)t_x, (int)t_y);

As long as I've got that right, my next question would be: what's the best way to scale the image? Or do you suggest I create a flat polygon for each image, and render the sprites using a TRANS POLYTYPE?

If persp_project_f takes a 3d coordinate and projects it to 2d space, how would I reverse the process for, say, the mouse coordinates?

Thomas Harte
Member #33
April 2000
avatar

Quote:

As long as I've got that right, my next question would be: what's the best way to scale the image?

Use stretch_sprite, and do something like:

persp_project_f(my_sprites_width, my_sprites_height, p_z2, &draw_width, &draw_height);

When p_z2 = 1 you'll get draw_width = my_sprites_width and draw_height = my_sprites_height, so decide what to do about picking my_sprites_width/height based on that. Or just play around!

Quote:

If persp_project_f takes a 3d coordinate and projects it to 2d space, how would I reverse the process for, say, the mouse coordinates?

Sorry, no time to comment on this (I'm on my way out), but do you need a "general solution" or will you accept a Mode 7 specific routine that simply tells you either that you hit a particular sprite or else that you hit a particular spot on the floor?

ngiacomelli
Member #5,114
October 2004

Well, I've got my plane rendered using the Allegro polygon routines, and I've got it rendering my tilemap. Which is good news. Really, right now, I'm writing the helper functions. This is going to be a two week Christmas break project. So I want to get most of the engine stuff out of the way.

I'm looking for an easy way to plot mouse -> 3d position for my map editor, more than anything. Just a routine that takes a mouse click and figures out: a) if a floor tile was clicked, b) which one it was.

I'm still not entirely sure what you meant with the stretch_sprite code you provided. If you could explain that a little more, I'd be very greatful. The code I'm using is as follows:

void render_object( MATRIX_f *cam, BITMAP *bmp, BITMAP *sprite, float x, float y, float z ) {
     
   float r_x, r_y, r_z;
   float t_x, t_y, s_x, s_y;

   apply_matrix_f(cam, x, y, z, &r_x, &r_y, &r_z);
   persp_project_f(r_x, r_y, r_z, &t_x, &t_y);   
   persp_project_f(64.0, 64.0, 1.0, &s_x, &s_y);
   
   stretch_sprite( bmp, sprite, (int)t_x, (int)t_y, (int)s_x, (int)s_y );
     
}

Thomas Harte
Member #33
April 2000
avatar

Okay, if you want to do it as a Christmas break project, then why not just do a 'quick fix' solution? E.g. create a true colour second bitmap for your level editor, and render your floormap to that as plain polygons. Give each one a distinct colour and then just use getpixel on it with the mouse location as a shortcut way of finding out which tile you are over?

Quote:

I'm still not entirely sure what you meant with the stretch_sprite code you provided.

Change persp_project_f(64.0, 64.0, 1.0, &s_x, &s_y) to persp_project_f(64.0, 64.0, r_z, &s_x, &s_y) — if you think about it then you clearly need to get z in there somehow and size is really just the difference between two positions, so it should vary exactly as positions do with regard to depth.

Tobias Dammers
Member #2,604
August 2002
avatar

Quote:

E.g. create a true colour second bitmap for your level editor, and render your floormap to that as plain polygons. Give each one a distinct colour and then just use getpixel on it with the mouse location as a shortcut way of finding out which tile you are over?

In fact, this is not a quick fix, but a rather useful solution - maybe even the best for this situation. The OpenGL documentation describes a very similar approach, though allegro's 3D API has the advantage that there is no color conversion or dithering, so a 32 bpp index buffer gives you the full 32 bits, and you can do it all in one pass. You can speed things up more by applying a very small clipping area to the index buffer bitmap, just around the mouse position. This way, most of the actual rendering will get clipped out.

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

ngiacomelli
Member #5,114
October 2004

Perfect. I'd actually seen a similar solution used in isometric engines. I'll do it that way! As far as my object rendering code is concerned:

void render_object( MATRIX_f *cam, BITMAP *bmp, BITMAP *sprite, float x, float y, float z ) {
     
   float r_x=0, r_y=0, r_z=0;
   float t_x=0, t_y=0, s_x=0, s_y=0;

   apply_matrix_f(cam, x, y, z, &r_x, &r_y, &r_z);
   persp_project_f(r_x, r_y, r_z, &t_x, &t_y);   
   persp_project_f(sprite->w, sprite->h, r_z, &s_x, &s_y);
     
   stretch_sprite( bmp, sprite, (int)t_x, (int)t_y, (int)s_x, (int)s_y );
     
}

The bitmap will grow/shrink dependant upon distance. But the sprite is stretched to ridiculous proportions ( > 1500 pixels ). Is it just a case of dividing the s_x and s_y values by some amount ( tweeking it until it feels right ). Or is there some math that I'm missing here?

Thomas Harte
Member #33
April 2000
avatar

Quote:

Is it just a case of dividing the s_x and s_y values by some amount ( tweeking it until it feels right ). Or is there some math that I'm missing here?

You're not missing anything — it's just a matter of tweaking really. What you're deciding, strictly speaking, is the dimensions in your 3d world of one pixel of your original sprite. At the minute at distance "1", your sprites have their original pixel dimensions. When they get closer they'll get substantially larger. Quite how "far away" 1 is probably isn't something you've decided explicitly (you probably just played with the camera settings until you got something that looks good?) so just play with s_x and s_y to get something that works there!

Quote:

In fact, this is not a quick fix, but a rather useful solution

Sorry, yes. It isn't a quick fix because it would generally work for any 3d scene of any geometry complexity provided you had at least as many colours as polygons. I just meant it's a quick fix because it's something that will work and is easy to understand and implement.

Go to: