C++ OpenGL4:旋转看起来完全错误

C++ OpenGL4:旋转看起来完全错误,c++,opengl,glm-math,C++,Opengl,Glm Math,以下是我正在绘制的四边形的顶点缓冲区信息: static const GLfloat pv_quad[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, }; 此四元框用于在屏幕上绘制二维帧,作为图形用户界面的一部分。我用来做这件事的类是Mage::Interface::Frame。我将不使用头定义,而是提供类的实现,因为它很小。这里有一些测试

以下是我正在绘制的四边形的顶点缓冲区信息:

static const GLfloat pv_quad[] = {
    -1.0f, -1.0f, 0.0f,
     1.0f, -1.0f, 0.0f,
    -1.0f,  1.0f, 0.0f,
     1.0f,  1.0f, 0.0f,
};
此四元框用于在屏幕上绘制二维帧,作为图形用户界面的一部分。我用来做这件事的类是
Mage::Interface::Frame
。我将不使用头定义,而是提供类的实现,因为它很小。这里有一些测试代码,所以忽略着色器是类的一部分这一事实。我知道它不应该在那里

#include <Mage/Root.h>
#include <Mage/Interface/Frame.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>

using Mage::Interface::Frame;

Frame::Frame()  
: width(300), height(200), position(0, 0), color(1.0, 1.0, 1.0), model(1.0), rotation(0) {
    prog.compileFile("Data/Shaders/FrameVertex.glsl", Mage::ShaderType::VERTEX);
    prog.compileFile("Data/Shaders/FrameFragment.glsl", Mage::ShaderType::FRAGMENT);
    prog.link();

    this->calcTransform();
}

void Frame::setSize(int w, int h) {
    this->width = w;
    this->height = h;
    this->calcTransform();
}

void Frame::setColor(int r, int g, int b) {
    this->color = glm::vec3(float(r) / 256, float(g) / 256, float(b) / 256);
}

void Frame::setRotation(float degrees) {
    this->rotation = glm::radians(degrees);
    this->calcTransform();
}

void Frame::calcTransform() {
    this->model = glm::mat4(1.0f); // reset model to origin.
    // 1280 and 720 are the viewport's size. This is only hard coded for tests.
    this->model = glm::scale(this->model, glm::vec3(float(width) / 1280, float(height) / 720, 1.0f));
    this->model = glm::rotate(this->model, this->rotation, glm::vec3(0.0f, 0.0f, 1.0f));
    this->model = glm::translate(this->model, glm::vec3(position.x, position.y, 0.0f));
}

void Frame::draw() {
    Mage::VertexObject obj = ROOT.getRenderWindow()->getVertexBufferObject()->getObject("PrimitiveQuad");

    prog.use();
    prog.setUniform("mvp", this->model);
    prog.setUniform("fColor", this->color);

    glEnableVertexAttribArray(0);
    ROOT.getRenderWindow()->getVertexBufferObject()->bind();
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)obj.begin);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, obj.size);
    glDisableVertexAttribArray(0);
}
当我使用
setRotation(0)
时,生成的四元组确实是400像素宽、200像素高,正如您所期望的那样,正好位于我的屏幕中央

但是,如果我将旋转设置为(90),那么会发生以下情况:

正如你所见,这根本不接近90度转弯。它应该是400px高,200px宽

有人想解释一下这里发生了什么吗


编辑:一些游戏向我表明,问题在于比例,而不是旋转。当我注释出刻度时,旋转似乎是正确的。

参数的角度是弧度,而不是度:

m
:输入矩阵乘以此旋转矩阵

角度
:以弧度表示的旋转角度

:旋转轴,建议[sic]标准化

使用以下命令:

void Frame::setRotation(float degrees) {
    this->rotation = glm::radians( degrees );
    this->calcTransform();
}

角度
参数的单位是弧度,而不是度:

m
:输入矩阵乘以此旋转矩阵

角度
:以弧度表示的旋转角度

:旋转轴,建议[sic]标准化

使用以下命令:

void Frame::setRotation(float degrees) {
    this->rotation = glm::radians( degrees );
    this->calcTransform();
}

角度
参数的单位是弧度,而不是度:

m
:输入矩阵乘以此旋转矩阵

角度
:以弧度表示的旋转角度

:旋转轴,建议[sic]标准化

使用以下命令:

void Frame::setRotation(float degrees) {
    this->rotation = glm::radians( degrees );
    this->calcTransform();
}

角度
参数的单位是弧度,而不是度:

m
:输入矩阵乘以此旋转矩阵

角度
:以弧度表示的旋转角度

:旋转轴,建议[sic]标准化

使用以下命令:

void Frame::setRotation(float degrees) {
    this->rotation = glm::radians( degrees );
    this->calcTransform();
}

我假设这个游戏应该是一个带有2D GUI的3D游戏,尽管这个问题中没有具体说明,尽管不是完全必要,因为我的答案是一样的

使用三维矩阵渲染时,与使用正交视图不同,使用透视视图(考虑视野)时,形状将根据fov弯曲到其位置

因此,我建议您使用一个简单的解决方案,并为2D界面初始化2D查看矩阵(或正交矩阵)。如果您只是在寻找一种简单的方法来在屏幕上渲染2D四边形,freeGLUT(免费图形库实用工具工具包)就在那里。有很多文档可以帮助安装freeglut,因此一旦完成安装,请初始化2D渲染矩阵,然后使用glVertex2i/f或glVertex3i/f渲染四边形,如下所示:

void setView2d()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, *SCREEN_WIDTH, *SCREEN_HEIGHT, 0);
    glMatrixMode( GL_MODELVIEW );
    glDisable(GL_DEPTH_TEST);
    glLoadIdentity();
}

