在 openGL 中使用触摸屏控制 3D 对象的旋转

发布于 2024-10-14 11:00:00 字数 636 浏览 2 评论 0原文

我是一名四年级计算机工程专业的学生,​​有一些 Android 开发经验。

我正在开发一个具有 3D 组件的应用程序,这需要我能够旋转它。我正在查看 android 资源站点上的示例。

http://developer.android .com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.html

此示例不讨论绕 z 轴的旋转。我已经尝试使用四元数进行旋转,但我不明白如何绕 z 轴旋转。

一旦旋转某物,轴就不再相同(x,y),那么如何找出在哪个轴上旋转多少?

我想知道是否有人可以帮助我学习如何能够围绕一个物体旋转。与上面的示例类似,但也是围绕 z 轴。我已经花了大约 24 小时搜索并试图解决这个问题。

更大的问题是,一旦绕 y 轴旋转 90 度,如何检测下一次旋转(在触摸屏上垂直旋转)应该绕 z 轴。

先感谢您。

I'm a 4th year computer engineering student and have some experience with Android dev.

I am working on an application that has a 3D component to it which requires me to be able to rotate it around. I was looking at the example at the android resources site.

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.html

This example does not talk about rotation around the z-axis. I have already tried using Quaternion for the rotations but I don't understand how to get rotations around the z-axis.

Once you rotate something, the axis are no longer the same (x,y) so how can you find out how much to rotate in which axis?

I was wondering if anyone can help me with learning how to just be able to rotate around an object. like the example above but also around the z-axis. I have already spend about 24 hours searching and trying to figure this out.

The bigger issue is that once you rotate 90 degrees around the y-axis how can you detect that the next rotation (going vertically on the touchscreen) should be around the z-axis.

Thank you in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

_畞蕅 2024-10-21 11:00:00

将 xAngle 和 yAngle 添加到当前矩阵。

Matrix.rotateM(matrix, 0, xAngleADD, matrix[1], matrix[5], matrix[9]);
Matrix.rotateM(matrix, 0, yAngleADD, matrix[0], matrix[4], matrix[8]);
gl.glMultMatrixf(matrix, 0);

Add xAngle and yAngle to the current matrix.

Matrix.rotateM(matrix, 0, xAngleADD, matrix[1], matrix[5], matrix[9]);
Matrix.rotateM(matrix, 0, yAngleADD, matrix[0], matrix[4], matrix[8]);
gl.glMultMatrixf(matrix, 0);
柏拉图鍀咏恒 2024-10-21 11:00:00

您还可以围绕中心旋转相机,而不是旋转对象。

You can also rotate the camera around the center instead of rotating the object.

恍梦境° 2024-10-21 11:00:00

你的问题不太对。不要问“一旦旋转某物,轴就不再相同(x,y),那么如何找出在哪个轴上旋转多少?”,问“如何绕全局轴而不是局部轴旋转”轴?”。您希望围绕全局 x 的旋转始终是围绕全局 x 的旋转,而不是围绕对象的局部 x 轴的旋转。您不会根据当前状态进行不同的旋转,您只需更改概念上旋转的内容即可。

首先,您可能正在存储 rotX、rotY 和 rotZ 并调用 glRotatef 来应用旋转?这对于你想做的事情来说还不够好。您正在做的是通过欧拉角描述方向。您总会遇到万向节锁定,这是一个轴的某些值转动另一个轴的地方两个轴变成同一个轴。所以你失去了一定程度的自由。查看文章以获得正确的解释。

因为作为 OpenGL 编码员,您会对它们感到非常满意,所以假设您直接将对象方向存储为名为 M 的矩阵。您将旋转存储为用于实现旋转的矩阵。没有明确的角度或轴概念。

假设你想绕 x 旋转。您围绕 x 轴生成一个合适的旋转矩阵,将其称为 R。OpenGL 将在内部构建这样的矩阵来执行 glRotatef(angle, 1, 0, 0)。

那么你实际上有两个选择——用 MR 替换 M 或用 RM 替换 M。矩阵乘法不可交换,因此它们不一样。就像使用 OpenGL 矩阵堆栈将 6 向左平移然后旋转 40 度会产生与旋转 40 度然后向左平移 6 不同的结果。

在这种情况下,R 是对象,因此 MR 是后乘法,RM 是预乘法。矩阵相乘创建一个矩阵,当将该矩阵应用于向量时,其效果与先应用第二个矩阵再应用第一个矩阵具有相同的效果。因此,如果您进行后乘,您将得到的结果就好像您将对象旋转了新的旋转,然后旋转了它之前的所有旋转。这显然是错误的做法。您希望新的修改在迄今为止的所有其他修改之后生效。所以你预乘。然后将结果存储为新的 M。

