How to implement Multi texture mapping on models

Hi ,
I am able to create a model with a single texture mapping image. via using imageloader.
But I am not able to use multiple images. I am using bmp file extension and image loader.

Please help me…

The below is my code.
// Main cpp file

// FOr compiling this code I used code of
//OpenGL Video Tutorial - Textures

#include<iostream>
#include<stdlib.h>
#include <glut.h>
#include<math.h>
#include “imageloader.h”

float value = 0.;

GLfloat white_light_diff[] = { 2,0,0,1 };
GLfloat white_light_amb[] = { 1,2,2, 2 };
GLfloat light_posn[] = { -0.5,10,-0.25, 1 };

GLfloat spot_posn[] = { 0.5, 5, 2, 1 };
GLfloat spot_direcn[] = { .2, -1., 2.15 };
GLfloat spot_spec[] = { 0.6, 0.6, 0.6, 1. };

float spot_cutoff = 60.;
float spot_expo = 0.0;

// For Pyramid sphere balls of Red purple color
GLfloat mat_diffuse0[] = { 0.4, 0.2,0.1, 1.0 };
GLfloat mat_ambient0[] = { 0.2, 0.1,0.1 , 1.0 };

// for Square Grids blue color
GLfloat mat_diffuse1[] = { 0.1, 0.0, 2, 1.0 };
GLfloat mat_specular1[] = { 0.1, 0., 1., 1.0 };
GLfloat mat_ambient1[] = { 0.1, 0., 0.3, 1.0 };

// for Ball primitives extruded ones
GLfloat mat_diffuse3[] = { 0.3, 0.4, 0.1, 1.0 };
GLfloat mat_specular3[] = { 0.1, 0.4, 0.1, 1.0 };
GLfloat mat_ambient3[] = { 0.1, 0.2, 0.1, 1.0 };

// for Square primitives extruded ones
GLfloat mat_diffuse2[] = { 0.5, 0.1, 0.2, 1.0 };
GLfloat mat_ambient2[] = { 0.3, 0.1, 0.2, 1.0 };

bool animate = false;

// for texturing stuff

//Makes the image into a texture, and returns the id of the texture
GLuint loadTexture(Image* image) {
GLuint textureId;
glGenTextures(1, &textureId); //Make room for our texture
glBindTexture(GL_TEXTURE_2D, textureId); //Tell OpenGL which texture to edit
//Map the image to the texture
glTexImage2D(GL_TEXTURE_2D, //Always GL_TEXTURE_2D
0, //0 for now
GL_RGB, //Format OpenGL uses for image
image->width, image->height, //Width and height
0, //The border of the image
GL_RGB, //GL_RGB, because pixels are stored in RGB format
GL_UNSIGNED_BYTE, //GL_UNSIGNED_BYTE, because pixels are stored
//as unsigned numbers
image->pixels); //The actual pixel data
return textureId; //Returns the id of the texture
}

GLuint _textureId; //The id of the texture

//…

void init(void)
{
glClearColor (1.0, 1.0, 1.0, 0.0);
glShadeModel (GL_SMOOTH);

glClearColor( .46, .53, .6, 0. );

// Enable depth testing
glEnable( GL_DEPTH_TEST );

// We keep our light within the display func so that we can influence its properties
// Create the first white light (made largely ambient and diffuse (source at infinity)
glLightfv( GL_LIGHT0, GL_POSITION, light_posn );
glLightfv( GL_LIGHT0, GL_DIFFUSE, white_light_diff );
glLightfv( GL_LIGHT0, GL_AMBIENT, white_light_amb );

//// Second light is a white spotlight
glLightfv( GL_LIGHT1, GL_DIFFUSE, white_light_diff );
glLightfv( GL_LIGHT1, GL_SPECULAR, spot_spec);
glLightfv( GL_LIGHT1, GL_POSITION, spot_posn );
glLightfv( GL_LIGHT1, GL_SPOT_DIRECTION, spot_direcn );
glLightfv( GL_LIGHT1, GL_SPOT_CUTOFF, &spot_cutoff );
glLightfv( GL_LIGHT1, GL_SPOT_EXPONENT, &spot_expo );

glEnable( GL_LIGHT0 );
glEnable( GL_LIGHT1 );

// for texture stuff

Image* image = loadBMP("tiger.bmp");

_textureId = loadTexture(image);

delete image;

	}

void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);

glColor3f (1,1,1);

gluLookAt(3,-2,1.3,1,-0.4,0.6,0,1,0);	
glScalef (1,1,1); /* modeling transformation */
glDisable( GL_LIGHTING );

