我在OpenGL中遇到了一个2D转换问题。我的程序在屏幕上画两个字母,通过按下指定的键,字母必须向上(GLUT_KEY_up(向下(GLUT_TKEY_down(向左(GLUT_LKEY_left(向右(GLUT_CKEY_right(,并顺时针旋转(GLUT_HKEY_HOME(和逆时针旋转(GLUT_KEY_END(。(在键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;
"设置"旋转矩阵的函数将角度和旋转点插入恒等矩阵[4x4]:
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
- 通过将MODELVIEW矩阵与(-angle,same point(相乘,恢复绘制对象后的旋转
- 试图删除glMultMatrix((并使用glTranslate((、glRotate((
它们都没有像我预期的那样工作
考虑以下步骤:
- 首先,在对象坐标系上旋转对象
- 接下来,将对象放置到您正在考虑方向{上、下、左、右}的空间(坐标系(中
即,对于第一次旋转,中心必须是对象坐标系中的值。例如,对象坐标系通常定义为原点等于对象的中心。在这种情况下,旋转中心为(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();
我发现我做错了什么:按钮GLUT_KEY_HOME/GUT_KEY_END应该执行与GLUT_KEY_PAGE_UP/GLUT_KEY_PAGE_DOWN:类似的旋转
- 增加整个模型的当前旋转角度(保存模型中间旋转角度的新变量(
- 调用display方法((
然后,在display((方法内部:
- 将当前矩阵推入堆栈
- 按角度旋转模型
- 将另一个矩阵推入堆栈
- 按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;
edited 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((中,移除到弧度的转换;
添加新的可变旋转速率,将其用作两次旋转的增量:
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