opengl 2D基本变换组合

vqlkdk9b  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(133)

我在OpenGL中遇到了一个二维变换问题。我的程序在屏幕上画出两个字母,然后按下指定的键,字母必须上移(GLUT_KEY_UP)向下(GLUT_KEY_DOWN)向左(图形查找表_键_左)右侧(GLUT_KEY_RIGHT)并顺时针旋转(GLUT_KEY_HOME)和逆时针方向(图形查询表关键字结束)。(在键GLUT_KEY_PAGE_UP和GLUT_KEY_PAGE_DOWN上,两个字母同时围绕它们自己的中心以相反的方向旋转,例如,在GLUT_KEY_PAGE_UP之后按下GLUT_KEY_UP,以正确的方向移动两个字母)。
使用GLUT_KEY_HOME或GLUT_KEY_END旋转对象后,我无法使字母进行正确的移动(上、下、左或右):

case GLUT_KEY_HOME: //rotate clockwise around the center of the model
    glMatrixMode(GL_MODELVIEW);
    setRotationMatrix(-angle, modelSizeX, modelSizeY);
    glMultMatrixf(rotationMatrix);  // multiply current Modelview Matrix by rotate-and-translate matrix
    display();
    break;

“设置”旋转矩阵的函数将Angular 和旋转点插入单位矩阵[4x 4]:

void setRotationMatrix(float theta, float x0, float y0)
{
    theta = theta * (2 * acos(0.0)) / 180; // convert theta from degrees to radian
    rotationMatrix[0] = cos(theta);
    rotationMatrix[1] = sin(theta);
    rotationMatrix[4] = -sin(theta);
    rotationMatrix[5] = cos(theta);
    rotationMatrix[12] = ((x0 * 0.5f) * (1 - cos(theta)) + (y0 * 0.5f) * sin(theta));
    rotationMatrix[13] = ((y0 * 0.5f) * (1 - cos(theta)) - (x0 * 0.5f) * sin(theta));
}

对象旋转后,如果我按KEY_UP键,它们不会“向上”移动(沿x轴的法线方向),而是沿旋转后对象水平面的法线方向移动(略微向侧面移动)。

case GLUT_KEY_UP:
    glMatrixMode(GL_MODELVIEW);
    glTranslated(0, delta, 0);
    display();
    break;

我如何使它直线移动到“北”,意思是,不是对象的“北”,而是我的坐标系的“北”?


# include <Windows.h>

# include <GL/glut.h>

# include <vector>

# include <fstream>

# include <cmath>

using namespace std;

# define EscKey 27

# define PlusKey 43

# define MinusKey 45

struct Point
{
    int x, y;
};

double pi = 2 * acos(0.0);
void reshape(int w, int h);
void display();
void drawInitials();
void processNormalKeys(unsigned char key, int x, int y);
void processSpecialKeys(int key, int x, int y);
void setRotationMatrix(float theta, float x0, float y0);
void readFromFile();
void lineto(Point p);
void moveto(Point p);
void drawM();
void drawJ();
vector <Point> point;
vector <int>   code;
Point currentPoint;
int modelSizeX = 202; int modelSizeY = 89;
int letterMSizeX = 107; int letterJSizeX = 78;
int   delta = 5;        // movement size
float zoomRate = 0.1;   // scale-and-translate rate: 0.1 = resize by 10%
float angle = 1, rotaterR = 1 * pi / 180, rotater,  angleCount = 0.0; // saved rotation angle
GLfloat modelviewStateMatrix[16];

int windowSizeX, windowSizeY;

boolean separate = false;

float rotationMatrix[16] = { 1.0f, 0.0f,  0.0f,  0.0f,
                             0.0f, 1.0f,  0.0f,  0.0f,
                             0.0f, 0.0f,  1.0f,  0.0f,
                             0.0f, 0.0f,  0.0f,  1.0f };

float plusKeyMatrix[16] = { 1.0f + zoomRate, 0.0f,  0.0f,  0.0f,
                             0.0f, 1.0f + zoomRate,  0.0f,  0.0f,
                             0.0f, 0.0f,  1.0f,  0.0f,
                           -(modelSizeX * zoomRate * 0.5f), -(modelSizeY * zoomRate * 0.5f),  0.0f,  1.0f };

