Jump to content
  • Advertisement
Sign in to follow this  
beloni

OpenGL move through an image

This topic is 4140 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I need move the screen window through an large image.bmp:
//pixmap.h
typedef char byte;
typedef unsigned char ubyte;

struct pixmap
{
	unsigned width, 
					 height;
	ubyte *data;

	enum {RED = 0, GREEN, BLUE};

	pixmap(const char *fname);
	pixmap();
	~pixmap();

	void read(const char *fname);
	ubyte pixel_elem(int x, int y, int elem);
	ubyte *pixel_pos(int x, int y);
};


//pixmap.cpp

#include "pixmap.h"

#include <fstream>
#include <iostream>
#include <cstdlib>


pixmap::pixmap(const char *fname)
	: width(0), height(0), data(0)
{
	this->read(fname);
}

pixmap::pixmap()
	: width(0), height(0), data(0) {}

pixmap::~pixmap()
{
	if( data )
		delete[] data;
}

void pixmap::read(const char *fname)
{
	using namespace std;

	unsigned short planes;	// number of planes in image (must be 1) 
	unsigned short bpp;			// number of bits per pixel (must be 24)

	ifstream fin(fname, ios::in | ios::binary);
	if( !fin )
	{
		cerr << "File not found " << fname << '\n';
		exit(1);
	}
  
	fin.seekg(18, ios::cur);

	fin.read((byte *)&width, sizeof(unsigned));
	fin.read((byte *)&height, sizeof(unsigned));
	cout << "width: " << width << " height: " << height << '\n';

	fin.read((byte *)&planes, sizeof(unsigned short));
	if( planes != 1 )
	{
		cout << "Planes from " << fname << " is not 1: " << planes << "\n";
		exit(1);
	}

	fin.read((byte *)&bpp, sizeof(unsigned short));
	if( bpp != 24 )
	{
		cout << "Bpp from " << fname << " is not 24: " << bpp << "\n";
		exit(1);
	}
	
	fin.seekg(24, ios::cur);

	unsigned size(width * height * 3);				// size of the image in bytes (3 is to RGB component).
	data = new ubyte[size];
	fin.read((byte *)data, size);

	ubyte tmp;					// temporary color storage for bgr-rgb conversion.
	for( int i(0); i < size; i += 3 )
	{
		tmp = data;
		data = data[i+2];
		data[i+2] = tmp;
	}
}

ubyte pixmap::pixel_elem(int x, int y, int elem)
{
	int pos = (y*width+x) * 3 + elem;
	return data[pos];
}

ubyte *pixmap::pixel_pos(int x, int y)
{
	int pos = (y * width + x) * 3;
	return &data[pos];
}

//test program

#include <GL/glut.h>
#include <iostream>
#include <cstdlib>

#include "pixmap.h"

#define MAX_WIDTH 300
#define MAX_HEIGHT 200


pixmap *img(0);
GLfloat transx(0.0), transy(0.0);

void init_gl()
{
	glClearColor(0.0, 0.0, 0.0, 0.0);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLfloat)MAX_WIDTH, 0.0, (GLfloat)MAX_HEIGHT);
}

void reshape(int w, int h)
{
	glViewport (0, 0, (GLint)w, (GLint)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, (GLfloat)w, 0.0, (GLfloat)h);
//	gluOrtho2D(-(GLfloat)MAX_WIDTH, (GLfloat)MAX_WIDTH, -(GLfloat)MAX_HEIGHT, (GLfloat)MAX_HEIGHT);
}

void render_scene()
{
	glClear(GL_COLOR_BUFFER_BIT);

// drawing it manually
/*	glBegin(GL_POINTS);
	for( int i(0); i < img->width; i++ )
		for( int j(0); j < img->height; j++ )
		{
//			glColor3ub(img->pixel_elem(i, j, pixmap::RED),
//								 img->pixel_elem(i, j, pixmap::GREEN),
//								 img->pixel_elem(i, j, pixmap::BLUE));
			glColor3ubv(img->pixel_pos(i, j));
			glVertex2i(i+(int)transx, j+(int)transy); 
		}
	glEnd();*/

// draw using OpenGL functions
	glTranslatef(transx, transy, 0.0);
	glRasterPos2i(0, 0);
	glDrawPixels(img->width, img->height, GL_RGB, GL_UNSIGNED_BYTE, img->data);

	glutSwapBuffers();
	glFlush();
}

