如何使用 Android 罗盘方向来瞄准 opengl 相机?

发布于 2024-10-21 14:43:34 字数 888 浏览 1 评论 0原文

我正在使用 libgdx 为 Android 开发一个基本的 3D 游戏,但在给定罗盘提供的三个旋转角度(方位角 - 绕 Z 旋转、滚动 - 绕 Y 旋转、俯仰 - 绕 X 旋转)的情况下,我很难正确定向相机。 。我通过以下代码取得了一些小小的成功,因为我可以按照我的预期正确地将虚拟相机瞄准 Z 轴和 X 轴。 (角度以度为单位[-180,180])

camera.direction.x = 0;
camera.direction.y = 0;
camera.direction.z = 1;
camera.up.x = -1;
camera.up.y = 0;
camera.up.z = 0;

camera.rotate(azimuth,0,0,1);
camera.rotate(roll,0,1,0);
camera.rotate(pitch,1,0,0);

我在这方面也取得了一些成功,但它没有确定相机的向上矢量方向。 (在此版本中角度已转换为弧度)

float x,y,z;
roll = (float) (roll + Math.PI/2.0);
x = (float) (Math.cos(azimuth) * Math.cos(roll));
y = (float) (Math.sin(azimuth) * Math.cos(roll));
z = (float) (Math.sin(roll));
Vector3 lookat = new Vector3(x,y,z);
camera.lookAt(lookat.x, lookat.y, lookat.z);

有人可以阐明如何从这三个角度正确定位虚拟相机吗?

另外,我试图让手机处于横向模式,使手机顶部位于左侧,底部位于右侧。因此,相机的默认方向(所有旋转均为 0,手机顶部朝北)是相机瞄准地面(正 Z),向上瞄准东(负 X)。

I'm using libgdx to develop a basic 3d game for android and I'm having difficulty properly orienting the camera given three rotation angles provided from the compass (azimuth - rotation about Z, roll - rotation about Y, pitch - rotation about X). I've had some slight success with the following code in that I can properly aim the virtual camera down the Z-axis and X-axis as I expected. (Angles are in degrees [-180,180])

camera.direction.x = 0;
camera.direction.y = 0;
camera.direction.z = 1;
camera.up.x = -1;
camera.up.y = 0;
camera.up.z = 0;

camera.rotate(azimuth,0,0,1);
camera.rotate(roll,0,1,0);
camera.rotate(pitch,1,0,0);

I've also had some success with this, but it does not orient the camera's up-vector. (Angles have been converted to radians in this version)

float x,y,z;
roll = (float) (roll + Math.PI/2.0);
x = (float) (Math.cos(azimuth) * Math.cos(roll));
y = (float) (Math.sin(azimuth) * Math.cos(roll));
z = (float) (Math.sin(roll));
Vector3 lookat = new Vector3(x,y,z);
camera.lookAt(lookat.x, lookat.y, lookat.z);

Can someone shed some light on how to properly orient the virtual camera from these three angles?

Also, I'm trying to have the phone be in landscape mode such that the top of the phone is to the left and the bottom is to the right. Hence the camera's default direction (all rotations are at 0, top of the phone is aimed north) be the camera aiming toward the ground (positive Z) with the up aiming east (negative X).

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

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

发布评论

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

评论(1

数理化全能战士 2024-10-28 14:43:34

通过编写一段时间的其他代码,我最终达到了尝试将渲染、模拟和输入分开的地步。因此,我提出了以下适合我的解决方案。我还没有严格测试它,但它似乎做了我想要的(忽略相机胶卷)

在程序的 android 部分,我需要将方向设置为横向模式:

<activity android:name=".MySuperAwesomeApplication"
              android:label="@string/app_name"
              android:screenOrientation="landscape">
              >

我创建了一个播放器类来存储偏航、俯仰、滚动和位置

public class Player {
    public final Vector3 position = new Vector3(0,1.5f,0);    
    /** Angle left or right of the vertical */
    public float yaw = 0.0f;
    /** Angle above or below the horizon */
    public float pitch = 0.0f;
    /** Angle about the direction as defined by yaw and pitch */
    public float roll = 0.0f;
}

然后当我根据输入更新播放器时,我执行以下操作:

player.yaw = -Gdx.input.getAzimuth();
player.pitch = -Gdx.input.getRoll()-90;
player.roll = -Gdx.input.getPitch();

请注意音调映射到 input.roll,而 roll 映射到 input.pitch。不知道为什么,但它对我有用。最后更新相机:

camera.direction.x = 0;
camera.direction.y = 0;
camera.direction.z = 1;
camera.up.x = 0;
camera.up.y = 1;
camera.up.z = 0;
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 0;
camera.update();

// The world up vector is <0,1,0>
camera.rotate(player.yaw,0,1,0);
Vector3 pivot = camera.direction.cpy().crs(camera.up);
camera.rotate(player.pitch, pivot.x,pivot.y,pivot.z);
camera.rotate(player.roll, camera.direction.x, camera.direction.y, camera.direction.z);
camera.translate(player.position.x, player.position.y, player.position.z);
camera.update();

编辑:将相机胶卷添加到代码中。对于我和我的 Droid 2,滚动似乎只有 [-90,90] 范围内的值,因此如果您旋转超过 -90 或 90,则值开始变回 0。

By coding other things for a while, I eventually reached a point where I was trying to separate the rendering, simulation, and input. Because of that I have come up with the following solution that works for me. I haven't tested it rigorously, but it appears to do what I want (ignoring camera roll).

On the android part of the program, I needed to set the orientation to landscape mode:

<activity android:name=".MySuperAwesomeApplication"
              android:label="@string/app_name"
              android:screenOrientation="landscape">
              >

I created a player class to store yaw, pitch, roll, and position

public class Player {
    public final Vector3 position = new Vector3(0,1.5f,0);    
    /** Angle left or right of the vertical */
    public float yaw = 0.0f;
    /** Angle above or below the horizon */
    public float pitch = 0.0f;
    /** Angle about the direction as defined by yaw and pitch */
    public float roll = 0.0f;
}

And then when I update the player based on input I do the following:

player.yaw = -Gdx.input.getAzimuth();
player.pitch = -Gdx.input.getRoll()-90;
player.roll = -Gdx.input.getPitch();

Note that pitch maps to input.roll and roll maps to input.pitch. Not sure why, but it works for me. Finally update the camera:

camera.direction.x = 0;
camera.direction.y = 0;
camera.direction.z = 1;
camera.up.x = 0;
camera.up.y = 1;
camera.up.z = 0;
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 0;
camera.update();

// The world up vector is <0,1,0>
camera.rotate(player.yaw,0,1,0);
Vector3 pivot = camera.direction.cpy().crs(camera.up);
camera.rotate(player.pitch, pivot.x,pivot.y,pivot.z);
camera.rotate(player.roll, camera.direction.x, camera.direction.y, camera.direction.z);
camera.translate(player.position.x, player.position.y, player.position.z);
camera.update();

EDIT: added camera roll to the code. For me and my Droid 2, roll appears to only have values in [-90,90] such that if you rotate past -90 or 90 the values start changing back towards 0.

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