LWJGL Преместване на камерата към това, което гледате

От доста време търся и не мога да намеря отговор на този на пръв поглед лесен въпрос. Имам 3d пространство и камерата ми има променливи 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;

Забележка: rotation.y = yaw, rotation.x = pitch, rotation.z би било roll. Разстоянието е просто колко да се движите, да кажем 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 завъртания: въртене, отклонение и наклон. Те също могат да се представят като точки върху диск, начертан върху плоска равнина в 3D пространство: xy-равнина (наклон), xz-равнина (yaw), zy-равнина (наклон).

За да ви помогнем да визуализирате това, представете си, че сте вътре в куб. Кубът има 6 лица, върху всяко от които е нарисуван кръг. Двете лица под и над вас са равнините xz; отдясно и отляво са равнините zy; отпред и отзад са познатите xy равнини.

Вашият пример е въртене около центъра на кръг, начертан в равнината xz. Когато самолетът се завърта, той очевидно не променя наклона си. Преобръщане (xy) ще изглежда нещо като:

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

Може да се наложи да смените знаците, защото не съм сигурен как се прилага това.

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

Не съм сигурен обаче какво имате предвид под „преместване на камерата напред“.

person Valentin    schedule 08.02.2014