void keyb_handler(unsigned char key, int x, int y)
{
	if( key == 27 )
		std::exit(0);
}

void special_key(int key, int x, int y)
{
	switch( key )
	{
		case GLUT_KEY_UP:
		{
			transy = -5.0;
			transx = 0.0;
			break;
		}

		case GLUT_KEY_DOWN:
		{
			transy = +5.0;
			transx = 0.0;
			break;
		}

		case GLUT_KEY_LEFT:
		{
			transx = +5.0;
			transy = 0.0;
			break;
		}

		case GLUT_KEY_RIGHT:
		{
			transx = -5.0;
			transy = 0.0;
			break;
		}
	}
	glutPostRedisplay();
}

void special_key2(int key, int x, int y)
{
	switch( key )
	{
		case GLUT_KEY_UP:
		{
			if( transy < MAX_HEIGHT ) transy += 5.0;
			break;
		}

		case GLUT_KEY_DOWN:
		{
			if( transy > 0 ) transy -= 5.0;
			break;
		}

		case GLUT_KEY_LEFT:
		{
			if( transx > 0 ) transx -= 5.0;
			break;
		}

		case GLUT_KEY_RIGHT:
		{
			if( transx < MAX_WIDTH ) transx += 5.0;
			break;
		}
	}
	glutPostRedisplay();
}

int main(int argc, char **argv)
{
	if( argc != 2 )
	{
		std::cerr << "INVALID ARGUMENTS\n";
		std::cerr << "You should specify the pixmap to load!\n";
		return 1;
	}

	img = new pixmap(argv[1]);

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("A pixmap loader - by Beloni");

	init_gl();

	glutDisplayFunc(&render_scene);
	glutReshapeFunc(&reshape);
	glutKeyboardFunc(&keyb_handler);
	glutSpecialFunc(&special_key);
//	glutFullScreen();

	glutMainLoop();
	delete img;
	return 0;
}


Can you help me to do that? [Edited by - beloni on May 17, 2007 12:48:21 PM]

Share this post


Link to post
Share on other sites
Advertisement
You seem to have the right approach, but it's hard to see what's going wrong. Could you describe which part exactly is giving you troubles?

Also, when posting large segments of code, try to encase your code within source tags, like so (without spaces in the tags):

[ source ] _code_here_ [ /source ]

That will format your code nicely, making it easier for others to read.

Share this post


Link to post
Share on other sites
Thanks for posting source tips.
The right and up translations are done nicely, so the window actually seems to move through the image.
The problem occurs when the translation must affect the image down and left, in which image coordinates tends to zero: the image simply disappear (reasonably).
so the question is:
Quote:

How to move through an image? This like in RPG game (but this is not a game), where whatever the avatar moves, the background image (scenario) moves.


In my program, to move the image you should use the cursor keys...

Share this post


Link to post
Share on other sites
I'm not positive about this, but I'm pretty sure that using glTranslate will have no effect on glRasterPos or glDrawPixels, as those deal in window coordinates rather than 3d coordinates. One possibility would be to get rid of the glTranslate call and call glRasterPos with transx and transy instead, but I think that a better alternative would be to create a texture out of your image and then render it on a quad.

Share this post


Link to post
Share on other sites
Ok, thanks.
But how do can I create a texture of the image and render it on a quad?

Share this post


Link to post
Share on other sites
Quote:
Original post by beloni
Ok, thanks.
But how do can I create a texture of the image and render it on a quad?

NeHe has a great tutorial with sample code that shows you exactly how to do this. See the tutorial located here.

Share this post


Link to post
Share on other sites
Thanks a lot, I got it!
But it has some problems when the window is resized. Can I not allow the user resize the window in GLUT library?

That is my new source. The pixmap.h is the same as above


#include <GL/glut.h>
#include <iostream>
#include <exception>
#include <cstdlib>

