ALLEGRO_PRIM_QUAD
Todd Cope

Any chance we could get an ALLEGRO_PRIM_QUAD primitive type? I am in need of a function that works like OpenLayer's Bitmap::BlitDistorted() function. I tried using triangles but the texture doesn't get stretched correctly.

Trent Gamblin

I think you might be doing something wrong if the texture isn't applied correctly... But we don't have quads now because some hardware doesn't support them (some entire platforms don't support them)... I don't see any need. Maybe you could post your code?

Todd Cope

The problem I'm having is I am wanting to do some simple 3D effects but with triangles I am not getting the correct perspective on the texture. Because each triangle is rendered separately I get one triangle with the texture stretched one way and the other with the texture stretched another way. The effect I want cannot be done with triangles without actually using 3D.

Trent Gamblin

Sorry, I don't know what OpenLayer's Bitmap::BlitDistorted() does. Can you explain? Sometimes when you need a 3d effect, you need to use 3d?

Todd Cope

Here is a description of the function:

Quote:

Draws the bitmap such that the given coordinates describe the positions of the corner points of the bitmap in the screen.

Coordinates are given in a clockwise order starting from the top-left coordinate. The bitmap will be stretched to fill the quadrate area inside the corner points.

Trent Gamblin

Ok.. I'm not even sure how you would do that without shaders or making a bunch of triangles. I wouldn't add it to Allegro, I think it's too specialized but wait for the smart people to speak.

Dario ff

Trent, BlitDistorted actually uses a quad, here it is in case you want to take a loot at it:

#SelectExpand
1void Bitmap:: 2BlitDistorted( float x1, float y1, float x2, float y2, float x3, float y3, 3 float x4, float y4, const RenderMode &mode, float fact ) const { 4 mode.Select(); 5 6 GetReadyToRender( fact ); 7 8 OlRect renderArea = mode.GetRenderRect( OlRect( 0.0, 0.0, textureInfo.imgWidth, textureInfo.imgHeight )); 9 OlTexCoords texCoordArea = mode.GetTexCoords( OlTexCoords( textureInfo )); 10 11 texCoordArea.CalculateTextureCoords(); 12 13 bool setsTexCoords = mode.SetsTexCoords(); 14 15 float w = textureInfo.imgWidth; 16 float h = textureInfo.imgHeight; 17 18 glBegin( GL_QUADS ); 19 if( setsTexCoords ) 20 mode.SetTexCoord( OL_TC_BOTTOMLEFT, renderArea, texCoordArea, w, h ); 21 else 22 RenderMode::PrimarySetTexCoord( OL_TC_BOTTOMLEFT, renderArea, texCoordArea, w, h ); 23 24 glVertex2f( x4, y4 ); 25 26 if( setsTexCoords ) 27 mode.SetTexCoord( OL_TC_BOTTOMRIGHT, renderArea, texCoordArea, w, h ); 28 else 29 RenderMode::PrimarySetTexCoord( OL_TC_BOTTOMRIGHT, renderArea, texCoordArea, w, h ); 30 31 glVertex2f( x3, y3 ); 32 33 34 if( setsTexCoords ) 35 mode.SetTexCoord( OL_TC_TOPRIGHT, renderArea, texCoordArea, w, h ); 36 else 37 RenderMode::PrimarySetTexCoord( OL_TC_TOPRIGHT, renderArea, texCoordArea, w, h ); 38 39 glVertex2f( x2, y2 ); 40 41 if( setsTexCoords ) 42 mode.SetTexCoord( OL_TC_TOPLEFT, renderArea, texCoordArea, w, h ); 43 else 44 RenderMode::PrimarySetTexCoord( OL_TC_TOPLEFT, renderArea, texCoordArea, w, h ); 45 46 glVertex2f( x1, y1 ); 47 glEnd(); 48 49 mode.Unselect(); 50 51 if( !Settings::TextureMappingUsed() ) 52 glDisable( GL_TEXTURE_2D ); 53}

If the hardware supports it, quads could be a useful addition. If a software fallback routine isn't hard to do. :-/

Evert

It's not clear to me what that function does, or why you couldn't do the same thing by splitting the thing up into two triangles (as long as you order your vertices correctly and set the texture coordinates properly), however it seems to me you could just use a textured polygon?

Trent Gamblin

To me it sounds like you could place your vertices anywhere you like, so you could create a flattened out mobius strip, which is twisted so can't be rendered by two triangles AFAIK.

Todd Cope

Here's what it looks like when I use triangles:

{"name":"Screenshot-EOF%20Audition-1.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/4\/44024acc4a3d7d543c3c9d1231bb858b.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/4\/44024acc4a3d7d543c3c9d1231bb858b"}Screenshot-EOF%20Audition-1.png

Here's the original texture:

