1

我目前正在尝试在 Android 中可视化 OpenGL ES 2 中的建筑物。当我向左滑动时,整个场景应该向左移动(与右、下和上相同)。现在,当我将模型旋转 90° 时,轴被交换。当我向右滑动时,模型将移动到顶部而不是右侧(与另一个轴相同)。

如何在不影响当前场景旋转的情况下平移相机?当我使用手机时,我总是想将对象移动到我要滑动的方向。当我先调用 translate 时,翻译工作正常,但旋转有一些错误。

更新:我创建了大部分相机类(建议在答案中):

private Vector3D c = new Vector3D(eye); // copy of eye
private Vector3D l = Vector3D.getNormalized
        (Vector3D.subtract(center, eye)); // normalized center-eye
private Vector3D u = new Vector3D(up); // up (normalized)

public void rotateX(float angle) {
    // Now you can rotate L vector left and
    // right by rotating it around U by any angle. ??
}

public void rotateY(float angle) {
    // If you also need to look up and down
    // (rotate) you need to rotate both L and U around S ??
}

public void rotateZ(float angle) {
    // to tilt left and right you need to rotate U around L. ??
}

// move left and right
// C = C+S * inputfactor
public void translateX(float inputFactor) {
    Vector3D s = Vector3D.cross(l, u);
    Vector3D sTimesInput = mul(s, inputFactor);
    c = new Vector3D(c).add(sTimesInput);
}

// move forward and backward
// C = C+L*inputfactor
public void translateY(float inputFactor) {
    Vector3D lTimesInput = mul(l, inputFactor);
    c = new Vector3D(c).add(lTimesInput);
}

// move up and down
// C = C+U * inputfactor
public void translateZ(float inputFactor) {
    Vector3D uTimesInput = mul(u, inputFactor);
    c = new Vector3D(c).add(uTimesInput);
}

// reconstruct lookAt - eye,center,up

public Vector3D getEye() {
    return new Vector3D(c);
}

public Vector3D getCenter() {
    return new Vector3D(c).add(new Vector3D(l));
}

public Vector3D getUp() {
    return new Vector3D(u);
}

public float[] createLookAt() {
    Vector3D eye = getEye();
    Vector3D center = getCenter();
    Vector3D up = getUp();
    return new float[] { eye.getX(), eye.getY(), eye.getZ(), center.getX(),
            center.getY(), center.getZ(), up.getX(), up.getY(), up.getZ() };
}

// helper-function
public Vector3D mul(Vector3D vec, float factor) {
    return new Vector3D(vec.getX() * factor, vec.getY() * factor,
            vec.getZ() * factor);
}

如何将一个向量围绕另一个向量旋转一个角度?

4

2 回答 2

2

如果您定义相机基向量-center CL-look at、-up,UC相机中心,L则它是从中心到您正在查看的点的归一化向量,并且U是向上归一化的。现在,您可以通过将矢量旋转任意角度L来左右旋转矢量。U

至于向左和向右移动,您将不得不重建侧向量S:L 和 U 之间的叉积(S=LxU)。现在你所要做的就是移动中心:C = C+S*inputFactor.

要重建lookAt向量:

eye = C
center = C+L
up = U

就像一个注释:如果你还需要向上和向下(旋转)你需要同时旋转LU左右旋转,左右S倾斜你需要U旋转L。向前或向后C = C+L*inputFactor移动以及上下移动C = C+U*inputFactor

这应该解决所有逻辑相机移动和旋转。

于 2014-01-08T08:57:02.027 回答
1

我认为您混合了移动相机和旋转对象的概念。首先,您需要将旋转对象的动作与与相机的任何交互分开。您应该能够对对象执行任何操作,而无需更改相机。为此,只需使用模型矩阵来描述对象的平移/旋转/缩放。然后,您通过使用 Matrix.setLookAtM 和与您的模型位置无关的 eyeX、eyeY、eyeZ 来单独处理您的相机。在您的情况下,需要注意的一点取决于 eyeX、eyeY、eyeZ,因为您希望始终注视同一个方向。

例如,如果要将对象绕 Y 轴旋转 90 度,请使用:

Matrix.rotateM(mModelMatrix, 0, 90, 0.0f, 1.0f, 0.0f);

还要记住,在 Matrix.setIdentityM 之后的所有矩阵运算都将以倒序完成,即,如果您先旋转然后在代码中执行第一件事时进行平移,您将首先将对象从其原点位置平移,然后旋转围绕原点,使您的对象围绕第一个原点而不是对象的中心进行一种旋转。

然后假设您已将相机向左平移 100 个单位并查看 -Z 方向,请使用:

Matrix.setLookAtM(mViewMatrix, offset, -100.0f+camX, camY, camZ, -100.0f+camX, camY, -1.0f+camZ, upX, upY, upZ);
于 2014-01-08T12:30:31.227 回答