OpenGL:相机和对象

Posted

技术标签:

【中文标题】OpenGL:相机和对象【英文标题】:OpenGL: Camera and objects 【发布时间】:2016-07-17 17:21:44 【问题描述】:

我正在开发一些游戏来学习 OpenGL。

我正在尝试实现一种拾取对象的方法(例如拾取斧头、枪等)。

这个想法是,即使在相机移动或旋转之后,这个对象也会固定在相机前面。

我目前取得的成就

当我向前、向后、向左、向右、向上或向下移动时,我可以让对象跟随我,方法是将其设置在相机正前方。

但是……当相机旋转/倾斜(向上、向下、向左、向右……)时,问题就开始了。

在这种情况下,一切正常(向上、向下、向左、向右、向右倾斜、向左倾斜......所有这些操作都转化为围绕 x、y、z 轴的旋转),直到我组合了几个旋转,例如向后旋转 180 度,然后尝试向上旋转(在我们的语言中:在 Z 轴上旋转 180 度,然后在 X 轴上旋转)。

对象开始以一种奇怪的行为围绕自身旋转。如果我在 Z 轴上向后旋转 -180 度(=再次向前看)然后向上看(围绕 X 轴旋转),则对象旋转良好。

我的游戏实现

相机有 4 个向量,每个对象有 4 个向量:原点、x、y 和 z(表示对象坐标系)。

为了向前移动相机,我从当前位置减去 z 轴

其他方向也一样。

为了使相机倾斜,例如向右倾斜,我只计算围绕 Z 轴的旋转并应用于 X、Y 轴。

注意:世界上的运动在各个方向和角度都很好。

这是我用来在世界中定位对象的(相关)代码。在绘制它们之前,我首先将它们放在它们的原点(回想一下:我将原点和 x、y、z 轴保存到我的所有对象),然后做一些缩放以适合我想要的大小:

// translate to position
gl.glTranslatef((float)origin.x, (float)origin.y, (float)origin.z);
// scale to size
gl.glScalef((float)size.x, (float)size.y, (float)size.z);
// apply rotation around the object's axes
gl.glRotatef(xrot, (float)x.x, (float)x.y, (float)x.z);
gl.glRotatef(yrot, (float)y.x, (float)y.y, (float)y.z);
gl.glRotatef(zrot, (float)z.x, (float)z.y, (float)z.z);

已编辑:

这是我计算角度的方式:

Math.toDegrees(Math.acos(v1.dot(v2))) // dot is a simple dot product

【问题讨论】:

那么,当你asked this question yesterday但没有得到答案时,为什么你觉得删除那个问题再问是合适的? 我认为缺乏解释。我发布了更清晰的解释。 @NicolBolas 我有一个突破和编辑的问题。 我不知道您为什么选择使用顺序旋转向量使事情复杂化。但是,由于您没有向我们展示如何“计算新旧 Z 轴之间的角度差”,这很可能就是您的问题所在。 【参考方案1】:

让我向您介绍一种叫做“矩阵”的东西:

float matrix[16];

矩阵是一个简单的数组,旨在以 OpenGL 可以理解的格式将所有四个向量存储在一个简洁的包中。您可以通过以下方式将向量存储在矩阵中:

matrix[0] = getAxisX().getX();
matrix[1] = getAxisX().getY();
matrix[2] = getAxisX().getZ();
matrix[3] = 0.0;

matrix[4] = getAxisY().getX();
matrix[5] = getAxisY().getY();
matrix[6] = getAxisY().getZ();
matrix[7] = 0.0;

matrix[8] = getAxisZ().getX();
matrix[9] = getAxisZ().getY();
matrix[10] = getAxisZ().getZ();
matrix[11] = 0.0;

matrix[12] = getOrigin().getX();
matrix[13] = getOrigin().getY();
matrix[14] = getOrigin().getZ();
matrix[15] = 1.0;

您可以在每次要将数据传递给 OpenGL 时将其复制到一个矩阵中,也可以通过采用矩阵作为现在将数据存储在对象中的标准方式来为自己省去很多麻烦。

(请注意,0.01.0 常量很重要,原因我不会在这里讨论。)

然后简单地替换:

gl.glTranslatef((float)origin.x, (float)origin.y, (float)origin.z);

有了这个:

gl.glMultMatrixf(matrix);

如果您的 OpenGL 版本按我预期的方式工作,它应该会为您完成平移和旋转。

【讨论】:

谢谢。可能这是存储数据的“更好”方式,但它不能解决我的问题...... P.S 我刚刚遇到了一个突破性的编辑问题。 要么我没看懂你的问题,要么你没看懂我的回答。我的解决方案不是矩阵本身,而是gl.glMultMatrixf(matrix); 调用。矩阵只是将数据传递给函数的一种方式。 @Jjang 好!请记住对您认为有帮助的答案进行投票。 :) @Jjang 你的要求对我来说听起来微不足道。但是,如果我要向您展示如何做您想做的事情,您就必须更具体一些。 @Jjang 如果您想相对于相机平移和旋转它,那么可以,只需在之后添加这些平移和旋转。

以上是关于OpenGL:相机和对象的主要内容,如果未能解决你的问题,请参考以下文章

在OpenGL中使对象跟随相机

OpenGL制作物面相机

相机倒置OpenGL

openGL - 我希望相机更接近物体,如何?

如何将 OpenGL 对象添加到 SurfaceView 相机中?

Java OpenGL - 如何使对象随相机旋转?