实际上,这就是全部内容。您可以显式地使用 GL 矩阵堆栈快速获得概念证明,例如:

// ... I assume the modelview stack is active, M is an array of 16 floats ...

// ensure whatever's on the stack currently is kept safe
glPushMatrix();

    // but we don't actually care what it was, so load the identity
    glLoadIdentity();

    // build our rotation matrix first
    glRotatef(changeAroundX, 1, 0, 0);
    glRotatef(changeAroundY, 0, 1, 0);

    // multiply by M. OpenGL postmultiplies by the newer matrix, so this
    // is premultiplying M by whatever we just loaded
    glMultMatrixf(M);

    // read the new M back
    glGetFloatv(GL_MODELVIEW_MATRIX, M);

// and pretend we never touched the stack
glPopMatrix();

然后使用 glMultMatrixf(M) 代替 glRotatef 来应用当前对象旋转。这只是一个概念证明,因为您很快就会在 M 中得到一些令人讨厌的数值错误,而这只是由于您对其进行了大量操作而导致的。您可以在进行过程中修复 M,但如果您已经有了四元数代码并且对它们感到满意,那么沿着这条路线走可能会更明智。只需用四元数等价物替换逻辑矩阵运算即可。

Your question isn't quite right. Don't ask "Once you rotate something, the axis are no longer the same (x,y) so how can you find out how much to rotate in which axis?", ask "how can I rotate around global axes rather than local axes?". You want a rotation around your global x always to be a rotation around global x, not a rotation around your object's local x axis. You don't rotate differently according to the current state, you just change what you're conceptually rotating around.

First of all, you're probably storing, say rotX, rotY and rotZ and calling glRotatef to apply a rotation? That's not good enough for what you want to do. What you're doing is describing orientation by Euler angles. You'll always encounter gimbal lock, which is where some values for one of the axes turn the other two axes into the same axis. So you lose a degree of freedom. Check out the article for a proper explanation.

Because you'll be very happy with them as an OpenGL coder, suppose you were instead storing object orientation directly as a matrix called M. You store the rotation as the matrix you apply to achieve the rotation. There's no explicit concept of angles or axes.

Suppose you want to rotate around x. You generate a suitable rotation matrix around the x axis, call it R. Such a matrix would be the thing OpenGL would build internally to carry out glRotatef(angle, 1, 0, 0).

Then you actually have two options — replace M with MR or replace M with RM. Matrix multiplication isn't commutative, so those aren't the same. Just like using the OpenGL matrix stack to translate six to the left and then rotate by 40 degrees produces a different result to rotating by 40 degrees and then translating six to the left.

In this case R is the object, so MR is postmultiplication and RM is premultiplication. Multiplication of matrices creates a matrix that, when applied to a vector, has the same effect as applying the second one and then applying the first one. So if you postmultiplied, you'd get the result as though you'd rotated the object by the new rotation and then all the ones that preceded it. That's obviously the wrong way around. You want the new modification to take effect after all other modifications to date. So you premultiply. And then store the result as the new M.

That's all there is to it, actually. You can knock up a quick proof of concept using the GL matrix stack explicitly, like:

// ... I assume the modelview stack is active, M is an array of 16 floats ...

// ensure whatever's on the stack currently is kept safe
glPushMatrix();

    // but we don't actually care what it was, so load the identity
    glLoadIdentity();

    // build our rotation matrix first
    glRotatef(changeAroundX, 1, 0, 0);
    glRotatef(changeAroundY, 0, 1, 0);

    // multiply by M. OpenGL postmultiplies by the newer matrix, so this
    // is premultiplying M by whatever we just loaded
    glMultMatrixf(M);

    // read the new M back
    glGetFloatv(GL_MODELVIEW_MATRIX, M);

// and pretend we never touched the stack
glPopMatrix();

Then use glMultMatrixf(M) in place of glRotatef to apply the current object rotation. This is only a proof of concept because you'll quickly get some nasty numerical errors in M, just resulting from the high amount of manipulation you're doing to it. You can fix M as you go along but if you already have quaternion code and are happy with them, it might be smarter to go down that route. Just replace the logical matrix ops with the quaternion equivalents.

笑,眼淚并存 2024-10-21 11:00:00

我建议您阅读这本书链接

具体您的问题:请参阅第3.3部分.1

I recommend you to read this book link

Specifically your question: see part 3.3.1

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文