效果图:
纹理图:
源码:
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <assert.h>
#include <GL/freeglut.h>
using namespace std;
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 &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);
}
char* loadBMP2(const char* filename,int& width,int& height) {
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);
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;
char* pixdata = new char[size];
input.seekg(dataOffset, ios_base::beg);
input.read(pixdata, size);
//Get the data into the right format
char* resdata = 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++) {
resdata[3 * (width * y + x) + c] =
pixdata[bytesPerRow * y + 3 * x + (2 - c)];
}
}
}
input.close();
delete[] pixdata;
return resdata;
}
float yRotate = 50;
GLUquadricObj *sphere = NULL;
GLuint texture;
void init(char* texpath) {
glClearColor(0.0,0.0,0.0,0.0);
glShadeModel(GL_SMOOTH);
int width=0,height=0;
char* imagedata = loadBMP2(texpath,width,height);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(
GL_TEXTURE_2D, // target
0, 3,// level
width, // width
height, // height
0, GL_RGB, GL_UNSIGNED_BYTE, imagedata);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
sphere = gluNewQuadric();
gluQuadricNormals(sphere, GLU_SMOOTH);
gluQuadricDrawStyle(sphere, GLU_FILL);
gluQuadricTexture(sphere, GL_TRUE);
}
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (float)w / (float)h, 0.5, 100.0);
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, texture);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -30.0f);//保证球体可见
glRotatef(yRotate, 0, 1, 0);
glRotatef(-90, 1, 0, 0); //-90
gluSphere(sphere, 5.0, 50, 50);
glutSwapBuffers();
}
void idleFunc (void)
{
yRotate += 0.003;
glutPostRedisplay();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutCreateWindow("World");
init("./volume2/world.bmp");
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutIdleFunc(idleFunc);
glutMainLoop();
return 0;
}