glDisable( GL_LIGHTING );	

glBegin(GL_QUADS); // X-Z PLane
glColor4f(1,1,1,1);
glVertex3f(0,-0.5, 0.0);
glVertex3f(0,-0.5,-7.0);
glVertex3f(11,-0.5,-7.0);
glVertex3f(11, -0.5, 0.0);
glEnd();

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureId);

// trial for texture working

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glNormal3f(0.0, 1.0f, 0.0f);

glBegin(GL_QUADS);// -Z-X PLane

glColor3f(1,1,0);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-11,-0.5, -7.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-11, -0.5, 0.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(0,-0.5, 0.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(0,-0.5,-7.0);
glEnd();

glDisable(GL_TEXTURE_2D);

glDisable(GL_TEXTURE_2D);

glBegin(GL_QUADS); // XZ PLane
glColor3f(0,1,0);
glVertex3f(0,-0.5, 0.0);
glVertex3f(0,-0.5,7.0);
glVertex3f(11,-0.5,7.0);
glVertex3f(11, -0.5, 0.0);
glEnd();

glBegin(GL_QUADS);// Z-X PLane
glColor4f(0.98,0.85,.12,1);
glVertex3f(-11,-0.5, 7.0);
glVertex3f(-11, -0.5, 0.0);
glVertex3f(0,-0.5, 0.0);
glVertex3f(0,-0.5,7.0);
glEnd();

glDisable( GL_LIGHTING );

glPushMatrix();
	glTranslatef (2, 5, 0.0);
	glColor3f (1,0,0.0);
	glutSolidCube(4);
	
glPopMatrix();


glutSwapBuffers();

glFlush ();

}

void reshape (int w, int h)
{
glViewport (0,0, (GLsizei) w, (GLsizei) h);

glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(-14, 14, -14,14, 16, -14);
glMatrixMode (GL_MODELVIEW);
}

using namespace std;

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);

glutReshapeFunc(reshape);

glutMainLoop();

return 0;

}

// imageloader.cpp file

#include <assert.h>
#include <fstream>

#include “imageloader.h”

using namespace std;

Image::Image(char* ps, int w, int h) : pixels(ps), width(w), height(h) {

}

Image::~Image() {
delete[] pixels;
}

namespace {
//Converts a four-character array to an integer, using little-endian form
int toInt(const char* bytes) {
return (int)(((unsigned char)bytes[3] << 24) |
((unsigned char)bytes[2] << 16) |
((unsigned char)bytes[1] << 8) |
(unsigned char)bytes[0]);
}

//Converts a two-character array to a short, using little-endian form
short toShort(const char* bytes) {
	return (short)(((unsigned char)bytes[1] &lt;&lt; 8) |
				   (unsigned char)bytes[0]);
}

//Reads the next four bytes as an integer, using little-endian form
int readInt(ifstream &input) {
	char buffer[4];
	input.read(buffer, 4);
	return toInt(buffer);
}

//Reads the next two bytes as a short, using little-endian form
short readShort(ifstream &input) {
	char buffer[2];
	input.read(buffer, 2);
	return toShort(buffer);
}

//Just like auto_ptr, but for arrays
template&lt;class T&gt;
class auto_array {
	private:
		T* array;
		mutable bool isReleased;
	public:
		explicit auto_array(T* array_ = NULL) :
			array(array_), isReleased(false) {
		}
		
		auto_array(const auto_array&lt;T&gt; &aarray) {
			array = aarray.array;
			isReleased = aarray.isReleased;
			aarray.isReleased = true;
		}
		
		~auto_array() {
			if (!isReleased && array != NULL) {
				delete[] array;
			}
		}
		
		T* get() const {
			return array;
		}
		
		T &operator*() const {
			return *array;
		}
		
		void operator=(const auto_array&lt;T&gt; &aarray) {
			if (!isReleased && array != NULL) {
				delete[] array;
			}
			array = aarray.array;
			isReleased = aarray.isReleased;
			aarray.isReleased = true;
		}
		
		T* operator-&gt;() const {
			return array;
		}
		
		T* release() {
			isReleased = true;
			return array;
		}
		
		void reset(T* array_ = NULL) {
			if (!isReleased && array != NULL) {
				delete[] array;
			}
			array = array_;
		}
		
		T* operator+(int i) {
			return array + i;
		}
		
		T &operator[](int i) {
			return array[i];
		}
};

}