float minusKeyMatrix[16] = { 1.0f - zoomRate, 0.0f,  0.0f,  0.0f,
                             0.0f, 1.0f - zoomRate,  0.0f,  0.0f,
                             0.0f, 0.0f,  1.0f,  0.0f,
                             modelSizeX * zoomRate * 0.5f,    modelSizeY * zoomRate * 0.5f,  0.0f,  1.0f };

void readFromFile()
{
    fstream f("initials_points_2.txt", ios::in);
    int pointNumber;
    Point p;
    f >> pointNumber;
    for (int i = 0; i < pointNumber;i++)
    {
        f >> p.x >> p.y;
        point.push_back(p);
    }
    int movesNumber, m;
    f >> movesNumber;
    for (int i = 0; i < movesNumber; i++)
    {
        f >> m; code.push_back(m);
    }
    f.close();
}
void moveto(Point p)
{
    currentPoint.x = p.x; currentPoint.y = p.y;
}
void lineto(Point p)
{
    glBegin(GL_LINES);
    glVertex2i(currentPoint.x, currentPoint.y);
    glVertex2i(p.x, p.y);
    glEnd();
    currentPoint.x = p.x; currentPoint.y = p.y;
}

void setRotationMatrix(float theta, float x0, float y0)
{
    theta = theta * (2 * acos(0.0)) / 180; // convert theta from degrees to radian
    rotationMatrix[0] = cos(theta);
    rotationMatrix[1] = sin(theta);
    rotationMatrix[4] = -sin(theta);
    rotationMatrix[5] = cos(theta);
    rotationMatrix[12] = ((x0 * 0.5f) * (1 - cos(theta)) + (y0 * 0.5f) * sin(theta));
    rotationMatrix[13] = ((y0 * 0.5f) * (1 - cos(theta)) - (x0 * 0.5f) * sin(theta));
}

void drawM()
{
    int i = 1;
    moveto(point[0]);
    while (code[i] > 0 && i < code.size())
    {
        lineto(point[code[i] - 1]);
        i++;
    }

    glBegin(GL_LINES);
    glVertex3f(0.0, 0.0, 0.0);
    glVertex3f(letterMSizeX, 0.0, 0.0);
    glVertex3f(letterMSizeX, 0.0, 0.0);
    glVertex3f(letterMSizeX, modelSizeY, 0.0);
    glVertex3f(letterMSizeX, modelSizeY, 0.0);
    glVertex3f(0.0, modelSizeY, 0.0);
    glVertex3f(0.0, modelSizeY, 0.0);
    glVertex3f(0.0, 0.0, 0.0);
    glEnd();

    glColor3f(0.0, 1.0, 0.0);
    glBegin(GL_LINES);
    glVertex2i(0, 0); glVertex2i(letterMSizeX, modelSizeY);
    glVertex2i(letterMSizeX, 0); glVertex2i(0, modelSizeY);
    glEnd();
}
void drawJ()
{
    glColor3f(1.0, 0.0, 0.0);
    int i = 14;
    moveto(point[-1 * (code[i]) - 1]);
    i++;
    while (i < code.size())
    {
        lineto(point[code[i] - 1]);
        i++;
    }

    glBegin(GL_LINES);
    glVertex3f((modelSizeX - letterJSizeX), 0.0, 0.0);
    glVertex3f((modelSizeX - letterJSizeX), modelSizeY, 0.0);
    glVertex3f((modelSizeX - letterJSizeX), modelSizeY, 0.0);
    glVertex3f(modelSizeX, modelSizeY, 0.0);
    glVertex3f(modelSizeX, modelSizeY, 0.0);
    glVertex3f(modelSizeX, 0.0, 0.0);
    glVertex3f(modelSizeX, 0.0, 0.0);
    glVertex3f((modelSizeX - letterJSizeX), 0.0, 0.0);
    glEnd();

    glColor3f(0.0, 1.0, 0.0);
    glBegin(GL_LINES);
    glVertex2i(letterMSizeX + 17, 0); glVertex2i(modelSizeX, modelSizeY);
    glVertex2i(letterMSizeX + 17, modelSizeY); glVertex2i(modelSizeX, 0);
    glEnd();

}