#include "pixmap.h"

#define MAX_WIDTH 600
#define MAX_HEIGHT 400

pixmap *img(0);
GLfloat trans[] = {0.0, 0.0};
unsigned pos[] = {0ul, MAX_WIDTH, MAX_HEIGHT, 0ul};
GLuint texid(0);

void init_gl()
{
glClearColor(0.0, 0.0, 0.0, 0.0);

// loading texture
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
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

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->width, img->height, 0, GL_RGB, GL_UNSIGNED_BYTE, img->data);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLfloat)MAX_WIDTH, 0.0, (GLfloat)MAX_HEIGHT);
}

void reshape(int w, int h)
{
glViewport (0, 0, (GLint)w, (GLint)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLfloat)w, 0.0, (GLfloat)h);
}

void render_scene()
{
glClear(GL_COLOR_BUFFER_BIT);

glEnable (GL_TEXTURE_2D); /* enable texture mapping */

glBindTexture (GL_TEXTURE_2D, texid); /* bind to our texture, has id of 13 */



glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f); /* lower left corner of image */

glVertex2i(0, 0);

glTexCoord2f(1.0f, 0.0f); /* lower right corner of image */

glVertex2i(img->width, 0);

glTexCoord2f(1.0f, 1.0f); /* upper right corner of image */

glVertex2i(img->width, img->height);

glTexCoord2f(0.0f, 1.0f); /* upper left corner of image */

glVertex2i(0, img->height);

glEnd ();



glDisable(GL_TEXTURE_2D); /* disable texture mapping */

glutSwapBuffers();
}

void keyb_handler(unsigned char key, int x, int y)
{
if( key == 27 )
std::exit(0);
}

void special_key(int key, int x, int y)
{
bool flag(false);
switch( key )
{
case GLUT_KEY_UP:
if( pos[2] < (img->height-1) )
{
trans[1] = -5.0;
trans[0] = 0.0;
flag = true;
pos[2] += 5;
pos[0] += 5;
}
break;

case GLUT_KEY_DOWN:
if( pos[0] > 0 )
{
trans[1] = +5.0;
trans[0] = 0.0;
flag = true;
pos[0] -= 5;
pos[2] -= 5;
}
break;

case GLUT_KEY_LEFT:
if( pos[3] > 0 )
{
trans[0] = +5.0;
trans[1] = 0.0;
flag = true;
pos[3] -= 5;
pos[1] -= 5;
}
break;

case GLUT_KEY_RIGHT:
if( pos[1] < (img->width-1) )
{
trans[0] = -5.0;
trans[1] = 0.0;
flag = true;
pos[1] += 5;
pos[3] += 5;
}
break;
}
if( flag )
{
glTranslatef(trans[0], trans[1], 0.0);
glutPostRedisplay();
}
}

int main(int argc, char **argv)
{
if( argc != 2 )
{
std::cerr << "INVALID ARGUMENTS\n";
std::cerr << "You should specify the pixmap to load!\n";
return 1;
}

try
{
img = new pixmap(argv[1]);
}
catch( std::bad_alloc &ex )
{
std::cerr << ex.what() << '\n';
return 2;
}

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT);
glutInitWindowPosition(0, 0);
glutCreateWindow("A pixmap loader - by Beloni");

init_gl();

glutDisplayFunc(&render_scene);
glutReshapeFunc(&reshape);
glutKeyboardFunc(&keyb_handler);
glutSpecialFunc(&special_key);
// glutFullScreen();

glutMainLoop();
delete img;
return 0;
}



thanks

Share this post


Link to post
Share on other sites
Quote:
Original post by beloni
Thanks a lot, I got it!
But it has some problems when the window is resized. Can I not allow the user resize the window in GLUT library?

You should be able to. What's the problem you're noticing? I haven't worked much with the GLUT library, so I'm probably not the best to answer, but if you can describe what's going on, I'm sure someone else could give some insight.

Share this post


Link to post
Share on other sites
I am so sorry...
Just not allowing the user to resize the window will solve my problem.
That is the problem: not allow the user to resize the window.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!