#include #include #include #include #include unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader); ////// Defines #define BITMAP_ID 0x4D42 // the universal bitmap ID void display(void); void reshape(int width, int height); void keyboard(unsigned char key, int x, int y); void motion(int x, int y); void init(); void idle(); void setUpTexture(); void drawSquare(); unsigned int hTexture; //handle to the texture bool animate = false; bool linear = false; float magnification=1; // window int width = 400; int height = 400; // view position, angles are in degrees float phi=0; float theta=0; float radius=500; using namespace std; main(int argc, char **argv) { // set up window glutInitWindowSize(400, 400); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutCreateWindow("Texture Demo"); // register callback functions glutDisplayFunc(display); glutReshapeFunc(reshape); glutMotionFunc(motion); glutKeyboardFunc(keyboard); // initalize opengl parameters init(); // initialize texture setUpTexture(); // loop until something happens glutMainLoop(); return 0; } void init() { // initialize viewing system glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, 1.0, 1.0, 1000.0); glMatrixMode(GL_MODELVIEW); // initialize background color to black glClearColor(0.0,0.0,1.0,0.0); // enable depth buffering glEnable(GL_DEPTH_TEST); } void setUpTexture() { // read in the bit map // the file names is hard-coded BITMAPINFOHEADER bitmapInfoHeader; // bitmap info header unsigned char* bitmapData=LoadBitmapFile("checkerboard.bmp", &bitmapInfoHeader); // create texture glGenTextures(1,&hTexture); glBindTexture(GL_TEXTURE_2D, hTexture); // the following two commands tell openGL how to interpolate texture // values between the sampled values in your texture bitmap glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // the following two commands tell openGL how to extend the texture // when needed glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // the following tell openGL to use the texture in place of color glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // now give it the texture map glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapData); } void reshape(int newWidth, int newHeight) { width = newWidth; height = newHeight; // preserve aspect ratio if (width < height) glViewport(0,0,width,width); else glViewport(0,0,height,height); } void display() { // clear buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // compute eye position glLoadIdentity(); float eye[3]; float rtheta = theta*3.14159/180.0; float rphi = phi*3.14159/180.0; eye[0] = (float) radius * cos(rtheta) * sin(rphi); eye[1] = (float) radius * sin(rtheta); eye[2] = (float) radius * cos(rtheta) * cos(rphi); // compute up vector // toward is -eye float up[3]; up[0] = -sin(rtheta)*sin(rphi); up[1] = cos(rtheta); up[2] = -sin(rtheta)*cos(rphi); // set viewpoint gluLookAt(eye[0],eye[1],eye[2], 0,0,0,up[0], up[1], up[2]); // draw a fixed square for perspective glPushMatrix(); glTranslatef(0,-100,0); glRotatef(90,1,0,0); drawSquare(); glPopMatrix(); //draw billboarded square glPushMatrix(); // set up rotation for billboard type // the normal should be in the direction of eye float n[3]; float r[3]; float myMatrix[16]; //glMultMatrixf(myMatrix); drawSquare(); glPopMatrix(); // draw to screen glutSwapBuffers(); } void drawSquare() { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, hTexture); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f(-100.0f, -100.0f, 0.0f); glTexCoord2f(magnification, 0.0f); glVertex3f(100.0f, -100.0f, 0.0f); glTexCoord2f(magnification,magnification); glVertex3f(100.0f, 100.0f, 0.0f); glTexCoord2f(0.0f,magnification); glVertex3f(-100.0f, 100.0f,0.0f); glEnd(); glDisable(GL_TEXTURE_2D); } void keyboard(unsigned char key, int mouseX, int mouseY) { switch (key){ case 'r': radius -= 1.0f; if (radius < 0.5) radius = 0.5; break; case 'R': radius += 1.0f; break; case 'a': case 'A': if (animate == true) { glutIdleFunc(NULL); animate=false; } else { glutIdleFunc(idle); animate=true; } break; case 't': case 'T': if (linear == true) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); linear = false; cout << "Nearest interpolation." << endl; } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); linear = true; cout << "Bi-linear interpolation." << endl; } break; case 'm': magnification -=1; if (magnification<1) magnification=1; break; case 'M': magnification +=1; break; case '?': default: break; } glutPostRedisplay(); } void idle() { static int count =0; if (count%1000 == 0) { theta = 3.14159/20.0f; phi +=.001; display(); } count++; } void motion(int x, int y) { static int currX=-1; static int currY=-1; if (animate==true) return; if (currX>0 && abs(x-currX) < width/6 && abs(y-currY) < height/6) { phi -= (double) (x-currX)/ (double) width * 90; theta += (double) (y-currY)/ (double) height * 90; } // restrict theta to be between -75 and 75 if (theta < -60) theta = -60; if (theta > 60) theta = 60; currX = x; currY = y; glutPostRedisplay(); } // LoadBitmapFile // desc: Returns a pointer to the bitmap image of the bitmap specified // by filename. Also returns the bitmap header information. // No support for 8-bit bitmaps. unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader) { FILE *filePtr; // the file pointer BITMAPFILEHEADER bitmapFileHeader; // bitmap file header unsigned char *bitmapImage; // bitmap image data int imageIdx = 0; // image index counter unsigned char tempRGB; // swap variable // open filename in "read binary" mode filePtr = fopen(filename, "rb"); if (filePtr == NULL) return NULL; // read the bitmap file header fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr); // verify that this is a bitmap by checking for the universal bitmap id if (bitmapFileHeader.bfType != BITMAP_ID) { fclose(filePtr); return NULL; } // read the bitmap information header fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr); // move file pointer to beginning of bitmap data fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET); // allocate enough memory for the bitmap image data bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage); // verify memory allocation if (!bitmapImage) { free(bitmapImage); fclose(filePtr); return NULL; } // read in the bitmap image data fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr); // make sure bitmap image data was read if (bitmapImage == NULL) { fclose(filePtr); return NULL; } // swap the R and B values to get RGB since the bitmap color format is in BGR for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3) { tempRGB = bitmapImage[imageIdx]; bitmapImage[imageIdx] = bitmapImage[imageIdx + 2]; bitmapImage[imageIdx + 2] = tempRGB; } // close the file and return the bitmap image data fclose(filePtr); return bitmapImage; }