【发布时间】:2015-05-24 00:21:06
【问题描述】:
我有一个 OpenGL 可视化工具(使用 OpenTK)。它应该以 PLY 格式打开一个网格文件,并显示它。用户能够在对象周围移动、旋转或缩放它。最后,用户应该能够从他/她在保存之前看到的完全相同的视图将网格保存到 PLY 文件中。
我已将网格对象抽象为一个类。这是类(有点)的样子:
public class Mesh {
Vector3d vertices[];
int[] triangleIndices;
Matrix4d translation = Matrix4d.Identity();
Matrix4d rotation = Matrix4d.Identity();
Matrix4d scale = Matrix4d.Identity();
int vboHandle;
int faceHandle;
public void Draw() {
GL.PushMatrix();
/**
* Apply transformations
*/
// Do VBO drawing stuff
// ...
GL.PopMatrix();
}
}
我正在做的是将 PLY 文件加载为 VBO。当要绘制网格时,我首先应用平移,应用旋转(通过找到对象的质心,平移坐标系,旋转并平移回来围绕对象的中心),然后(以与旋转相同的方式) 应用缩放。
这可以正常工作,并且可视化工具可以正确绘制网格。但是,当我想保存时,我不知道如何将同一组转换应用于所有顶点并编写 PLY 文件。
我试过这样做:(几乎模仿了我对上面Draw 方法的做法):
for(int i = 0 ; i <this.vertices.Length; i++)
{
// Apply the transformations
Vector3d transformed = Vector3d.Transform(this.vertices[i], this.translation);
// Handle rotation
Matrix4d centerTrans = Matrix4d.CreateTranslation(Center);
transformed = Vector3d.Transform(transformed, centerTrans);
transformed = Vector3d.Transform(transformed, this.rotation);
centerTrans = Matrix4d.CreateTranslation(-Center);
transformed = Vector3d.Transform(transformed, centerTrans);
// Handle scale
centerTrans = Matrix4d.CreateTranslation(Center);
transformed = Vector3d.Transform(transformed, centerTrans);
transformed = Vector3d.Transform(transformed, this.scale);
centerTrans = Matrix4d.CreateTranslation(-Center);
transformed = Vector3d.Transform(transformed, centerTrans);
result[i] = transformed;
}
但问题是输出有点偏离(尤其是在对对象应用旋转时)。
我的主要问题是如何解决这个问题以及解决这个问题的正确方法是什么。
PS。我知道我的方法可能是过时的、幼稚的和错误的整个网格渲染事情(并考虑到 OpenGL 最佳实践),但我正在创建这个可视化工具来解决一个完全不相关且更大的问题。所以在某种程度上,我是为了我的目的而破解东西。非常感谢任何有关解决此问题的好方法的建议)。
PS2。多次Matrix4d 变换的原因是我总是希望将旋转应用于对象的中心,而我不知道任何其他方法可以达到相同的效果。
【问题讨论】:
-
您可能需要颠倒转换的顺序。请记住,当您在 OpenGL 中指定变换时,它们会按照您指定它们的相反顺序应用到顶点。因此,如果您自己将它们一个一个应用到向量,则与指定它们时使用的顺序相反用于 OpenGL。
-
你感兴趣的是
unprojection从世界坐标到屏幕坐标(包括屏幕深度)。已经有一个名为gluUnproject的函数可以精确地执行此操作,但如果您有兴趣滚动自己的投影/非投影函数,那么这就是您要搜索的内容。 -
@RetoKoradi 哦,这解决了我的问题!谢谢!介意将其发布为答案,以便我接受吗?另外,你能简要解释一下这种行为吗?我没有在任何地方读到任何关于它的东西......
-
@Ike 我知道 gluUnproject 但这似乎不适合我的目的。请注意,我已经知道我的对象所在的位置,我不想将其屏幕坐标转换为世界坐标。
-
我现在明白了——是的,除了翻转的转换顺序之外,如果不是将同一个顶点转换 7 次,而是通过以下方式连接转换,您可能会简化一些事情并节省一些计算时间将循环外的所有矩阵相乘成一个单一的、包罗万象的变换矩阵。然后你的内部循环逻辑只包括通过这个矩阵转换每个顶点,如果有些东西变得时髦,你可以在循环外摆弄矩阵逻辑(比如颠倒乘法的顺序)。
标签: opengl rendering mesh opentk