Image* loadBMP(const char* filename) {
ifstream input;
input.open(filename, ifstream::binary);
assert(!input.fail() || !“Could not find file”);
char buffer[2];
input.read(buffer, 2);
assert(buffer[0] == ‘B’ && buffer[1] == ‘M’ || !“Not a bitmap file”);
input.ignore(8);
int dataOffset = readInt(input);

//Read the header
int headerSize = readInt(input);
int width;
int height;
switch(headerSize) {
	case 40:
		//V3
		width = readInt(input);
		height = readInt(input);
		input.ignore(2);
		assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
		assert(readShort(input) == 0 || !"Image is compressed");
		break;
	case 12:
		//OS/2 V1
		width = readShort(input);
		height = readShort(input);
		input.ignore(2);
		assert(readShort(input) == 24 || !"Image is not 24 bits per pixel");
		break;
	case 64:
		//OS/2 V2
		assert(!"Can't load OS/2 V2 bitmaps");
		break;
	case 108:
		//Windows V4
		assert(!"Can't load Windows V4 bitmaps");
		break;
	case 124:
		//Windows V5
		assert(!"Can't load Windows V5 bitmaps");
		break;
	default:
		assert(!"Unknown bitmap format");
}

//Read the data
int bytesPerRow = ((width * 3 + 3) / 4) * 4 - (width * 3 % 4);
int size = bytesPerRow * height;
auto_array&lt;char&gt; pixels(new char[size]);
input.seekg(dataOffset, ios_base::beg);
input.read(pixels.get(), size);

//Get the data into the right format
auto_array&lt;char&gt; pixels2(new char[width * height * 3]);
for(int y = 0; y &lt; height; y++) {
	for(int x = 0; x &lt; width; x++) {
		for(int c = 0; c &lt; 3; c++) {
			pixels2[3 * (width * y + x) + c] =
				pixels[bytesPerRow * y + 3 * x + (2 - c)];
		}
	}
}

input.close();
return new Image(pixels2.release(), width, height);

}

// Image loader.h header file

#ifndef IMAGE_LOADER_H_INCLUDED
#define IMAGE_LOADER_H_INCLUDED

//Represents an image
class Image {
public:
Image(char* ps, int w, int h);
~Image();

	/* An array of the form (R1, G1, B1, R2, G2, B2, ...) indicating the
	 * color of each pixel in image.  Color components range from 0 to 255.
	 * The array starts the bottom-left pixel, then moves right to the end
	 * of the row, then moves up to the next column, and so on.  This is the
	 * format in which OpenGL likes images.
	 */
	char* pixels;
	int width;
	int height;

};

//Reads a bitmap image from file.
Image* loadBMP(const char* filename);

#endif

// the below is the link of bmp image which i have used for this model

http://www.google.com/imgres?imgurl=http://cd.textfiles.com/waycooltoo/GAMES/PICPUZ/TIGER.BMP&imgrefurl=http://cd.textfiles.com/waycooltoo/GAMES/PICPUZ/&usg=__yHd-9HNeU_ZY99MtM5Bl6bPjOtc=&h=480&w=640&sz=151&hl=en&start=1&zoom=1&tbnid=P3_A38nKfOxLhM:&tbnh=103&tbnw=137&ei=T-1ZTfXXINCCtgfIyuX1Cg&prev=/images%3Fq%3Dtiger%2Bbmp%26um%3D1%26hl%3Den%26sa%3DN%26biw%3D1280%26bih%3D633%26tbs%3Disch:1&um=1&itbs=1

Regards

Please enclose the code snippet in the code tage. You are not even loading multiple images where are u loading them? For multitexturing check this http://www.lighthouse3d.com/opengl/glsl/index.php?textureMulti

Hi, Thanks for replying if you modify this in the above code … The same image will be displayed all over.
Can you please tell me the syntax of using different images I mean the multi- texturing stuff… how to do it.
The link which you forwarded is quite advance I think for SuperBible 5 edition. shading things are very advance. and I want be able to understand , I am using SuperBible 3 rd edition.

I am extremely sorry I am not able to find code snippets it looks very weird to understand the code sequence. and even file manager does not permits to upload the cpp and project files.

I request you to please only forward me the multi texture coding sequence like for single image we use:

