GAM200L1 / Purring_Engine

Purring_Engine is a custom 2D game engine developed in C++ with OpenGL
0 stars 0 forks source link

Camera system #144

Open krystalyamin opened 1 year ago

krystalyamin commented 1 year ago

Rubric Items: 1108 (Critical), 1208 (Advanced)

Acceptance Criteria:

Stretch Goals:

krystalyamin commented 1 year ago

References

krystalyamin commented 1 year ago

I was debugging an issue where, when the camera was rotated and the viewport did not have a square aspect ratio (i.e. not 1:1), the image would appear stretched.

Image

I tried a few different alternatives to generating my world to view and view to NDC matrices, thinking this was the issue. It turned out that I was just multiplying the world to view and view to NDC matrices in the wrong order. pain.

In order to ensure that all the alt methods I've found don't go to waste, I'm going to immortalize them here.

Manual creation of matrices from Graphics Tutorial 4

    float scaleReciprocal{ 1.f / m_magnification };
    glm::vec2 up{ GetUpVector(r_transform) };
    up *= scaleReciprocal;
    glm::vec2 right{ up.y, -up.x };

    float upDotPosition{ up.x * r_transform.position.x + up.y * r_transform.position.y };
    float rightDotPosition{ right.x * r_transform.position.x + right.y * r_transform.position.y };

    // Update the cached values
    glm::mat4 worldToViewMatrix{
        right.x, up.x, 0.f, 0.f,
        right.y, up.y, 0.f, 0.f,
        0.f,    0.f,   1.f, 0.f,
        -rightDotPosition, -upDotPosition, 0.f, 1.f
    };

    glm::mat4 viewToNdcMatrix {
        2.f / m_viewportWidth, 0.f, 0.f, 0.f,
        0.f, 2.f / m_viewportHeight, 0.f, 0.f,
        0.f, 0.f, 1.f, 0.f,
        0.f, 0.f, 0.f, 1.f,
    };

    return viewToNdcMatrix * worldToViewMatrix;

Using GLM's helper methods

    glm::vec2 up{ -glm::sin(m_orientation), glm::cos(m_orientation) };

    glm::mat4 worldToViewMatrix { glm::lookAt(
        glm::vec3{ r_transform.position.x, r_transform.position.y, 0.f },
        glm::vec3{ r_transform.position.x, r_transform.position.y, -1.f },
        glm::vec3{ up.x, up.y, 0.f }
    )};

    float halfWidth{ m_viewportWidth * 0.5f };
    float halfHeight{ m_viewportHeight * 0.5f };

    glm::mat4 viewToNdcMatrix { glm::ortho(-halfWidth, halfWidth, -halfHeight, halfHeight, -1.f, 1.f) };

    return viewToNdcMatrix * worldToViewMatrix;
krystalyamin commented 1 year ago

As of commit [branch feature-cameraSystem commit 3cadac7]

Image

When the editor windows are active, an internal editor camera is used to render the scene. When the editor windows are toggled off (by pressing ESC), the main runtime camera is used instead.

2 runtime cameras are spawned in the scene when the engine is initialized.

  1. The first camera object follows the player object,
  2. The second camera stays stationary, but its transform can be adjusted through the component window. Only one runtime camera will be used to render the scene at a time (the "main" camera). You can swap between the two cameras using the Middle Mouse Button.

If debug objects are enabled, objects with camera components will have a purple cross "+" rendered at the position of the camera. The vertical line is oriented to the up vector of the camera, and the horizontal line is oriented to the right vector of the camera.

If no cameras exist in the object list, only the background colour (light brown) will be rendered. There is currently no way to add new cameras to the scene if all the existing cameras have been deleted.

Controls

Editor Camera Control

Control Action
ESC Key Close the editor windows and switch the camera to the main runtime camera
Up, Down, Left, Right Keys Move the editor camera along the world axes
Scroll middle mouse button Zoom in and out of the scene
Comma Key Rotate the editor camera counter-clockwise
Period Key Rotate the editor camera clockwise

Player Controls

Control Action
W, A, S, D Keys Move the player along the world axes
Z Key Rotate player counter-clockwise
X Key Rotate player clockwise

Runtime Camera Controls

Control Action
Click middle mouse button Swap between the two runtime camera objects in the scene
C Key Zoom the active runtime camera out
V Key Zoom the active runtime camera in

Nice things to add on in the future: