【问题标题】:Android : OpenGL 2.0 first person cameraAndroid : OpenGL 2.0 第一人称相机
【发布时间】:2013-04-15 21:08:50
【问题描述】:

所以我正在尝试在 Android 上学习 OpenGL 2.0,我确实在 iOS 上玩了很多 OpenGL 1,并且非常喜欢它。

我的简单问题是关于相机和制作一个可以移动的 3D 环境(第一人称)

我应该使用

Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);

控制相机和我在世界上的位置(在 onDrawFrame 上更新),或在 onSurfaceCreated 上设置(一次)并使用

Matrix.setIdentityM(mViewMatrix, 0);
Matrix.translateM(mViewMatrix, 0, mMoveY, 0.0f, mMoveX);
Matrix.rotateM(mViewMatrix, 0, mDeltaY, 1.0f, 0.0f, 0.0f);
Matrix.rotateM(mViewMatrix, 0, mDeltaX, 0.0f, 1.0f, 0.0f);

相反,这感觉就像我在旋转我周围的世界。

我曾经在 OpenGL 1 上看到过他们使用 GLLookAt 的示例

【问题讨论】:

  • 显然,使用产生正确结果的那个。两者都可以使用,因为setLookAt 只是对平移和旋转的更高抽象。
  • 使用最适合您和您的用例的那个。在 OpenGL 中,您所做的只是旋转周围的世界,没有实际的相机(在 ES 2 中更是如此,无论如何您都可以完全控制着色器中的转换)。最后,setLookAt 除了计算 “世界” 的旋转和平移之外,并没有做太多其他事情,就像一堆 translaterotate 调用一样,它是只是某些用例的更好(或更高级别)的界面。如果您已经有了 mMovemDelta 值,则第二种方法似乎更容易。
  • 请向我解释一下lookAt与调用一堆翻译和旋转方法调用一样吗?翻译部分确实不是什么工作,但旋转必须执行正弦/余弦运算来创建旋转矩阵,然后将 2 个矩阵相乘。另一方面,LookAt 直接将 3 个基向量和平移插入到矩阵中。基本向量是:X 轴交叉(向前,向上),Y 轴向上,Z 轴向前 = 观察眼睛。它们中的每一个分别由一列表示。虽然我同意结果是否相同,但请使用最适合您的。
  • 感谢大家的时间和回复,如果有人想将其作为答案发布,那么我会标记它,我感觉 LookAt 确实在引擎盖下做到了这一点,使用翻译和旋转对我来说似乎更容易理解。然而,我的视角出现了问题,所以当我在我面前直接转动一个立方体时,它在我周围旋转时变得相当宽。我会将此作为另一个问题发布
  • @MaticOblak 好吧,是的,旋转将使用一些三角函数。我没有说他们执行完全相同的算术(看评论),我只是在概念上说他们都只是创建一个刚体变换矩阵(旋转+平移)。并不是 setLookAt 做了一些非常神奇的事情(我不确定 OP 是否知道)。当然,实际的实现是完全未定义的(好吧,不是那么未定义),但结果是一样的(实际上,这堆三角函数对于每帧构造的矩阵并不重要)。

标签: android opengl-es opengl-es-2.0


【解决方案1】:

这两种方法中的任何一种都可以,因为您可以获得相同的结果。一般的区别在于您希望如何存储对象状态。对于 3D 环境,我总是使用 3 个向量来确定对象状态(位置、前进、向上),并使用修改版本的 lookAt 和 modelMatrix 可以放置具有与 lookAt 相同参数的对象。这种方法的好处是您可以根据其他对象直接放置参数,例如:导弹跟随您,无论您身在何处或如何移动,它始终朝向您。那么它的前向向量就是taregetPosition-missilePosition(通常是标准化的)。另一方面,如果您必须计算角度,那么您需要做很多工作,直接asinacos 和几个if 两个角度中的每一个的语句。接下来例如简单地在房间里移动,继续前进:如果你使用基向量,那么position = position+forward*speedFactor 而使用角度你必须再次计算你面对的方向,然后做同样的事情......(有很多情况哪里有用)

但也有缺点。您需要拥有自己的系统来移动和旋转这些矢量。例如,如果你想说向左转 45 度,它看起来像这样:

forward = (forward+cross(up,forward)*tan(45)).normalized

这仅适用于区间 (-90, 90) 中的角度。出现时它变得完全相同,但您还需要更正向上向量。

总而言之,如果您创建了所有使用基本向量的方法(旋转、查看、模型矩阵...),它们是一种真正节省劳动力的方法。但这完全取决于您正在编写的项目来决定使用什么。

【讨论】:

  • 我想我明白你的意思,采用第二种方法,我的度数旋转开箱即用,但是我需要计算出我在空间中的位置(X,Y,Z) .你知道我会怎么做吗?
  • 这到底是什么意思?
  • 因此,如果您使用 rotateM,那么您在设置时就知道玩家轮换,但是您不知道空间中的位置,因为您同时使用 translateM 和 rotateM。例如旋转 45 度,然后向前移动 1 步,你怎么知道你的 x,y,z 位置
  • 哦,听起来这并不是真正的问题。您应该始终保持 x、y、z 位置和 2 次旋转。然后,您将首先调用 translate,然后调用 2 个旋转调用。你唯一需要问的是(当以第一人称移动时)向前在哪里,这样你就可以进行这样的控制(它在(cos(phiX),sin(phiX),sin(phiY))所以它不多大不了的)。但是永远不要先使用旋转,如果你做了我认为你认为你必须跟踪所有输入调用的事情(向前走 A,左转 B,向前走 C,向上翻 D...)和重新创建当前状态。
  • 你是一个真正的帮助老实人,我一直在两种方法之间切换,我为另一种方法提出了这个问题stackoverflow.com/questions/16022821/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多