按负数不按比例翻转 Opengl 绘图
Flipping Opengl drawing without scale by negative numbers
我正在尝试绘制两个彼此面对的 2D 钻石。
所以我画了第一颗钻石然后我画了第二颗钻石使用后:
glTranslated(0, -150, 0);
所以它可以正好出现在我的第一颗钻石下面。
但是,我 运行 遇到了一个问题,我无法翻转第二颗钻石,使它看起来像一面镜子。
这是我正在尝试做的事情:
我在网上搜索解决方案,他们都提到我应该
使用
glScalef(1.0f,-1.0f,1.0f);
但每次我使用它时,绘图都会消失。
函数
glRotatef(angle,x,y,z);
引起了我的注意,但我无法正确使用它导致方向错误。
这是我的图片现在没有 glRotate()
时的样子:
所以我认为我需要适当的技术来使用这些功能中的任何一个。
注意:我使用了很多线环和顶点来绘制。
#include <windows.h> // For MS Windows
#include <GL/glut.h> // (or others, depending on the system in use)
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); // Set display-window color to
white.
glMatrixMode(GL_PROJECTION); // Set projection parameters.
gluOrtho2D(0.0, 400.0, 0.0, 400.0);
}
void drawDiamond()
{
glBegin(GL_LINE_LOOP);
glVertex2f(125, 350);
glVertex2f(245, 350);
glVertex2f(290, 300);
glVertex2f(182, 200);
glVertex2f(75, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(109, 333);
glVertex2f(138, 350);
glVertex2f(159, 337);
glVertex2f(123, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(109, 333);
glVertex2f(123, 300);
glVertex2f(154, 225);
glVertex2f(92, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(290, 300);
glVertex2f(75, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(123, 300);
glVertex2f(159, 337);
glVertex2f(154, 300);
glVertex2f(171, 225);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(181, 300);
glVertex2f(159, 337);
glVertex2f(181, 350);
glVertex2f(209, 337);
glVertex2f(181, 300);
glVertex2f(171, 225);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(181, 300);
glVertex2f(209, 337);
glVertex2f(219, 300);
glVertex2f(195, 225);
glVertex2f(181, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(209, 337);
glVertex2f(243, 300);
glVertex2f(195, 225);
glVertex2f(219, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(209, 337);
glVertex2f(229, 350);
glVertex2f(260, 333);
glVertex2f(243, 300);
glVertex2f(209, 337);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(260, 333);
glVertex2f(278, 300);
glVertex2f(210, 225);
glVertex2f(243, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(195, 225);
glVertex2f(182, 200);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(171, 225);
glVertex2f(182, 200);
glEnd();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
glColor3f(0.0, 0.0, 0.0); // Set line segment color to blue.
// your code goes here
drawDiamond();
glTranslatef(0.0f, -150, 0.0f);
drawDiamond();
glFlush(); // Process all OpenGL routines as quickly as possible.
}
void main(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // Set display mode.
glutInitWindowPosition(50, 100); // Set top-left display-window
position.
glutInitWindowSize(400, 400); // Set display-window width and
height.
glutCreateWindow("Diamond Project"); // Create display window.
init(); // Execute initialization procedure.
glutDisplayFunc(display); // Send graphics to display window.
glutMainLoop(); // Display everything and wait.
}
根据您的顶点设置方式以及您是否启用了背面剔除,您可能需要将菱形或(模型的)中心点更改为底部尖端,然后您可以简单地围绕 X 旋转轴,前提是您将其声明为水平轴。这样做应该没有那么难。它看起来像:
glRotatef( 180.0f, 1, 0, 0 );
如果您旋转的是度数而不是弧度。
对于每个顶点(我假设您使用直接模式来指定顶点),您可以 glVertex2i(myVertex.x, symmetryLine - myVertex.y, 0)
其中 myVertex 是您之前使用的 x 和 y 值,而 symmetryLine 是您希望镜像的值反对。不过,最好的方法是使用负数 glScale
。您的钻石是旋转对称的 glRotate
也可以,但是您知道,这不是一种非常优雅的方法。
您要做的是围绕平行于 X-axis 的轴镜像(翻转)对象,并穿过对象(菱形)的底部边界。
为此,必须找到底部 Y 坐标 (bottomY
),并且必须在 相反 方向平移对象。注意模型坐标(顶点)的底部和不是视口上最终坐标的底部:
float bottomY = 200.0f;
glTranslatef( 0.0f, -bottomY , 0.0f );
接下来必须翻转对象。这可以通过
glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
或
glScalef(1.0f, -1.0f, 0.0f)
注意,这两个操作产生相同的变换矩阵,因为cos(90°) = cos(-90°), sin(90°) = -sin(90°).
那么bottomY
的翻译要反过来:
glTranslatef( 0.0f, bottomY, 0.0f );
但请注意,OpenGL 固定功能管道堆栈以相反的顺序运行,因为当前矩阵乘以新操作指定的矩阵。
翻译:见glTranslate
的文档:
glTranslate
produces a translation by x y z
. The current matrix (see glMatrixMode
) is multiplied by this translation matrix, with the product replacing the current matrix.
旋转:参见glRotate
的文档:
glRotate
produces a rotation of angle degrees around the vector x y z
. The current matrix (see glMatrixMode
) is multiplied by a rotation matrix with the product replacing the current matrix.
缩放:参见glScale
的文档:
glScale
produces a nonuniform scaling along the x
, y
, and z
axes. The three parameters indicate the desired scale factor along each of the three axes.
The current matrix (see glMatrixMode
) is multiplied by this scale matrix.
这意味着以下应该做你想做的事:
float bottomY = 200.0f;
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
drawDiamond();
glTranslatef( 0.0f, bottomY , 0.0f );
glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );
glTranslatef( 0.0f, -bottomY , 0.0f );
drawDiamond();
并且与:
相同
glTranslatef( 0.0f, bottomY , 0.0f );
glScalef( 1.0f, -1.0f, 1.0f );
glTranslatef( 0.0f, -bottomY , 0.0f );
我正在尝试绘制两个彼此面对的 2D 钻石。 所以我画了第一颗钻石然后我画了第二颗钻石使用后:
glTranslated(0, -150, 0);
所以它可以正好出现在我的第一颗钻石下面。 但是,我 运行 遇到了一个问题,我无法翻转第二颗钻石,使它看起来像一面镜子。
这是我正在尝试做的事情:
我在网上搜索解决方案,他们都提到我应该 使用
glScalef(1.0f,-1.0f,1.0f);
但每次我使用它时,绘图都会消失。
函数
glRotatef(angle,x,y,z);
引起了我的注意,但我无法正确使用它导致方向错误。
这是我的图片现在没有 glRotate()
时的样子:
所以我认为我需要适当的技术来使用这些功能中的任何一个。
注意:我使用了很多线环和顶点来绘制。
#include <windows.h> // For MS Windows
#include <GL/glut.h> // (or others, depending on the system in use)
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); // Set display-window color to
white.
glMatrixMode(GL_PROJECTION); // Set projection parameters.
gluOrtho2D(0.0, 400.0, 0.0, 400.0);
}
void drawDiamond()
{
glBegin(GL_LINE_LOOP);
glVertex2f(125, 350);
glVertex2f(245, 350);
glVertex2f(290, 300);
glVertex2f(182, 200);
glVertex2f(75, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(109, 333);
glVertex2f(138, 350);
glVertex2f(159, 337);
glVertex2f(123, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(109, 333);
glVertex2f(123, 300);
glVertex2f(154, 225);
glVertex2f(92, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(290, 300);
glVertex2f(75, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(123, 300);
glVertex2f(159, 337);
glVertex2f(154, 300);
glVertex2f(171, 225);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(181, 300);
glVertex2f(159, 337);
glVertex2f(181, 350);
glVertex2f(209, 337);
glVertex2f(181, 300);
glVertex2f(171, 225);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(181, 300);
glVertex2f(209, 337);
glVertex2f(219, 300);
glVertex2f(195, 225);
glVertex2f(181, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(209, 337);
glVertex2f(243, 300);
glVertex2f(195, 225);
glVertex2f(219, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(209, 337);
glVertex2f(229, 350);
glVertex2f(260, 333);
glVertex2f(243, 300);
glVertex2f(209, 337);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(260, 333);
glVertex2f(278, 300);
glVertex2f(210, 225);
glVertex2f(243, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(195, 225);
glVertex2f(182, 200);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(171, 225);
glVertex2f(182, 200);
glEnd();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
glColor3f(0.0, 0.0, 0.0); // Set line segment color to blue.
// your code goes here
drawDiamond();
glTranslatef(0.0f, -150, 0.0f);
drawDiamond();
glFlush(); // Process all OpenGL routines as quickly as possible.
}
void main(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // Set display mode.
glutInitWindowPosition(50, 100); // Set top-left display-window
position.
glutInitWindowSize(400, 400); // Set display-window width and
height.
glutCreateWindow("Diamond Project"); // Create display window.
init(); // Execute initialization procedure.
glutDisplayFunc(display); // Send graphics to display window.
glutMainLoop(); // Display everything and wait.
}
根据您的顶点设置方式以及您是否启用了背面剔除,您可能需要将菱形或(模型的)中心点更改为底部尖端,然后您可以简单地围绕 X 旋转轴,前提是您将其声明为水平轴。这样做应该没有那么难。它看起来像:
glRotatef( 180.0f, 1, 0, 0 );
如果您旋转的是度数而不是弧度。
对于每个顶点(我假设您使用直接模式来指定顶点),您可以 glVertex2i(myVertex.x, symmetryLine - myVertex.y, 0)
其中 myVertex 是您之前使用的 x 和 y 值,而 symmetryLine 是您希望镜像的值反对。不过,最好的方法是使用负数 glScale
。您的钻石是旋转对称的 glRotate
也可以,但是您知道,这不是一种非常优雅的方法。
您要做的是围绕平行于 X-axis 的轴镜像(翻转)对象,并穿过对象(菱形)的底部边界。
为此,必须找到底部 Y 坐标 (bottomY
),并且必须在 相反 方向平移对象。注意模型坐标(顶点)的底部和不是视口上最终坐标的底部:
float bottomY = 200.0f;
glTranslatef( 0.0f, -bottomY , 0.0f );
接下来必须翻转对象。这可以通过
glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
或
glScalef(1.0f, -1.0f, 0.0f)
注意,这两个操作产生相同的变换矩阵,因为cos(90°) = cos(-90°), sin(90°) = -sin(90°).
那么bottomY
的翻译要反过来:
glTranslatef( 0.0f, bottomY, 0.0f );
但请注意,OpenGL 固定功能管道堆栈以相反的顺序运行,因为当前矩阵乘以新操作指定的矩阵。
翻译:见glTranslate
的文档:
glTranslate
produces a translation byx y z
. The current matrix (seeglMatrixMode
) is multiplied by this translation matrix, with the product replacing the current matrix.
旋转:参见glRotate
的文档:
glRotate
produces a rotation of angle degrees around the vectorx y z
. The current matrix (seeglMatrixMode
) is multiplied by a rotation matrix with the product replacing the current matrix.
缩放:参见glScale
的文档:
glScale
produces a nonuniform scaling along thex
,y
, andz
axes. The three parameters indicate the desired scale factor along each of the three axes. The current matrix (seeglMatrixMode
) is multiplied by this scale matrix.
这意味着以下应该做你想做的事:
float bottomY = 200.0f;
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
drawDiamond();
glTranslatef( 0.0f, bottomY , 0.0f );
glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );
glTranslatef( 0.0f, -bottomY , 0.0f );
drawDiamond();
并且与:
相同glTranslatef( 0.0f, bottomY , 0.0f );
glScalef( 1.0f, -1.0f, 1.0f );
glTranslatef( 0.0f, -bottomY , 0.0f );