{"name":"neck.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/b\/c\/bc919f4302dab4e56a4de6097e031646.png","w":512,"h":1024,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/b\/c\/bc919f4302dab4e56a4de6097e031646"}neck.png

Trent Gamblin

Dario, missed your post... I think I understand now. It still plays by the rules of regular opengl quads. Basically it can draw trapezoids and other weird shapes but the vertices must be planar... So I think quads would be useful to simplify this stuff, though I'm not convinced it couldn't be done with triangles.

Evert

It can be done with triangles, but as the posted example shows, you can't do it with just two (four will work: chop off the slanted sides, then split the remaining rectangle in two).
I would still say that a textured polygon should work, but that may have the same issue (not sure).

SiegeLord

Using GL_QUADS results in the same output as triangles.

#SelectExpand
1#include <allegro5/allegro5.h> 2#include <allegro5/allegro_image.h> 3#include <allegro5/allegro_opengl.h> 4 5int main() 6{ 7 al_init(); 8 9 al_set_new_display_flags(ALLEGRO_OPENGL); 10 ALLEGRO_DISPLAY* disp = al_create_display(800, 800); 11 12 ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue(); 13 al_register_event_source(queue, al_get_display_event_source(disp)); 14 15 al_init_image_addon(); 16 ALLEGRO_BITMAP* texture = al_load_bitmap("grid.png"); 17 18 bool quit = false; 19 while(!quit) 20 { 21 ALLEGRO_EVENT event; 22 if(al_get_next_event(queue, &event)) 23 { 24 if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 25 quit = true; 26 } 27 28 glEnable(GL_TEXTURE_2D); 29 glBindTexture(GL_TEXTURE_2D, al_get_opengl_texture(texture)); 30 31 glBegin(GL_QUADS); 32 33 glTexCoord2f(0, 0); 34 glVertex2f(400, 200); 35 36 glTexCoord2f(1, 0); 37 glVertex2f(500, 200); 38 39 glTexCoord2f(1, 1); 40 glVertex2f(800, 600); 41 42 glTexCoord2f(0, 1); 43 glVertex2f(100, 600); 44 45 glEnd(); 46 47 al_flip_display(); 48 al_rest(0.01); 49 } 50 51 return 0; 52}

Output:
{"name":"601548","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/4\/24b3b452b84845d7eb51487dcb436b6d.png","w":800,"h":800,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/4\/24b3b452b84845d7eb51487dcb436b6d"}601548

Dario ff

I would've guessed that since the original function was using QUADs the texture's mapping would be fixed... but why does the mapping in your example look like it was done with 2 triangles?

Trent Gamblin

The graphics card breaks a quad into two triangles. Everything is done in triangles at the lowest level of the gpu.

SiegeLord
Dario ff said:

I would've guessed that since the original function was using QUADs the texture's mapping would be fixed... but why does the mapping in your example look like it was done with 2 triangles?

Because it is done like that internally. GL_QUADS is just a convenience type. Internally, OpenGL tesselates the quad into two triangles. For Todd Cope to get what he wants he needs to either:

  1. Use perspective (primitives addon in principle supports this in hardware mode)

  2. Approximate the effect using more triangles (e.g. in the way Evert suggested)

Note that without the third dimension you can never get the proper mapping (unless your vertices are arranged in a particular way) because the generic quad to quad mapping is non-affine... and without 3D, only affine mappings can be done. You can get a good approximation by throwing more triangles at it, but it won't be exact in the general case.

Dario ff

I see. I'm getting the same here... the only difference is that the image seems to be flipped horizontally.

Oscar Giner

Assuming that the projection matrix is set up as an orthogonal projection, you can get the effect with just 2 triangles and playing with the z coordinate. A bit of trigonometry should give you what z values you need to use.

Well if the output he expects is what I think (the horizontal lines won't be equidistant).

Trent Gamblin

I thought with an orthographic projection, z value didn't matter and distant objects appear in line with close objects, i.e., there is no way to tell tell distance of anything.

Oscar Giner

Now I'm starting to not be sure about what OpenGL would output doing that. I would think that the z coordinate would be used to perform the perspective correction and you could get the desired output that way (it's a bit of a hack/trick actually). But I haven't used OpenGL in a lot of time and now I'm unsure about that.

Trent Gamblin

I think you need a perspective projection for that, not an orthographic projection.

Dario ff

Can't we just investigate on OpenLayer's setup and see how it setups the projections?

SiegeLord

The point I was getting at is that OpenLayer does it wrong also, since it uses the GL_QUADS in the same way I did: a single quad on a plane. In that configuration the perspective does not matter, since the quad is parallel to the viewing plane. It'd be nice if someone with OpenLayer could confirm this.

Dario ff

AFAIK, OpenLayer sets up an ortographic projection like this:

    glMatrixMode( GL_PROJECTION );
    glPushMatrix();
    glLoadIdentity();
    glOrtho( 0, w, 0, h, -1, 1000 );
    glScalef( 1, -1, 1 );
    glTranslatef( 0, -h, 0 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glDisable( GL_DEPTH_TEST );

There must be something else though, but I'm looking for any clues. If you want, I'll attach OpenLayer's source here.

EDIT: Ok, here it is. I took away the demos, but I just 7-zipped the old package I had. Download.

Arthur Kalliokoski

As far as I can see, the correct mapping would have to be in 3d with the bottom vertices near the camera, and the top vertices in the distance, but the vertices are actually a square in 3 space. Using an orthgraphic projection would show this as a square every time.

Dario ff

OpenLayer's alternative BlitDistorted function actually uses a GL_TRIANGLE_FAN. :-/

Elias

Well, do you have a screenshot how it looks in OpenLayer?

Dario ff

How curious, after months of not using it, it doesn't seem to be able to do this as well.
{"name":"601562","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/2\/52818de022201e6db00ac0c433f54981.jpg","w":795,"h":602,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/5\/2\/52818de022201e6db00ac0c433f54981"}601562
I remember it working perfectly. ??? Maybe this case is hard to do?

Elias

Ok, so we don't want a function that "works like OpenLayer's Bitmap::BlitDistorted" but a new function nobody has ever done yet...? :P

Todd Cope

Seems like too much of a hassle to me. I thought it would be something simple but from the looks of it this is something that is best left to being done in 3D. I retract my request.

Elias

Googling a bit I found this paper from 2004. It sounds like a method to do what you want: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.62.7170&rep=rep1&type=pdf

It requires a hardware implementation though and doesn't seem like any hardware supports it, they all just use triangles. OpenGL ES 1 and 2 as well as normal OpenGL 3 and 4 even removed the GL_QUAD primitives completely. So yes, your best bet is to just use one of the methods suggested in this thread to achieve it, in your own code.

Thread #604303. Printed from Allegro.cc