OpenGL转换无法按预期工作

时间:2014-11-28 04:00:05

标签: c# opengl opentk

我正在编写一个OpenGL应用程序(C#和OpenTK),我对OpenGL转换的工作原理感到困惑。

我设置了一个透视投影,我在默认位置使用默认方向(+ X向右,+ Y向上,+ Z向我。)现在我在XY平面绘制一个四边形,在Z轴上-10。

GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Vertex3(-1, 1, -10);
GL.Vertex3(1, 1, -10);
GL.Vertex3(1, -1, -10);
GL.Vertex3(-1, -1, -10);
GL.End();

这可以按预期工作。但是现在我想沿它的局部 Y轴旋转四边形,所以我添加了一个旋转,它被应用到我的单位矩阵。这是代码的相关部分:

GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();

GL.Rotate(10, 0, 1, 0);

GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Vertex3(-1, 1, -10);
GL.Vertex3(1, 1, -10);
GL.Vertex3(1, -1, -10);
GL.Vertex3(-1, -1, -10);
GL.End();

但是这将围绕我的“世界”Y轴旋转飞机,所以现在飞机不再穿过我的-Z轴了,但它是一个角度。

问题

如何将物体保持在所需的位置(沿着我的Z轴在-10处)但是它绕自己的轴旋转?

我尝试了什么

我已经尝试过第一次转换到原点,执行旋转,绘图,然后向后移动,但这也不起作用,大概是因为一旦我旋转,现在我不再沿着“世界”进行翻译“轴,但旋转的轴。这是代码:

GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();

GL.Translate(0, 0, 10);
GL.Rotate(10, 0, 1, 0);

GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Vertex3(-1, 1, -10);
GL.Vertex3(1, 1, -10);
GL.Vertex3(1, -1, -10);
GL.Vertex3(-1, -1, -10);
GL.End();

GL.Translate(0, 0, -10);

我有一种感觉,我需要使用PushMatrixPopMatrix,但我不太清楚我是否理解他们是如何发挥作用的。如果我在执行任何操作之前推动我的矩阵,然后弹出它,我的视图是否应该恢复正常?如果是这样,为什么这不起作用:

GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();

// Push current matrix onto the stack
GL.PushMatrix();

// Perform operations on newly pushed matrix
GL.Translate(0, 0, 10);
GL.Rotate(10, 0, 1, 0);

GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.Green);
GL.Vertex3(-1, 1, -10);
GL.Vertex3(1, 1, -10);
GL.Vertex3(1, -1, -10);
GL.Vertex3(-1, -1, -10);
GL.End();

// Pop it off, so return to my previous matrix
GL.PopMatrix();

1 个答案:

答案 0 :(得分:3)

你的第二次尝试是在正确的轨道上,但它仍然错过了几个方面:

  • 在开始绘图之前,需要指定所有转换。只有在进行绘制调用时处于活动状态的转换才会应用于该绘制调用中的坐标。在glEnd()之后进行翻译将无能为力。
  • 订单倒退。指定最后的转换将应用于顶点第一个。因此,需要最后指定将几何体移动到原点的平移,并且需要首先指定将其移回其位置的平移。

代码序列将如下所示:

GL.Translate(0, 0, -10);
GL.Rotate(10, 0, 1, 0);
GL.Translate(0, 0, 10);

GL.Begin(PrimitiveType.Quads);
...
GL.End();

此代码示例中不需要PushMatrix()PopMatrix(),因为您在绘制函数的开头调用LoadIdentity(),这会将当前转换恢复为标识转换。至少根据显示的内容,您不会在此代码之后绘制任何内容,因此无需恢复以前的矩阵。

另一种方法是不为每一帧调用LoadIdentity(),而是将上面的代码段括在开头的PushMatrix()和最后的PopMatrix()。这实际上更具可扩展性,因为如果需要,它会恢复矩阵以进行额外的渲染。

我在这里回答类似问题时更详细地解释了一些内容:Rotating an object around a fixed point using glMultMatrix