通过这种方式,每个输出一个obj文件的效果很好。
但是如果我试图同时表示这两个围绕中心太阳旋转的物体,我会得到一个错误。
一开始看起来运行得很好,然后纹理消失了,结果窗口被迫关闭。
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// World Transfrom
glPushMatrix();
glLoadIdentity();
//glTranslatef (0.0f, 0.0f, -300.0f);
///////////////////Drawing//////////////////////////////////////////////////////
// Figure0 Draw
glPushMatrix();
glLoadIdentity();
glColor3f(1.0f, 0.0f, 0.0f);
glutSolidSphere(10, 15, 15);
glPopMatrix();
// Figure1 Draw
glPushMatrix();
glLoadIdentity();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glRotatef(0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(Sphere1_degree, 0.0f, 1.0f, 0.0f);
glTranslatef(70.0f, 0.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f);
_mesh = new Mesh("obj\\Earth_2K.obj", "obj\\Diffuse_2K_Earth.png");
_mesh->drawSolid(_smoothing);
glPopMatrix();
// Figure2 Draw
glPushMatrix();
glLoadIdentity();
glRotatef(-45.0f, 0.0f, 0.0f, 1.0f);
glRotatef(Sphere2_degree, 0.0f, 1.0f, 0.0f);
glTranslatef(60.0f, 0.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
_mesh = new Mesh("obj\\Moon 2K.obj", "obj\\Diffuse_2K_Moon.png");
_mesh->drawSolid(_smoothing);
glPopMatrix();
////////////////////////////////////////////////////////////////////////////////
glPopMatrix();
glutSwapBuffers();
}
这段代码是一个输出和移动obj的函数。那边的_mesh
是我加载obj文件的类对象。DrawSolid
是一个平滑方法的表达式。我觉得那段代码中glPushMatrix
和glPopMatrix
的用法是错误的,但是我不知道怎么修正。为什么会这样呢?
附加说明
此代码是Mesh类
class Mesh
{
public:
vector<Face*> _faces;
vector<Vertex*> _vertices;
Vec3<double> _minBound;
Vec3<double> _maxBound;
vector<Texture*> _textureCoords;
GLuint _textureIndex;
public:
Mesh();
Mesh(char* obj, char* texture) {
open(obj);
loadTexture(texture, _textureIndex);
}
Mesh(char* obj) {
open(obj);
}
~Mesh();
public:
void makeList(void);
void open(char* file);
void loadTexture(char* file, GLuint& texture_index);
void computeNormal(void);
void moveToCenter(double scale = 1.0);
public:
void drawWire(void);
void drawPoint(void);
void drawSolid(bool smoothing);
};
创建Mesh类对象时,它将读取obj文件和纹理文件。
void Mesh::open(char* file)
{
FILE* fp;
char buffer[100] = { 0 };
Vec3<double> pos;
int index[4], tex[4], empty[4];
int id = 0;
_minBound.Set(1000000.0);
_maxBound.Set(-1000000.0);
fopen_s(&fp, file, "r");
while (fscanf(fp, "%s %lf %lf %lf", buffer, &pos[0], &pos[1], &pos[2]) != EOF)
{
// v 0.2 0.3 0.1
// vt
if (buffer[0] == 'v' && buffer[1] == NULL) {
for (int i = 0; i < 3; i++) {
if (_minBound[i] > pos[i]) _minBound[i] = pos[i];
if (_maxBound[i] < pos[i]) _maxBound[i] = pos[i];
}
_vertices.push_back(new Vertex(id, pos));
}
}
// read texture coordinate of vertics
id = 0;
fseek(fp, 0, SEEK_SET);
while (fscanf(fp, "%s %lf %lf", &buffer, &pos[0], &pos[1]) != EOF) {
if (!strcmp(buffer, "vt")) {
_textureCoords.push_back(new Texture(pos[0], 1.0 - pos[1], 0.0));
}
}
// read faces
id = 0;
fseek(fp, 0, SEEK_SET);
while (fscanf(fp, "%s %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d", &buffer, &index[0], &tex[0], &empty[0], &index[1], &tex[1], &empty[1], &index[2], &tex[2], &empty[2], &index[3], &tex[3], &empty[3]) != EOF) {
if (buffer[0] == 'f' && buffer[1] == NULL) {
auto v0 = _vertices[index[0] - 1];
auto v1 = _vertices[index[1] - 1];
auto v2 = _vertices[index[2] - 1];
_faces.push_back(new Face(id++, v0, v1, v2, _vertices[index[3] - 1], tex[0] - 1, tex[1] - 1, tex[2] - 1, tex[3] - 1));
//_faces.push_back(new Face(index++, _vertices[v_index[0] - 1], _vertices[v_index[1] - 1], _vertices[v_index[2] - 1]);
}
}
fclose(fp);
moveToCenter(10.0);
makeList();
computeNormal();
}
这段代码是Mesh类的Open函数。这段代码从obj文件中读取顶点值、纹理元素值和表面值。然后将其传递给每个类对象,并存储在类向量列表中并进行规范化。
void Mesh::drawSolid(bool smoothing) {
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, _textureIndex);
glEnable(GL_LIGHTING);
glEnable(GL_SMOOTH)
for (auto f : _faces) {
// get texture coord
glBegin(GL_POLYGON);
if(!smoothing)
glNormal3f(f->_normal.x(), f->_normal.y(), f->_normal.z());
_textureCoords[f->_texelPos[0]];
for (int i = 0; i < 4; i++) {
auto t = _textureCoords[f->_texelPos[i]];
auto v = f->_vertices[i];
glTexCoord2f((GLfloat)t->x(), (GLfloat)t->y());
glNormal3f(v->_normal.x(), v->_normal.y(), v->_normal.z());
}
glEnd();
}
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
在这里,我平滑了标准化的值。在这段代码中,_texelPos是每个面的texel值的数组。
其他问题
void Mesh::loadTexture(char* file, GLuint& texture_index) {
glGenTextures(1, &texture_index);
FILE* fp;
fopen_s(&fp, file, "rb");
if (!fp) {
printf("ERROR : No %s.\n fail to bind %d\n", file, texture_index);
}
int width, height, channel;
unsigned char *image = stbi_load_from_file(fp, &width, &height, &channel, 4);
fclose(fp);
glBindTexture(GL_TEXTURE_2D, texture_index);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, GL_MODULATE);
}
这是负责设置纹理的代码。
这里,glGenTextures(1, &texture_index);
如果我这样写代码,我可以把glBindTexture(GL_TEXTURE_2D, _textureIndex);
写在main cpp
的RenderScene
函数中吗?
// Figure1 Draw
glPushMatrix();
glLoadIdentity();
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glRotatef(0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(Sphere1_degree, 0.0f, 1.0f, 0.0f);
glTranslatef(70.0f, 0.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, 1);
_mesh1->drawSolid(_smoothing);
glPopMatrix();
1条答案
按热度按时间kg7wmglp1#
你是否创建了网格并在每一帧中加载纹理?可能你没有释放资源并耗尽内存。加载网格和纹理一次,但在每一帧中绘制它们
在渲染循环之前创建一次网格:
但在
RenderScene
中绘制网格: