在OpenGl中对象不能正确移动的问题

js81xvg6  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(122)

通过这种方式,每个输出一个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是一个平滑方法的表达式。我觉得那段代码中glPushMatrixglPopMatrix的用法是错误的,但是我不知道怎么修正。为什么会这样呢?

附加说明

此代码是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 cppRenderScene函数中吗?

// 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();
kg7wmglp

kg7wmglp1#

你是否创建了网格并在每一帧中加载纹理?可能你没有释放资源并耗尽内存。加载网格和纹理一次,但在每一帧中绘制它们
在渲染循环之前创建一次网格:

_mesh1 = new Mesh("obj\\Earth_2K.obj", "obj\\Diffuse_2K_Earth.png");
_mesh2 = new Mesh("obj\\Moon 2K.obj", "obj\\Diffuse_2K_Moon.png");

但在RenderScene中绘制网格:

void RenderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // [...]

    _mesh1->drawSolid(_smoothing);

    // [...]

    _mesh2->drawSolid(_smoothing);

    // [...]
}

相关问题