我有一个代码应该渲染两个球体,每个球体都有不同的纹理,但它不起作用,即使构建成功。它说:变量'textureId'周围的堆栈已损坏。原始代码(仅适用于一个纹理和一个球体)在这里。http://www.dreamincode.net/forums/topic/253361-texture-mapping-and-glutsolidsphere/
编码 :
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <cmath>
#include <GL/glut.h>
using namespace std;
const float SIZE = 10.0f;
#define M_PI (3.14159265)
GLUquadricObj *sphere = NULL;
GLUquadricObj *sphere2 = NULL;
float _angle = 0;
GLuint _textureId[2];
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]);
}
//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);
}
}
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;
};
Image::Image(char* ps, int w, int h) : pixels(ps), width(w), height(h) {
}
Image::~Image() {
}
Image* loadBMP(const char* filename);
Image* loadBMP(const char* filename) {
ifstream infile(filename, ifstream::binary);
infile.seekg(10, std::ios::cur);
int dataOffset = readInt(infile);
//Read the header
int headerSize = readInt(infile);
int width = readInt(infile);
int height = readInt(infile);
//Read the data
int bytesPerRow = ((width * 3 + 3) / 4) * 4 - (width * 3 % 4);
int size = bytesPerRow * height;
char* pixels = new char[size];
infile.seekg(dataOffset, ios_base::beg);
infile.read(pixels, size);
infile.close();
//Get the data into the right format
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)];
}
}
}
delete[] pixels;
return new Image(pixels2, width, height);
}
GLuint loadTextureFromImage(Image* image) {
GLuint textureId;
glGenTextures(2, &textureId); //Make room for our texture
//glBindTexture(GL_TEXTURE_2D, textureId);
//Map the image to the texture
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
image->width, image->height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
image->pixels);
return textureId;
}
void initRendering() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glEnable(GL_COLOR_MATERIAL);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
Image* img = loadBMP("earth.bmp");
_textureId[1] = loadTextureFromImage(img);
delete img;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
sphere = gluNewQuadric();
gluQuadricDrawStyle(sphere, GLU_FILL);
gluQuadricTexture(sphere, GL_TRUE);
gluQuadricNormals(sphere, GLU_SMOOTH);
Image* image = loadBMP("sky.bmp");
_textureId[2] = loadTextureFromImage(image);
delete image;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
sphere2 = gluNewQuadric();
gluQuadricDrawStyle(sphere2, GLU_FILL);
gluQuadricTexture(sphere2, GL_TRUE);
gluQuadricNormals(sphere2, GLU_SMOOTH);
}
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (float)w / (float)h, 1.0, 200.0);
}
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, _textureId[1]);
glTranslatef(0.0f, 0.0f, -20.0f);
glRotatef(_angle, 0, 1, 0);
gluSphere(sphere, 5.0, 20, 20);
glBindTexture(GL_TEXTURE_2D, _textureId[2]);
glTranslatef(0.0f, 0.0f, -30.0f);
glRotatef(_angle, 0, 1, 0);
gluSphere(sphere, 5.0, 20, 20);
glutSwapBuffers();
}
//Called every 25 milliseconds
void update(int value) {
_angle += 1.5f;
if (_angle > 360) {
_angle -= 360;
}
glutPostRedisplay();
glutTimerFunc(25, update, 0);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutCreateWindow("Sphery sky");
initRendering();
glutDisplayFunc(drawScene);
glutReshapeFunc(handleResize);
glutTimerFunc(25, update, 0);
glutMainLoop();
return 0;
}