LWJGL Перемещение камеры к тому, на что вы смотрите

Я долго искал и не мог найти ответ на этот, казалось бы, простой вопрос. У меня есть трехмерное пространство, и моя камера имеет переменные x, y, z, yaw, pitch и roll, и я хочу иметь возможность перемещать камеру вперед в направлении того, на что я смотрю. Большинство классов камеры имеют что-то вроде этого:

//moves the camera forward relitive to its current rotation (yaw)
public void walkForward(float distance)
{

    position.x -= distance * (float)Math.sin(Math.toRadians(yaw));
    position.z += distance * (float)Math.cos(Math.toRadians(yaw));

}

Это хорошо работает для движения вперед в зависимости от вашего рыскания, но ваше положение по оси y никогда не изменится. Как это можно изменить, чтобы оно также соответствовало вашему тону, чтобы вы всегда двигались к тому, на что смотрит камера?

РЕДАКТИРОВАТЬ:

Под продвижением вперед я подразумеваю, что при перемещении вашей камеры на определенную величину по каждой оси эта величина, зависящая от вашего рысканья, тангажа и крена, всего, что находится перед вами, будет казаться больше. Это можно использовать:

    position.x += -Math.sin(Math.toRadians(rotation.y)) * Math.cos(Math.toRadians(rotation.x)) * distance;
    position.z += Math.cos(Math.toRadians(rotation.y)) * Math.cos(Math.toRadians(rotation.x)) * distance;
    position.y -= -Math.sin(Math.toRadians(rotation.x)) * distance;

Примечание: вращение.y = рыскание, вращение.x = тангаж, вращение.z будет вращением. Расстояние - это просто то, сколько нужно двигаться, скажем, 0,1.

Это будет работать, если вы не измените поворот камеры (вращение по оси z), иначе не будет. Этот пост, вероятно, очень похож на этот теперь, но я не знаю, как применить матричное умножение, которое было решением, к моему классу камеры, который выглядит так

public class Camera
{
// Field Of View
private float fov;
// Aspect Ratio
private float aspect;
// Near Plane
private float zNear;
// Far Plane
private float zFar;

// Projection matrix
private Matrix4f projection;
// View matrix
private Matrix4f view;

// Camera position
private Vector3f position;
// Camera rotation
private Vector3f rotation;

// Vectors for axes
private Vector3f xAxis, yAxis, zAxis;

/**
 * Creates a simple 3D Perspective Camera.
 * 
 * @param fov The field of view in degrees.
 * @param aspect The aspect ratio.
 * @param zNear The near clipping plane.
 * @param zFar The far clipping plane.
 */
public Camera(float fov, float aspect, float zNear, float zFar)
{
    // Set the local variables
    this.fov = fov;
    this.aspect = aspect;
    this.zNear = zNear;
    this.zFar = zFar;

    // Create matrices
    projection = MatrixUtil.createPerspectiveProjection(fov, aspect, zNear, zFar);
    view = MatrixUtil.createIdentityMatrix();

    // Initialize position and rotation vectors
    position = new Vector3f(0, 0, 0);
    rotation = new Vector3f(0, 0, 0);

    // Create normalized axis vectors
    xAxis = new Vector3f(1, 0, 0);
    yAxis = new Vector3f(0, 1, 0);
    zAxis = new Vector3f(0, 0, 1);

    // Enable depth testing
    glEnable(GL_DEPTH_TEST);
}

/**
 * Apply the camera's transformations.
 */
public void apply()
{
    // Make the view matrix an identity.
    view.setIdentity();

    // Rotate the view
    Matrix4f.rotate((float) Math.toRadians(rotation.x), xAxis, view, view);
    Matrix4f.rotate((float) Math.toRadians(rotation.y), yAxis, view, view);
    Matrix4f.rotate((float) Math.toRadians(rotation.z), zAxis, view, view);

    // Move the camera
    Matrix4f.translate(position, view, view);
}

//moves the camera forward relitive to its current rotation (yaw and pitch)
public void moveForward(float distance)
{
    position.x += -Math.sin(Math.toRadians(rotation.y)) * Math.cos(Math.toRadians(rotation.x)) * distance;
    position.z += Math.cos(Math.toRadians(rotation.y)) * Math.cos(Math.toRadians(rotation.x)) * distance;
    position.y -= -Math.sin(Math.toRadians(rotation.x)) * distance;
}

(Этот класс камеры основан на этом руководстве)

Итак, как я могу заставить камеру двигаться вперед в зависимости от ее рыскания, тангажа и крена.


person Alex Socha    schedule 08.02.2014    source источник


Ответы (1)


У вас есть 3 вращения: крен, рыскание и тангаж. Их также можно представить в виде точек на диске, нарисованном на плоской плоскости в трехмерном пространстве: xy-плоскость (крен), xz-плоскость (рыскание), zy-плоскость (шаг).

Чтобы помочь вам визуализировать это, представьте, что вы находитесь внутри куба. Куб имеет 6 граней, на каждой из которых нарисован круг. 2 грани ниже и выше вас — это плоскости xz; справа и слева от вас находятся плоскости zy; спереди и сзади — знакомые плоскости xy.

Ваш пример представляет собой вращение вокруг центра круга, нарисованного на плоскости xz. Когда самолет рыскает, он, очевидно, не меняет свой шаг. Roll(xy) будет выглядеть примерно так:

position.x -= distance * (float)Math.cos(Math.toRadians(amount));
position.y += distance * (float)Math.sin(Math.toRadians(amount));

Возможно, вам придется изменить знаки, потому что я не уверен, как это реализовано.

На плоскости xy (типичный двухмерный вид), если вы нарисуете круг с радиусом r, любая точка на круге под углом тета может быть задана как P (r * cos (тета), r * sin (тета)). В трехмерном пространстве у вас есть 3 плоскости, и вам придется применить одну и ту же логику ко всем плоскостям, чтобы найти подходящие значения для вращения в этой плоскости.

Однако я не уверен, что вы подразумеваете под «перемещением камеры вперед».

person Valentin    schedule 08.02.2014