OpenGL 对象不转换为旋转轴

Posted

技术标签:

【中文标题】OpenGL 对象不转换为旋转轴【英文标题】:OpenGL object doesn't translate to rotation axis 【发布时间】:2016-03-14 06:54:50 【问题描述】:

我在 2d 旋转中遇到问题。使用opengl绘制原语GL_LINES绘制三角形。

场景是我想使用ER 键来旋转这个三角形,并通过按up down left right 箭头键沿其旋转轴平移这个三角形。

但是现在三角形是旋转的,但不会沿着它的旋转轴平移。例如,简单来说,当用户按下向上箭头键时,我将对象旋转 90 度角,它不会将该三角形转换为 90 度角,它只是将其平移对象简单上下我被困在这个上面。 这是我的代码:

#include<iostream>
#include <cstdlib>
#include<GL\freeglut.h> 

using namespace std;    
float posX = 0.0f, posY = 0.0f, move_unit = 0.01f, angle = 0.0f;    
void init(void) 

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, -1.0);    


void drawFigure() 
    //LINES Make traingle
    glColor3f(1.0f, 1.0f, 0.0f);    
    glBegin(GL_LINES);    
    glVertex2f(0.1f, 0.0f);
    glVertex2f(-0.1f, 0.0f);
    glVertex2f(0.0f, 0.1f);
    glVertex2f(-0.1f, 0.0f);
    glVertex2f(0.0f, 0.1f);
    glVertex2f(0.1f, 0.0f);
    glColor3f(0.0f, 1.0f, 0.0f);
    glVertex2f(0.0f, 0.1f);
    glVertex2f(0.0f, 0.0f);    
    glEnd();    


void SpecialKeys(int key, int xpos, int ypos) 

    if (key == GLUT_KEY_UP)     
        if (posY < 0.95f) 
            posY += move_unit;
        
    
    else if (key == GLUT_KEY_DOWN) 
        if (posY > -1.0f) 
            posY -= move_unit;
        
    
    else if (key == GLUT_KEY_RIGHT) 
        if (posX < 0.95f) 
            posX += move_unit;
        

    
    else if (key == GLUT_KEY_LEFT) 
        if (posX > -0.95f) 
            posX = posX - move_unit;
        
    
    glutPostRedisplay();



void KeysFun(unsigned char key, int xpos, int ypos) 
    if (key == 'e' || key == 'E') 
        angle++;
    
    else if (key == 'r' || key == 'R') 
        angle--;
    

    glutPostRedisplay();    



void display()     
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glPushMatrix();
    glTranslatef(posX, posY, 0.0f); 
    glRotatef(angle, 0.0f, 0.0f, 1.0f);   
    drawFigure();    
    glPopMatrix();    

    glFlush();    


int main(int argc, char**argv) 
    glutInit(&argc, argv);
    glutInitWindowSize(600, 600);
    glutInitWindowPosition(450, 50);
    glutCreateWindow("C");
    init();
    glutDisplayFunc(display);
    glutSpecialFunc(&SpecialKeys);
    glutKeyboardFunc(&KeysFun);
    glutMainLoop();

    return EXIT_SUCCESS;

【问题讨论】:

使用当前代码,您的对象围绕原点旋转,对吗?变换的常见顺序是 TRS,因此对象围绕自身旋转/缩放。但我不明白你想要达到什么目的以及有什么问题。你能显示一个 GIF 吗? @aslg 我现在编辑我的问题,你明白了 【参考方案1】:

好的,我在阅读时误解了您的代码,但我在我的电脑上复制了它。

正如我在 cmets 中所说的,变换的常见顺序是您当前正在执行的 TRS(平移,然后是旋转,然后是缩放)。这样,您的对象将首先围绕原点缩放,然后围绕自身旋转,然后才被平移到另一个点。

我从您的问题中了解到的是,您希望对象围绕一个点旋转,而不是在屏幕参照中移动(向上总是向上等),而是希望它相对于它的新前向矢量移动,或者旋转轴。然后你必须将旋转放置在之前翻译。

rotate( angle, 0.0f, 0.0f, 1.0f );
translate( posX, posY, 0.0f );

现在对象应该围绕原点旋转并相对于当前旋转轴移动。另外,如果要绕另一个点旋转,还可以在旋转前添加另一个平移。

translate( centerX, centerY, 0.0f );
rotate( angle, 0.0f, 0.0f, 1.0f );
translate( posX, posY, 0.0f );

编辑: 这读作,将对象平移到点(posX, posY),围绕中心点(centerX, centerY) 沿轴(0,0,1) 旋转对象。

编辑2: 如果 centerX 和 centerY 为(0,0),即原点,则如下所示。三角形以(0,0) 为中心开始。

编辑3:

在 cmets 中,您需要更改输入。使用您在原始问题中的转换,即。旋转前的翻译。

// Let's assume we have a vector2 class that stores two floats
vector2 forward;
forward.x = sin( -_angle * DEG_TO_RADIANS );
forward.y = cos( -_angle * DEG_TO_RADIANS );

vector2 right;
right.x = forward.y;
right.y = -forward.x;

// Move one tenth of the length of the forward vector
float velocity = 0.1f;

if ( key == GLUT_KEY_UP ) 
    pos += forward * velocity;

else if ( key == GLUT_KEY_DOWN ) 
    pos -= forward * velocity;

else if ( key == GLUT_KEY_RIGHT ) 
    pos += right * velocity;

else if ( key == GLUT_KEY_UP ) 
    pos -= right * velocity;

当然,可以根据需要更改值。不要忘记三角函数采用弧度值。此外,由于您的对象默认朝上,因此使用角度 0 direction (0,1) 对应于传统数学中的角度 90,因此您必须相应地调整三角函数的参数。

【讨论】:

什么是centerX centerY 我正在使用相同的顺序,现在翻译发生在相同的旋转中。但是当再次从它的新位置旋转这个对象时,它不会从它的原点旋转。 @hamel123 我已经上传了最终结果的 gif。这是您想要实现的目标吗? 是的,但是为什么它从中心旋转我想从它上次停留的确切位置旋转 @hamel123 所以基本上,你希望你的三角形移动。像自上而下游戏中的 2D 角色?

以上是关于OpenGL 对象不转换为旋转轴的主要内容,如果未能解决你的问题,请参考以下文章

四元数旋转opengl

opengl旋转的对象不居中

围绕世界轴OpenGL旋转对象

OpenGL围绕自身而不是原点(0,0,0)旋转对象(一组立方体)

将 OpenGL 4x4 矩阵转换为旋转角度

OpenGL对象不旋转