Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Cargar Textura Con Opengl

Iniciado por javiel, 20 de Diciembre de 2005, 06:51:23 PM

« anterior - próximo »

javiel

 Bueno, estoy intentando hacer mis primeros pinitos con opengl + sdl y quiero poner una textura en 2d. Lo he conseguido, pero tengo una duda a ver si me la podéis responder. Lo que estoy intentando es para hacer un juego en 2d con opengl, así q de principio nada de 3d. Se poco de opengl, casi nada

Tengo un código que pone una textura. La cosa es que la textura sale en el centro de la pantalla alineada a la izquierda y abajo. Para poder moverla uso "glTranslatef" para poner el origen de coordenadas el GL_QUAD que voy a crear con la textura. La cosa es que no puedo usar posiciones directamente. Es decir, mi pantalla es de 640x480 y yo quisiera poner que la textura se cargara en el pixel 100x100 y no puedo. Puedo hacerlo mediante números relativos a la pantalla.

No se si me explicado bien, la verdad que creo que me he explicado como el culo. A ver si me entendéis


El codigo del programa es este. Si os fijais es un código de la web de Nehe (www.demonews.com/hosted/nehe) que he modificado.

gracias a todos



#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#if defined(__APPLE__) && defined(__MACH__)
#include <OpenGL/gl.h> // Header File For The OpenGL32 Library
#include <OpenGL/glu.h> // Header File For The GLu32 Library
#else
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
#endif
#include "SDL.h"
#include <stdlib.h>

/* floats for x rotation, y rotation, z rotation */
float xrot, yrot, zrot;

/* storage for one texture  */
GLuint texture[1];

SDL_Surface *LoadBMP(char *filename)
{
   Uint8 *rowhi, *rowlo;
   Uint8 *tmpbuf, tmpch;
   SDL_Surface *image;
   int i, j;

   image = SDL_LoadBMP(filename);
   if ( image == NULL ) {
       fprintf(stderr, "Unable to load %s: %s\n", filename, SDL_GetError());
       return(NULL);
   }

   /* GL surfaces are upsidedown and RGB, not BGR :-) */
   tmpbuf = (Uint8 *)malloc(image->pitch);
   if ( tmpbuf == NULL ) {
       fprintf(stderr, "Out of memory\n");
       return(NULL);
   }
   rowhi = (Uint8 *)image->pixels;
   rowlo = rowhi + (image->h * image->pitch) - image->pitch;
   for ( i=0; i<image->h/2; ++i ) {
       for ( j=0; j<image->w; ++j ) {
           tmpch = rowhi[j*3];
           rowhi[j*3] = rowhi[j*3+2];
           rowhi[j*3+2] = tmpch;
           tmpch = rowlo[j*3];
           rowlo[j*3] = rowlo[j*3+2];
           rowlo[j*3+2] = tmpch;
       }
       memcpy(tmpbuf, rowhi, image->pitch);
       memcpy(rowhi, rowlo, image->pitch);
       memcpy(rowlo, tmpbuf, image->pitch);
       rowhi += image->pitch;
       rowlo -= image->pitch;
   }
   //free(tmpbuf);
   return(image);
}

// Load Bitmaps And Convert To Textures
void LoadGLTextures(void)
{
   // Load Texture
   SDL_Surface *image1;
   
   image1 = LoadBMP("imagen.bmp");
   if (!image1) {
       SDL_Quit();
       //exit(1);
   }

   // Create Texture
   glGenTextures(1, &texture[0]);
   glBindTexture(GL_TEXTURE_2D, texture[0]);   // 2d texture (x and y size)

   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture

   // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
   // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
   glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->w, image1->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->pixels);
};

/* A general OpenGL initialization function.  Sets all of the initial parameters. */
void InitGL(int Width, int Height)         // We call this right after our OpenGL window is created.
{
   glViewport(0, 0, Width, Height);
   LoadGLTextures();    // Load The Texture(s)
   glEnable(GL_TEXTURE_2D);   // Enable Texture Mapping
   glClearColor(0.0f, 0.0f, 1.0f, 0.0f); // Clear The Background Color To Blue
   glClearDepth(1.0);    // Enables Clearing Of The Depth Buffer
   glDepthFunc(GL_LESS);   // The Type Of Depth Test To Do
   glEnable(GL_DEPTH_TEST);   // Enables Depth Testing
   glShadeModel(GL_SMOOTH);   // Enables Smooth Color Shading
   
   glMatrixMode(GL_PROJECTION);
   
   glMatrixMode(GL_MODELVIEW);
}

/* The main drawing function. */
void DrawGLScene()
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear The Screen And The Depth Buffer
   glLoadIdentity();    // Reset The View

   glTranslatef(-0.3f,-0.3f,0.0f);

   glEnable(GL_TEXTURE_2D);
   glEnable(GL_BLEND);
   glBindTexture(GL_TEXTURE_2D, texture[0]);   // choose the texture to use.
   
   int x = 0, y = 0, w = 256, h = 256;
   
   glBegin(GL_QUADS);
     glTexCoord2f(0.0f, 1.0f);
     glVertex2f(0.0f, 1.0f);
     glTexCoord2f(1.0f, 1.0f);
     glVertex2f(1.0f, 1.0f);
     glTexCoord2f(1.0f, 0.0f);
     glVertex2f(1.0f, 0.0f);
     glTexCoord2f(0.0f, 0.0f);
     glVertex2f(0.0f, 0.0f);
   glEnd();
   
   glDisable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);

   // swap buffers to display, since we're double buffered.
   SDL_GL_SwapBuffers();
}

int main(int argc, char **argv)
{  
 int done;

 /* Initialize SDL for video output */
 if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
   fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
   //exit(1);
 }

 /* Create a 640x480 OpenGL screen */
 if ( SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL ) {
   fprintf(stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError());
   SDL_Quit();
   //exit(2);
 }

 /* Set the title bar in environments that support it */
 SDL_WM_SetCaption("Jeff Molofee's GL Code Tutorial ... NeHe '99", NULL);

 /* Loop, drawing and checking events */
 InitGL(640, 480);
 done = 0;
 while ( ! done ) {
   DrawGLScene();

   /* This could go in a separate function */
   { SDL_Event event;
     while ( SDL_PollEvent(&event) ) {
       if ( event.type == SDL_QUIT ) {
         done = 1;
       }
       if ( event.type == SDL_KEYDOWN ) {
         if ( event.key.keysym.sym == SDLK_ESCAPE ) {
           done = 1;
         }
       }
     }
   }
 }
 SDL_Quit();
 return 1;
}
uper-Tirititran: el superhéroe gaditano (http://www.super-tirititran.com)

BeRSeRKeR

 No he mirado el código pero por lo que explicas, me imagino que tendrás que utilizar una proyección ortográfica. Supongo que en Nehe también habrá tutoriales sobre eso.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

senior wapo

 No uses glTranslate, pon las coordenadas correctas directamente. Ni siquiera necesitas proyección ortográfica.

Leete lo que contesté en este hilo antiguo a ver si te aclara algo:

Coordenadas y frustum en OpenGL

Lord Trancos 2

 Te cuento lo que yo hago (por si te sirve).

Primero llamo a esta funcion:


procedure GUI3D_BeginDraw(_left, _top, _right, _bottom: single);

// PROJECTION matrix are saved and 'll be restored when callig _EndDraw,
// but MODEL VIEW aren't saved!

begin
 // save current model view matrix
 glPushMatrix;

 // save current projection matrix, and set the identity matrix
 glMatrixMode(GL_PROJECTION);
 glPushMatrix;

 // set ortho mode
 glLoadIdentity;
 glOrtho(_left, _right, _bottom, _top, 0, 1);

 // switch to model view
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity;
end;


La cual me prepara el modo ortho, y ademas me permite especificar las cooredenadas 2D que tendra la pantalla. Yo suelo usar el valor 0 para el top y el left, y luego para right/bottom uso 4000/3000. Con lo cual me queda una pantalla de 4000 x 3000 pixeles virtuales (independientemente de la resolucion REAL que tenga la pantalla).

Despues cada vez que quiero dibujar uso una funcion como la siguiente:


procedure GUI3D_DrawRectTC1(_x1, _y1, _x2, _y2: single;
                           _s1, _t1, _s2, _t2: single;
                           _color: PGL4f);

begin
 with _color^ do glColor4f(f1, f2, f3, f4);

 glBegin(GL_QUADS);

 glTexCoord2f(_s1, _t1);
 glVertex2f(_x1, _y1); // top-left
 glTexCoord2f(_s1, _t2);
 glVertex2f(_x1, _y2); // bottom-left
 glTexCoord2f(_s2, _t2);
 glVertex2f(_x2, _y2); // bottom-right
 glTexCoord2f(_s2, _t1);
 glVertex2f(_x2, _y1); // top-right

 glEnd();
end;


Donde simplemente especifico coordenadas 2D "de toda la vida", eso si, teniendo en cuenta que la resolucion virtual (4000 x 3000).

Y una vez que he terminado de dibujar, llamo a la siguiente funcion que me restaura las matrizes (y por lo tanto deshace el modo ortho).


procedure GUI3D_EndDraw;

begin
 // restore projection matrix
 glMatrixMode(GL_PROJECTION);
 glPopMatrix;

 // restore model view matrix
 glMatrixMode(GL_MODELVIEW);
 glPopMatrix;
end;


Espero que se entienda y te sirva.
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

javiel

 De principio he usado Proyeccion ortográfica porque lo entiendo mejor. El enlace que me ha dado senior wapo me ha resuelto muchas dudas. Muchas gracias. Ahora solo una cosilla. Ya pongo las cosas donde quiero, ahora me gustaría rotar la imagen sobre su centro. El problema es que cuando uso glRotatef en el eje Z me rota, pero usa como centro de rotación el centro de coordenadas (0,0). Pongo el código


void InitGL(int Width, int Height)         // We call this right after our OpenGL window is created.
{
   glViewport(0, 0, Width, Height);
   LoadGLTextures();    // Load The Texture(s)
   glEnable(GL_TEXTURE_2D);   // Enable Texture Mapping
   glClearColor(0.0f, 0.0f, 1.0f, 0.0f); // Clear The Background Color To Blue
   glClearDepth(1.0);    // Enables Clearing Of The Depth Buffer
   glDepthFunc(GL_LESS);   // The Type Of Depth Test To Do
   glEnable(GL_DEPTH_TEST);   // Enables Depth Testing
   glShadeModel(GL_SMOOTH);   // Enables Smooth Color Shading
   
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(0, Width, Height, 0, 0, 1);    
   
   glMatrixMode(GL_MODELVIEW);
}

void DrawGLScene()
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glLoadIdentity();

   glRotatef(zrot,0.0f,0.0f,1.0f);

   glBindTexture(GL_TEXTURE_2D, texture[0]);

   int x = 50, y = 150, w = 256, h = 256;
   
   glBegin(GL_QUADS);
     glTexCoord2f(0.0f, 1.0f);
     glVertex2f(x,y);
     glTexCoord2f(1.0f, 1.0f);
     glVertex2f(x + w, y);
     glTexCoord2f(1.0f, 0.0f);
     glVertex2f(x + w, y + h);
     glTexCoord2f(0.0f, 0.0f);
     glVertex2f(x, y + h);
   glEnd();

   zrot+=1.0f;

   SDL_GL_SwapBuffers();
}


¿que tendría que hacer para que sólo rotase esa imagen y sobre su centro?

otra cosa Lord Trancos 2, ¿porque deshaces la proyección ortográfica al final de mostrar la imagen?

gracias a todos
uper-Tirititran: el superhéroe gaditano (http://www.super-tirititran.com)

Lord Trancos 2

Cita de: "javiel"otra cosa Lord Trancos 2, ¿porque deshaces la proyección ortográfica al final de mostrar la imagen?
Pq el código que te he enseñado es para dibujar el GUI de los juegos 3D que hago, asi que deshago la proyeccion para q la proxima vez que entre en la funcion que dibuja la escena 3D las matrices esten en su sitio. Pero vamos, si vas ha hacer un juego completamente 2D, no hace falta, claro.

Respecto a lo de rotar tienes 2 opciones:
- Rotar y despues trasladar el quad con las funciones de OpenGL (glTranslate, glRotate).
- O bien calcular la posicion de los vertices manualmente y pasarle a OpenGL directamente las coordenadas transformadas (tal y como lo hago yo en mis funciones).

pero mejor no mezcles. O lo calculas tu todo, o se lo dejas todo a OpenGL.

Para que rote sobre su centro, tendrias que especificar un QUAD con las coordenadas 0,0 en su centro; por ejemplo:
x1 = -1, y1 = -1, x2 = 1, y2 = 1
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

Ray

 No entiendo por que no usas glTranslatef para desplazar el sprite, yo lo hago así y me va bien.

despues con el glRotatef lo giro.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.