//Makes the image into a texture, and returns the id of the texture
GLuint loadTexture(Image* image) {
GLuint textureId;
glGenTextures(1, &textureId); //Make room for our texture
glBindTexture(GL_TEXTURE_2D, textureId); //Tell OpenGL which texture to edit
//Map the image to the texture
glTexImage2D(GL_TEXTURE_2D, //Always GL_TEXTURE_2D
0, //0 for now
GL_RGB, //Format OpenGL uses for image
image->width, image->height, //Width and height
0, //The border of the image
GL_RGB, //GL_RGB, because pixels are stored in RGB format
GL_UNSIGNED_BYTE, //GL_UNSIGNED_BYTE, because pixels are stored
//as unsigned numbers

void init(void)
{
glClearColor (1.0, 1.0, 1.0, 0.0);
glShadeModel (GL_SMOOTH);

glClearColor( .46, .53, .6, 0. );

// Enable depth testing
glEnable( GL_DEPTH_TEST );

// We keep our light within the display func so that we can influence its properties
// Create the first white light (made largely ambient and diffuse (source at infinity)
glLightfv( GL_LIGHT0, GL_POSITION, light_posn );
glLightfv( GL_LIGHT0, GL_DIFFUSE, white_light_diff );
glLightfv( GL_LIGHT0, GL_AMBIENT, white_light_amb );

//// Second light is a white spotlight
glLightfv( GL_LIGHT1, GL_DIFFUSE, white_light_diff );
glLightfv( GL_LIGHT1, GL_SPECULAR, spot_spec);
glLightfv( GL_LIGHT1, GL_POSITION, spot_posn );
glLightfv( GL_LIGHT1, GL_SPOT_DIRECTION, spot_direcn );
glLightfv( GL_LIGHT1, GL_SPOT_CUTOFF, &spot_cutoff );
glLightfv( GL_LIGHT1, GL_SPOT_EXPONENT, &spot_expo );

glEnable( GL_LIGHT0 );
glEnable( GL_LIGHT1 );

// for texture stuff

Image* image = loadBMP(“tiger.bmp”);

_textureId = loadTexture(image);

delete image;

}

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureId);

// trial for texture working

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glNormal3f(0.0, 1.0f, 0.0f);

glBegin(GL_QUADS);// -Z-X PLane

glColor3f(1,1,0);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-11,-0.5, -7.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-11, -0.5, 0.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(0,-0.5, 0.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(0,-0.5,-7.0);
glEnd();

glDisable(GL_TEXTURE_2D);

// Now here how should I call the second image and what changes need to made.

glBegin(GL_QUADS); // XZ PLane
glColor3f(0,1,0);
glVertex3f(0,-0.5, 0.0);
glVertex3f(0,-0.5,7.0);
glVertex3f(11,-0.5,7.0);
glVertex3f(11, -0.5, 0.0);

glEnd()

image->pixels); //The actual pixel data
return textureId; //Returns the id of the texture
}

GLuint _textureId; //The id of the texture

glBegin(GL_QUADS);// -Z-X PLane

glColor3f(1,1,0);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-11,-0.5, -7.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-11, -0.5, 0.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(0,-0.5, 0.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(0,-0.5,-7.0);
glEnd();

glDisable(GL_TEXTURE_2D);

glDisable(GL_TEXTURE_2D);

glBegin(GL_QUADS); // XZ PLane
glColor3f(0,1,0);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(0,-0.5, 0.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(0,-0.5,7.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(11,-0.5,7.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(11, -0.5, 0.0);
glEnd();

glBegin(GL_QUADS);// Z-X PLane
glColor4f(0.98,0.85,.12,1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-11,-0.5, 7.0);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-11, -0.5, 0.0);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(0,-0.5, 0.0);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(0,-0.5,7.0);
glEnd();

Chck this tutorial http://www.morrowland.com/apron/article/gl/lightmap/index.php.

That website is also not useful to me.
I am not able to implement multi-texture mapping concept!
NEHE is also waste most of that site program don’t run on vc++2008 and 2010 .
I request someone to provide a sample code in which they have used multi-texture concept . Any basic thing will work because I want to understand the basic concept.
Also I request OpenGL forum to provide a way to upload the complete files so that someone can help the beginners.
We can not upload images. cpp files . and there is limit of uploading only 3 files. :frowning:

NEHE is also waste most of that site program don’t run on vc++2008 and 2010 .

While that’s true (thanks to GLaux dependencies), the code itself is perfectly legible. And the actual text of the tutorials is fine. So if you’re interested in understanding fixed-function multitexture, you can still use that.

Also I request OpenGL forum to provide a way to upload the complete files so that someone can help the beginners.
We can not upload images. cpp files . and there is limit of uploading only 3 files.

If you need to upload an entire project in order for people to help you, there are hosting sites for that kind of thing. A forum isn’t the best place for it.