void setView3d()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(70, (GL_FLOAT)*SCREEN_WIDTH / *SCREEN_HEIGHT, 0.1, 100);
    glEnable(GL_DEPTH_TEST);
    glLoadIdentity();
}

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_TEST);

    setView2d(); //Render 2D objects
    glPushMatrix();
    {
        //glTranslatef() and glRotatef() still work for 2D
        //if using rotate, rotate on z axis, like so:
        glRotatef(90, 0, 0, 1);
        glBegin(GL_TRIANGLES);
        {
            glVertex2i(0, 0);
            glVertex2i(100, 0);
            glVertex2i(0, 100);

            /*
                glVertex2i is replacable with glVertex2f, glVertex3i, and glVertex3f
                if using a glVertex3, set the z value to 0
            */
        }
        glEnd();
    }
    glPopMatrix();


    setView3d(); //Render 3D objects
    glPushMatrix();
    {
        //render 3D stuff
    }
    glPopMatrix();

    glutSwapBuffers();
}
我还应该提到,在使用gluOrtho2D时,顶点x、y中使用的坐标基于像素,而不是3D块

希望这有帮助


-尼克

我假设这个游戏应该是一个带有2D图形用户界面的3D游戏,尽管这个问题没有具体说明,尽管不是完全必要,因为我的答案是一样的

使用三维矩阵渲染时,与使用正交视图不同,使用透视视图(考虑视野)时,形状将根据fov弯曲到其位置

因此,我建议您使用一个简单的解决方案,并为2D界面初始化2D查看矩阵(或正交矩阵)。如果您只是在寻找一种简单的方法来在屏幕上渲染2D四边形,freeGLUT(免费图形库实用工具工具包)就在那里。有很多文档可以帮助安装freeglut,因此一旦完成安装,请初始化2D渲染矩阵,然后使用glVertex2i/f或glVertex3i/f渲染四边形,如下所示:

void setView2d()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, *SCREEN_WIDTH, *SCREEN_HEIGHT, 0);
    glMatrixMode( GL_MODELVIEW );
    glDisable(GL_DEPTH_TEST);
    glLoadIdentity();
}

void setView3d()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(70, (GL_FLOAT)*SCREEN_WIDTH / *SCREEN_HEIGHT, 0.1, 100);
    glEnable(GL_DEPTH_TEST);
    glLoadIdentity();
}

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_TEST);

    setView2d(); //Render 2D objects
    glPushMatrix();
    {
        //glTranslatef() and glRotatef() still work for 2D
        //if using rotate, rotate on z axis, like so:
        glRotatef(90, 0, 0, 1);
        glBegin(GL_TRIANGLES);
        {
            glVertex2i(0, 0);
            glVertex2i(100, 0);
            glVertex2i(0, 100);

            /*
                glVertex2i is replacable with glVertex2f, glVertex3i, and glVertex3f
                if using a glVertex3, set the z value to 0
            */
        }
        glEnd();
    }
    glPopMatrix();


    setView3d(); //Render 3D objects
    glPushMatrix();
    {
        //render 3D stuff
    }
    glPopMatrix();

    glutSwapBuffers();
}
我还应该提到,在使用gluOrtho2D时,顶点x、y中使用的坐标基于像素,而不是3D块

希望这有帮助


-尼克

我假设这个游戏应该是一个带有2D图形用户界面的3D游戏,尽管这个问题没有具体说明,尽管不是完全必要,因为我的答案是一样的

使用三维矩阵渲染时,与使用正交视图不同,使用透视视图(考虑视野)时,形状将根据fov弯曲到其位置

因此,我建议您使用一个简单的解决方案,并为2D界面初始化2D查看矩阵(或正交矩阵)。如果您只是在寻找一种简单的方法来在屏幕上渲染2D四边形,freeGLUT(免费图形库实用工具工具包)就在那里。有很多文档可以帮助安装freeglut,因此一旦完成安装,请初始化2D渲染矩阵,然后使用glVertex2i/f或glVertex3i/f渲染四边形,如下所示:

void setView2d()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, *SCREEN_WIDTH, *SCREEN_HEIGHT, 0);
    glMatrixMode( GL_MODELVIEW );
    glDisable(GL_DEPTH_TEST);
    glLoadIdentity();
}

void setView3d()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(70, (GL_FLOAT)*SCREEN_WIDTH / *SCREEN_HEIGHT, 0.1, 100);
    glEnable(GL_DEPTH_TEST);
    glLoadIdentity();
}

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_TEST);

    setView2d(); //Render 2D objects
    glPushMatrix();
    {
        //glTranslatef() and glRotatef() still work for 2D
        //if using rotate, rotate on z axis, like so:
        glRotatef(90, 0, 0, 1);
        glBegin(GL_TRIANGLES);
        {
            glVertex2i(0, 0);
            glVertex2i(100, 0);
            glVertex2i(0, 100);

            /*
                glVertex2i is replacable with glVertex2f, glVertex3i, and glVertex3f
                if using a glVertex3, set the z value to 0
            */
        }
        glEnd();
    }
    glPopMatrix();


    setView3d(); //Render 3D objects
    glPushMatrix();
    {
        //render 3D stuff
    }
    glPopMatrix();

    glutSwapBuffers();
}
我还应该提到,在使用gluOrtho2D时,顶点x、y中使用的坐标基于像素,而不是3D块

希望这有帮助


-尼克

我假设这个游戏应该是一个带有2D图形用户界面的3D游戏,尽管这个问题没有具体说明,尽管不是完全必要,因为我的答案是一样的

使用三维矩阵渲染时,与使用正交视图不同,使用透视视图(考虑视野)时,形状将根据fov弯曲到其位置

因此,我建议您使用一个简单的解决方案,