void drawInitials()
{
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    setRotationMatrix(-rotater, letterMSizeX, modelSizeY);
    glMultMatrixf(rotationMatrix);  // multiply current Modelview Matrix by rotate-and-translate matrix
    drawM();
    glTranslatef(-letterMSizeX * 0.5, -modelSizeY * 0.5, 0);
    glPopMatrix();

    glPushMatrix();
    glTranslatef((modelSizeX - letterJSizeX), 0, 0);
    setRotationMatrix(rotater, letterJSizeX, modelSizeY);
    glMultMatrixf(rotationMatrix);  // multiply current Modelview Matrix by rotate-and-translate matrix
    glTranslatef(-(modelSizeX - letterJSizeX), 0, 0);
    drawJ();
    glPopMatrix();
}

void processNormalKeys(unsigned char key, int x, int y)
{
    switch (key)
    {
    case EscKey:
        exit(0);
        break;
    case PlusKey:                      // "zoom in" 
        glMatrixMode(GL_MODELVIEW);
        glMultMatrixf(plusKeyMatrix);  // multiply current Modelview Matrix by scale-and-translate matrix   
        display();
        break;
    case MinusKey:                     // "zoom out"    
        glMatrixMode(GL_MODELVIEW);
        glMultMatrixf(minusKeyMatrix); // multiply current Modelview Matrix by scale-and-translate matrix
        display();
        break;
    }
}

void processSpecialKeys(int key, int x, int y) {
    switch (key) {
    case GLUT_KEY_UP:
        glMatrixMode(GL_MODELVIEW);
        glTranslated(0, delta, 0);
        display();
        break;
    case GLUT_KEY_DOWN:
        glMatrixMode(GL_MODELVIEW);
        glTranslated(0, -delta, 0);
        display();
        break;
    case GLUT_KEY_LEFT:
        glMatrixMode(GL_MODELVIEW);
        glTranslated(-delta, 0, 0);
        display();
        break;
    case GLUT_KEY_RIGHT:
        glMatrixMode(GL_MODELVIEW);
        glTranslated(delta, 0, 0);
        display();
        break;
    case GLUT_KEY_HOME: //rotate clockwise around the center of the model
        glMatrixMode(GL_MODELVIEW);
        setRotationMatrix(-angle, modelSizeX, modelSizeY);
        glMultMatrixf(rotationMatrix);  // multiply current Modelview Matrix by rotate-and-translate matrix
        display();
        break;
    case GLUT_KEY_END: //rotate counterclockwise around the center of the model
        glMatrixMode(GL_MODELVIEW);
        setRotationMatrix(angle, modelSizeX, modelSizeY);
        glMultMatrixf(rotationMatrix);  // multiply current Modelview Matrix by rotate-and-translate matrix
        display();
        break;
    case GLUT_KEY_PAGE_UP:
        rotater -= rotaterR;
        if (rotater <= -2 * pi)
            rotater += 2 * pi;
        display();
        break;
    case GLUT_KEY_PAGE_DOWN:
        rotater += rotaterR;
        if (rotater >= 2 * pi)
            rotater -= 2 * pi;
        display();
        break;
    }
}

