PDA

View Full Version : How to implement Multi texture mapping on models



Scorpio
02-14-2011, 07:07 PM
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
//http://www.videotutorialsrock.com/opengl_tutorial/textures/video.php

#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, &amp;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, &amp;spot_cutoff );
glLightfv( GL_LIGHT1, GL_SPOT_EXPONENT, &amp;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(&amp;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] << 8) |
(unsigned char)bytes[0]);
}

//Reads the next four bytes as an integer, using little-endian form
int readInt(ifstream &amp;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 &amp;input) {
char buffer[2];
input.read(buffer, 2);
return toShort(buffer);
}

//Just like auto_ptr, but for arrays
template<class T>
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<T> &amp;aarray) {
array = aarray.array;
isReleased = aarray.isReleased;
aarray.isReleased = true;
}

~auto_array() {
if (!isReleased &amp;&amp; array != NULL) {
delete[] array;
}
}

T* get() const {
return array;
}

T &amp;operator*() const {
return *array;
}

void operator=(const auto_array<T> &amp;aarray) {
if (!isReleased &amp;&amp; array != NULL) {
delete[] array;
}
array = aarray.array;
isReleased = aarray.isReleased;
aarray.isReleased = true;
}

T* operator->() const {
return array;
}

T* release() {
isReleased = true;
return array;
}

void reset(T* array_ = NULL) {
if (!isReleased &amp;&amp; array != NULL) {
delete[] array;
}
array = array_;
}

T* operator+(int i) {
return array + i;
}

T &amp;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' &amp;&amp; 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<char> pixels(new char[size]);
input.seekg(dataOffset, ios_base::beg);
input.read(pixels.get(), size);

//Get the data into the right format
auto_array<char> pixels2(new char[width * height * 3]);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
for(int c = 0; c < 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&amp;imgrefurl=http://cd.textfiles.com/waycooltoo/GAMES/PICPUZ/&amp;usg=__yHd-9HNeU_ZY99MtM5Bl6bPjOtc=&amp;h=480&amp;w=640&amp;sz=151&amp;hl=en&amp; start=1&amp;zoom=1&amp;tbnid=P3_A38nKfOxLhM:&amp;tbnh=103&amp;tbnw =137&amp;ei=T-1ZTfXXINCCtgfIyuX1Cg&amp;prev=/images%3Fq%3Dtiger%2Bbmp%26um%3D1%26hl%3Den%26sa%3 DN%26biw%3D1280%26bih%3D633%26tbs%3Disch:1&amp;um=1&amp;it bs=1


Regards

mobeen
02-14-2011, 07:25 PM
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

Scorpio
02-14-2011, 07:58 PM
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, &amp;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, &amp;spot_cutoff );
glLightfv( GL_LIGHT1, GL_SPOT_EXPONENT, &amp;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();

mobeen
02-14-2011, 08:55 PM
Chck this tutorial http://www.morrowland.com/apron/article/gl/lightmap/index.php. (http://www.morrowland.com/apron/article/gl/lightmap/index.php)

Scorpio
02-15-2011, 11:49 PM
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. :(

Alfonse Reinheart
02-16-2011, 12:28 AM
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.