c++ - OpenGL:使用正交投影进行轨道运动

标签 c++ opengl

我正在使用正交投影对太阳系进行建模并测试地球绕太阳的轨道。

地球的起点在太阳的右边,移动的方向在太阳的左手边。但是地球在太阳前面和太阳后面更远时并没有完全渲染,正如您从下面的 3 张图片中看到的那样:

起点:

enter image description here

下一帧:

enter image description here

最终帧:

enter image description here

有人能解释一下这里究竟发生了什么吗?我认为这是剔除面问题,我试过:

glEnable(GL_CULL_FACES);
glCullFace(GL_FRONT);

它实际上不起作用。

这是我的代码:

// global vars
int width = 1820, height = 960;
#define CENTRE_X static_cast<float>(width/2)
#define CENTRE_Z static_cast<float>(-height/2)
#define EARTH_SIZE glm::vec3(30.0f, 40.0f, 30.0f)
#define SUN_SIZE EARTH_SIZE*3.0f

void renderSun(int i){
    glPushMatrix();
    glLoadIdentity();
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture_ID[0]);
    glUniform1i(texture_Location, 0);
    glm::mat4 Projection = glm::ortho(0.0f, static_cast<float>(width), 0.0f, static_cast<float>(height), 0.0f, 100.0f);
    glm::mat4 View = glm::lookAt(
        glm::vec3(0, 120, 1),
        glm::vec3(0, 0, 0),
        glm::vec3(0, 1, 0)
    );

    /* Animations */
    GLfloat angle = (GLfloat) (i);
    View = glm::translate(View, glm::vec3(static_cast<float>(width/2), 0.0f, static_cast<float>(-height/2)));
    View = glm::scale(View, SUN_SIZE);
    View = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
    /* ******* */
    glm::mat4 Model = glm::mat4(1.0f);
    glm::mat4 MVP = Projection * View * Model;

    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
    glDrawElements(GL_TRIANGLES, numsToDraw, GL_UNSIGNED_INT, NULL);
    glPopMatrix();
}

void renderEarth(int i){
    glPushMatrix();
    glLoadIdentity();
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture_ID[3]);
    glUniform1i(texture_Location, 0);
    glm::mat4 Projection = glm::ortho(0.0f, static_cast<float>(width), 0.0f, static_cast<float>(height), 0.0f, 100.0f);
    glm::mat4 View = glm::lookAt(
        glm::vec3(0, 150, 1),
        glm::vec3(0, 0, 0),
        glm::vec3(0, 1, 0)
    );

    /* Animations */
    GLfloat angle = (GLfloat) (i);
    View = glm::translate(View, glm::vec3(cos(orbitPos)*150, sin(orbitPos)*150, 0.0f));
    View = glm::translate(View, glm::vec3(CENTRE_X, 0.0f, CENTRE_Z));
    View = glm::scale(View, EARTH_SIZE);
    View = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
    /* ******* */
    glm::mat4 Model = glm::mat4(1.0f);
    orbitPos += 0.005;
    glm::mat4 MVP = Projection * View * Model;

    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "mvpMatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
    glDrawElements(GL_TRIANGLES, numsToDraw, GL_UNSIGNED_INT, NULL);
    glPopMatrix();
}

最佳答案

您使用的是不一致的 View 矩阵,您的代码本质上是在旋转地球的 View ,这导致它相对于太阳移动。这是一种非常不寻常的做事方式,可能是您遇到问题的原因。它(大概)导致模型在裁剪空间中发生碰撞,并相互交叉。您应该为两者使用相同的 View 矩阵,并为地球模型修改 Model 矩阵。保持 renderSun 方法不变,您可以通过修改 renderEarth 来做到这一点:

void renderEarth(int i){
//...
/* Animations */
GLfloat angle = (GLfloat) (i);
glm::mat4 M0 = glm::translate(View, glm::vec3(cos(orbitPos)*150, sin(orbitPos)*150, 0.0f));
glm::mat4 M1 = glm::translate(View, glm::vec3(CENTRE_X, 0.0f, CENTRE_Z));
glm::mat4 M2 = glm::scale(View, EARTH_SIZE);
glm::mat4 M3 = glm::rotate(View, angle * 0.5f, glm::vec3(0.0f, 0.0f, 1.0f));
/* ******* */
orbitPos += 0.005;
glm::mat4 MVP = Projection * View * M3 * M2 * M1 * M0;
// ...

关于c++ - OpenGL:使用正交投影进行轨道运动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30127864/

相关文章:

java - ECDSA 使用 BouncyCaSTLe 签名并使用 Crypto++ 验证

c++ - 使用任意值初始化/调整容器大小的建议方法

c++ - 法线贴图出了可怕的错误

opengl - opengl计算着色器中barrier()的语义

c++ - nVidia CUDA 代码不起作用?

c++ - 变量周围的堆栈已损坏,visual studio 2010 问题

c - 作为子进程运行时,OpenGL 窗口不会在 xcode (7.2) 中打开

c++ - 如何将 OpenGL 绘图分成类

c++ - 编译 C++ 程序的 Makefile 问题

c++ - 为什么我的三角形是白色的?