int main(int argc, char* argv[])
{
    currentPoint.x = 0; currentPoint.y = 0;
    readFromFile();

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(800, 600);
    glutInitWindowPosition(100, 150);
    glutCreateWindow("OpenGL lab");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    glutKeyboardFunc(processNormalKeys);
    glutSpecialFunc(processSpecialKeys);

    glutMainLoop();
    return 0;
}
void reshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    windowSizeX = w;
    windowSizeY = h;
    gluOrtho2D(-modelSizeX, modelSizeX * 2, -modelSizeY, modelSizeY * 2); // World size
}
void display()
{
    glClearColor(1, 1, 1, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glColor3f(0.0, 0.0, 1.0);
    glBegin(GL_LINES);
    glVertex2i(-windowSizeX, 0); glVertex2i(windowSizeX, 0);
    glVertex2i(0, -windowSizeY); glVertex2i(0, windowSizeY);
    glEnd();
    glPopMatrix();

    glColor3d(1, 0, 0);
    drawInitials();

    glPointSize(5);
    glBegin(GL_POINTS);
    glVertex3f(modelSizeX * 0.5, modelSizeY * 0.5, 0.0);
    glVertex3f(letterMSizeX * 0.5, modelSizeY * 0.5, 0.0);
    glVertex3f(letterJSizeX * 0.5 + letterMSizeX + 17, modelSizeY * 0.5, 0.0);
    glEnd();

    glFlush();
}

顶点文件:initials_points_2.txt
我正想:

  • 使用glPushMatrix()/glPopMatrix()封装_HOME/_END旋转
  • 通过将MODELVIEW矩阵乘以(-Angular ,相同点),在绘制对象后恢复旋转
  • 我尝试删除glMultMatrix()并使用glTranslate()、glRotate()

没有一个像我想的那样奏效

0mkxixxg

0mkxixxg1#

请考虑以下步骤:

  • 首先,在对象坐标系统上旋转对象。
  • 接下来,将对象放置在您考虑方向{上、下、左、右}的空间(坐标系)中。

即第一次旋转时,中心必须是物体坐标系中的值,例如物体坐标系通常定义为原点等于物体的中心,此时旋转中心为(0,0,0)。

glPushMatrix();
//2nd step : Place the object
glTranslatef( ... );
//1st step : rotate the object
glRotatef( ... );
//object draw code
//(all vertex value is in the object coordinate system)
glPopMatrix();
7qhs6swi

7qhs6swi2#

我发现我做错了什么:按钮GLUT_KEY_HOME/GLUT_KEY_END应执行与GLUT_KEY_PAGE_UP/GLUT_KEY_PAGE_DOWN类似的旋转:

  • 增加整个模型的当前旋转Angular(新变量用于保存模型中间的旋转Angular );
  • 调用显示方法();

然后,在display()方法里面:

  • 将当前矩阵推入堆栈;
  • 将模型旋转Angular;
  • 另一个将矩阵推入堆栈
  • 通过在PAGE_UP/PAGE_DOWN绘图字母中更改的旋转器变量旋转字母
  • 弹出矩阵
  • POP矩阵;

按键上的代码:

case GLUT_KEY_HOME: //rotate clockwise around the center of the model
        glMatrixMode(GL_MODELVIEW);
        angle -= rotationRate;
        if (angle <= -2 * pi)
            angle += 2 * pi;
        display();
        break;
    case GLUT_KEY_END: //rotate counterclockwise around the center of the model
        glMatrixMode(GL_MODELVIEW);
        angle += rotationRate;
        if (angle >= 2 * pi)
            angle -= 2 * pi;
        display();
        break;

编辑的drawInitials()方法(从display()方法调用):

void drawInitials()
{
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    setRotationMatrix(angle, modelSizeX, modelSizeY); //set rotation matrix to rotate around the center of the model by current angle
    glMultMatrixf(rotationMatrix);  // multiply current Modelview Matrix by rotate-and-translate matrix
        glPushMatrix();
        setRotationMatrix(-rotater, letterMSizeX, modelSizeY); //set to rotate around the center of the letter M by current rotater Clockwise
        glMultMatrixf(rotationMatrix);  // multiply current Modelview Matrix by rotate-and-translate matrix
        drawM();
        glPopMatrix();

        glPushMatrix();
        glTranslatef((modelSizeX - letterJSizeX), 0, 0);  // move OX axis by the size of letter M + space between the letters 
        setRotationMatrix(rotater, letterJSizeX, modelSizeY);//set to rotate around the center of the letter J by current rotater Counter Clockwise
        glMultMatrixf(rotationMatrix);  // multiply current Modelview Matrix by rotate-and-translate matrix
        glTranslatef(-(modelSizeX - letterJSizeX), 0, 0); // return OX axis to its previous place
        drawJ();
        glPopMatrix();
    glPopMatrix();
}

在setRotationMatrix()中清除转换成弧度;
添加新的变量rotationRate,将其用作两种旋转的索引:

float angle; 
// saved rotation angle around center of the model (radian) 
float rotater;
// rotater - saved rotation angle around center of the letter (radian)
float rotationRate = 1 * pi / 180;  // rotation rate (radian), ex rotaterR

相关问题