PDA

View Full Version : Drawing 2 quads with 2 different textures



afra89
04-01-2010, 08:58 AM
So i am working on 2D and with SDL and OpenGL.

I got it to work with using 1 quad with 1 texture on it, and moving it around with keyboard. Then i thought that i could add one more quad with another texture that just stays in place, while i move around the other quad with the other texture.

My code:



/************************************************** *****************
* *
* Using SDL With OpenGL *
* *
* Tutorial by Kyle Foley (sdw) *
* *
* http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
* *
************************************************** *****************/

#include "SDL/SDL.h"
#include <stdio.h>
#include <string.h>
#include "SDL/SDL_image.h"
#include <stdbool.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <stdio.h>

//The event structure
SDL_Event event;

float degree = 0.0f;
float x_pos=0.0f,y_pos=0.0f;
int check=0;
float size=0.0f;

GLuint texture; // Texture object handle

//Make sure the program waits for a quit
bool quit = false;


// Load the OpenGL texture
SDL_Surface *surface; // Gives us the information to make the texture

GLuint loadImage(char *path, GLuint tx,SDL_Surface* sur)
{
if ( (sur = IMG_Load(path)) )
{

// Check that the image's width is a power of 2
if ( (sur->w & (sur->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}

// Also check if the height is a power of 2
if ( (sur->h & (sur->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}

// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &amp;tx );

// Bind the texture object
glBindTexture( GL_TEXTURE_2D, tx );

// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

// Edit the texture object's image data using the information SDL_Surface gives us
glTexImage2D( GL_TEXTURE_2D, 0, 3, sur->w, sur->h, 0,
GL_BGR, GL_UNSIGNED_BYTE, sur->pixels );
}
else
{
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}

// Free the SDL_Surface only if it was successfully created
if ( sur )
{
SDL_FreeSurface( sur );
}

return tx;
}
int drawScene( GLuint tx ,float x,float y,float s)
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

glLoadIdentity( );

// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, tx );

glTranslatef(x_pos,y_pos,0.0f);
glRotatef(degree,0.0f,0.0f,1.0f);

glBegin( GL_QUADS );

// Top-left vertex (corner)
glTexCoord2i( 0, 0 );
glVertex3f( s, s, 0 );

// Bottom-left vertex (corner)
glTexCoord2i( 1, 0 );
glVertex3f( 228, s, 0 );

// Bottom-right vertex (corner)
glTexCoord2i( 1, 1 );
glVertex3f( 228, 228, 0 );

// Top-right vertex (corner)
glTexCoord2i( 0, 1 );
glVertex3f( s, 228, 0 );

glEnd();

SDL_GL_SwapBuffers();

return (true);
}

void moveLeft()
{
x_pos=x_pos-0.1f;
if(x_pos<-35)
{
x_pos=-35;
}
}

void moveRight()
{
x_pos=x_pos+0.1f;
}

void moveUp()
{
y_pos=y_pos-0.1f;
}

void moveDown()
{
y_pos=y_pos+0.1f;
}

void rotateRight()
{
degree=degree+0.1f;
}

void rotateLeft()
{
degree=degree-0.1f;
}

int main(int argc, char *argv[])
{
SDL_Surface *screen;

// Slightly different SDL initialization
if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}

SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*

screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
if ( !screen ) {
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}

// Set the OpenGL state after creating the context with SDL_SetVideoMode

glClearColor( 0, 0, 0, 0 );

glEnable( GL_TEXTURE_2D ); // Need this to display a texture

glViewport( 0, 0, 640, 480 );

glMatrixMode( GL_PROJECTION );
glLoadIdentity();

glOrtho( 0, 640, 480, 0, -1, 1 );

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

GLuint tx1,tx2;
SDL_Surface *characters;

tx1=loadImage("nehe1.bmp",tx1,characters);
drawScene(tx1,x_pos,y_pos,size);

tx2=loadImage("star.png",tx2,characters);
drawScene(tx2,40.0f,2.0f,size-30.0f);

while( quit == false )
{
//Get the keystates
Uint8 *keystates = SDL_GetKeyState( NULL );

//While there's an event to handle
while( SDL_PollEvent( &amp;event ) )
{
//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
// Free the SDL_Surface only if it was successfully created
if ( screen ) {
SDL_FreeSurface( screen );
}
quit = true;
}
}

if(keystates[ SDLK_e ])
{
rotateRight();
drawScene(tx1,x_pos,y_pos,size);
}
if(keystates[ SDLK_q ])
{
rotateLeft();
drawScene(tx1,x_pos,y_pos,size);
}
if(keystates[ SDLK_d ])
{
//x_pos=x_pos+0.1f;
moveRight();
drawScene(tx1,x_pos,y_pos,size);
}
if(keystates[ SDLK_a ])
{
//x_pos=x_pos-0.1f;
moveLeft();
drawScene(tx1,x_pos,y_pos,size);
}
if(keystates[ SDLK_w ])
{
//x_pos=x_pos-0.1f;
moveUp();
drawScene(tx1,x_pos,y_pos,size);
}
if(keystates[ SDLK_s ])
{
//x_pos=x_pos-0.1f;
moveDown();
drawScene(tx1,x_pos,y_pos,size);
}
}

// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &amp;texture );

SDL_Quit();

return 0;
}


But it first shows up the second texture only and if I touch the W,A,S,D buttons it disappears and it moves the first quad...I don't want the second quad to disappear -.-.

ZbuffeR
04-01-2010, 10:10 AM
You need to understand that whenever you swapbuffers, you have to clear and redraw the complete scene.

so move up the clear/loadidentity, as well as swapbuffers, something like that :



#pseudo code
drawCompleteScene(tx1,x1_pos,y1_pos,size1, tx2,x2_pos,y2_pos,size2) {

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity( );
drawScene( tx1,x1_pos,y1_pos,size1);
drawScene( tx2,x2_pos,y2_pos,size2);
SDL_GL_SwapBuffers();
}

afra89
04-01-2010, 11:32 AM
Okey thank you I see, so i have to first do the changes and then swap the screen.

Now 2 images appear on the screen, one over the other.
Something wierd is that when i press W,A,S,D both of the pictures move at the same time. It was intended that one should move and one to stay in place.

The thing i dont understand is htat for example if you have a background and a character and if you move the carachter you need to clear the screen, draw the background again and draw the characters new position again? Cant the background just remain and character be drawn in new position?

The part that i changed i marked with "**********".


/************************************************** *****************
* *
* Using SDL With OpenGL *
* *
* Tutorial by Kyle Foley (sdw) *
* *
* http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
* *
************************************************** *****************/

#include "SDL/SDL.h"
#include <stdio.h>
#include <string.h>
#include "SDL/SDL_image.h"
#include <stdbool.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <stdio.h>

//The event structure
SDL_Event event;

float degree = 0.0f;
float x_pos=0.0f,y_pos=0.0f;
int check=0;
float size=0.0f;

GLuint texture; // Texture object handle
GLuint character;
GLuint bg;

//Make sure the program waits for a quit
bool quit = false;

// Load the OpenGL texture
SDL_Surface *surface; // Gives us the information to make the texture

GLuint loadImage(char *path, GLuint tx,SDL_Surface* sur)
{
if ( (sur = IMG_Load(path)) )
{

// Check that the image's width is a power of 2
if ( (sur->w & (sur->w - 1)) != 0 ) {
printf("warning: image.bmp's width is not a power of 2\n");
}

// Also check if the height is a power of 2
if ( (sur->h & (sur->h - 1)) != 0 ) {
printf("warning: image.bmp's height is not a power of 2\n");
}

// Have OpenGL generate a texture object handle for us
glGenTextures( 1, &amp;tx );

// Bind the texture object
glBindTexture( GL_TEXTURE_2D, tx );

// Set the texture's stretching properties
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

// Edit the texture object's image data using the information SDL_Surface gives us
glTexImage2D( GL_TEXTURE_2D, 0, 3, sur->w, sur->h, 0,
GL_BGR, GL_UNSIGNED_BYTE, sur->pixels );
}
else
{
printf("SDL could not load image.bmp: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}

// Free the SDL_Surface only if it was successfully created
if ( sur )
{
SDL_FreeSurface( sur );
}

return tx;
}
int drawSmiley( GLuint tx ,float x,float y,float s)
{
// Bind the texture to which subsequent calls refer to
glBindTexture( GL_TEXTURE_2D, tx );

glTranslatef(x,y,0.0f);
glRotatef(degree,0.0f,0.0f,1.0f);

glBegin( GL_QUADS );

// Top-left vertex (corner)
glTexCoord2i( 0, 0 );
glVertex3f( s, s, 0 );

// Bottom-left vertex (corner)
glTexCoord2i( 1, 0 );
glVertex3f( 228, s, 0 );

// Bottom-right vertex (corner)
glTexCoord2i( 1, 1 );
glVertex3f( 228, 228, 0 );

// Top-right vertex (corner)
glTexCoord2i( 0, 1 );
glVertex3f( s, 228, 0 );

glEnd();

return (true);
}

void moveLeft()
{
x_pos=x_pos-0.1f;
if(x_pos<-35)
{
x_pos=-35;
}
}

void moveRight()
{
x_pos=x_pos+0.1f;
}

void moveUp()
{
y_pos=y_pos-0.1f;
}

void moveDown()
{
y_pos=y_pos+0.1f;
}

void rotateRight()
{
degree=degree+0.1f;
}

void rotateLeft()
{
degree=degree-0.1f;
}

int main(int argc, char *argv[])
{
SDL_Surface *screen;

// Slightly different SDL initialization
if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
printf("Unable to initialize SDL: %s\n", SDL_GetError());
return 1;
}

SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*

screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
if ( !screen ) {
printf("Unable to set video mode: %s\n", SDL_GetError());
return 1;
}

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

// Set the OpenGL state after creating the context with SDL_SetVideoMode

glClearColor( 0, 0, 0, 0 );

glEnable( GL_TEXTURE_2D ); // Need this to display a texture

glViewport( 0, 0, 640, 480 );

glMatrixMode( GL_PROJECTION );
glLoadIdentity();

glOrtho( 0, 640, 480, 0, -1, 1 );

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

GLuint txu,tx1,tx2;
SDL_Surface *characters;

//********************
tx1=loadImage("nehe1.bmp",txu,characters);
tx2=loadImage("star.png",txu,characters);
drawSmiley(tx1,x_pos,y_pos,size);
drawSmiley(tx2,200.0f,2.0f,size-30.0f);

SDL_GL_SwapBuffers(); //******************

while( quit == false )
{
//Get the keystates
Uint8 *keystates = SDL_GetKeyState( NULL );

//While there's an event to handle
while( SDL_PollEvent( &amp;event ) )
{
//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
// Free the SDL_Surface only if it was successfully created
if ( screen ) {
SDL_FreeSurface( screen );
}
quit = true;
}
}
//*************************
if(keystates[ SDLK_e ])
{
rotateRight();
}
if(keystates[ SDLK_q ])
{
rotateLeft();
}
if(keystates[ SDLK_d ])
{
//x_pos=x_pos+0.1f;
moveRight();
}
if(keystates[ SDLK_a ])
{
//x_pos=x_pos-0.1f;
moveLeft();
}
if(keystates[ SDLK_w ])
{
//x_pos=x_pos-0.1f;
moveUp();
}
if(keystates[ SDLK_s ])
{
//x_pos=x_pos-0.1f;
moveDown();
}
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity( );

drawSmiley(tx1,x_pos,y_pos,size);
drawSmiley(tx2,200.0f,2.0f,size-30.0f);

SDL_GL_SwapBuffers();
}
//************************************************** *********
// Now we can delete the OpenGL texture and close down SDL
glDeleteTextures( 1, &amp;texture );

SDL_Quit();

return 0;
}

ZbuffeR
04-01-2010, 01:01 PM
glTranslatef and glRotatef modify the current modelview matrix, so each time you do it, everything is affected, incrementally.
To "undo" the changes, use glPushMatrix() at the first line of drawSmiley, and glPopMatrix() at the last.

You should try to skim through a few beginners tutorials, this is really really basic stuff - ie. annoying to explain again and again if you see what I mean :) ...
http://nehe.gamedev.net/
http://www.lighthouse3d.com/opengl/tutorials.shtml