Skip to main content
Tweeted twitter.com/StackCodeReview/status/1244685915659919361
Became Hot Network Question
Minor cleanup
Source Link
1201ProgramAlarm
  • 7.8k
  • 2
  • 23
  • 39

As a hobby I am working on a game engine in order to learn c++C++ and graphics programming, now I have completed my first iteration of my camera system using OpengGL and GLM. Because I am mostly self taught I am searching for some feedback.

// MainCamera.cpp
#include "MainCamera.h"

using namespace cheetah;
using namespace math;
using namespace input;

MainCamera::MainCamera(const cheetah::PerspectiveCameraParams& params)
    : CameraController(params)
{
}

bool MainCamera::onWindowResize(const WindowResizeEvent& event)
{
    setAspectRatio((float)event.m_width, (float)event.m_height);
    return true;
}

void MainCamera::onUpdate(const float& deltaTime)
{
    handleKeyInput(deltaTime);
}

void MainCamera::handleKeyInput(const float& deltaTime)
{
    // reset
    if (Input::isKeyPressed(keys::R))
    {
        setPosition(vec3(0.0f, 0.0f, 0.0));
    }

    // moving
    if (Input::isKeyPressed(keys::W))
    {
        translate(vec3(0.0f, -(0.001f * deltaTime), 0.0f));
    }
    if (Input::isKeyPressed(keys::A))
    {
        translate(vec3(-(0.001f * deltaTime), 0.0f, 0.0f));
    }
    if (Input::isKeyPressed(keys::S))
    {
        translate(vec3(0.0f, 0.001f * deltaTime, 0.0f));
    }
    if (Input::isKeyPressed(keys::D))
    {
        translate(vec3(0.001f * deltaTime, 0.0f, 0.0f));
    }

    // rotating
    if (Input::isKeyPressed(keys::Q))
    {
        rotate(-(0.001f * deltaTime), vec3(0, 1, 0));
    }
    if (Input::isKeyPressed(keys::E))
    {
        rotate(0.001f * deltaTime, vec3(0, 1, 0));
    }
    if (Input::isKeyPressed(keys::Z))
    {
        translate(vec3(0.0f, 0.0f, 0.001f * deltaTime));
    }
    if (Input::isKeyPressed(keys::X))
    {
        translate(vec3(0.0f, 0.0f, -(0.001f * deltaTime)));
    }
}
```

As a hobby I am working on a game engine in order to learn c++ and graphics programming, now I have completed my first iteration of my camera system using OpengGL and GLM. Because I am mostly self taught I am searching for some feedback.

// MainCamera.cpp
#include "MainCamera.h"

using namespace cheetah;
using namespace math;
using namespace input;

MainCamera::MainCamera(const cheetah::PerspectiveCameraParams& params)
    : CameraController(params)
{
}

bool MainCamera::onWindowResize(const WindowResizeEvent& event)
{
    setAspectRatio((float)event.m_width, (float)event.m_height);
    return true;
}

void MainCamera::onUpdate(const float& deltaTime)
{
    handleKeyInput(deltaTime);
}

void MainCamera::handleKeyInput(const float& deltaTime)
{
    // reset
    if (Input::isKeyPressed(keys::R))
    {
        setPosition(vec3(0.0f, 0.0f, 0.0));
    }

    // moving
    if (Input::isKeyPressed(keys::W))
    {
        translate(vec3(0.0f, -(0.001f * deltaTime), 0.0f));
    }
    if (Input::isKeyPressed(keys::A))
    {
        translate(vec3(-(0.001f * deltaTime), 0.0f, 0.0f));
    }
    if (Input::isKeyPressed(keys::S))
    {
        translate(vec3(0.0f, 0.001f * deltaTime, 0.0f));
    }
    if (Input::isKeyPressed(keys::D))
    {
        translate(vec3(0.001f * deltaTime, 0.0f, 0.0f));
    }

    // rotating
    if (Input::isKeyPressed(keys::Q))
    {
        rotate(-(0.001f * deltaTime), vec3(0, 1, 0));
    }
    if (Input::isKeyPressed(keys::E))
    {
        rotate(0.001f * deltaTime, vec3(0, 1, 0));
    }
    if (Input::isKeyPressed(keys::Z))
    {
        translate(vec3(0.0f, 0.0f, 0.001f * deltaTime));
    }
    if (Input::isKeyPressed(keys::X))
    {
        translate(vec3(0.0f, 0.0f, -(0.001f * deltaTime)));
    }
}
```

As a hobby I am working on a game engine in order to learn C++ and graphics programming, now I have completed my first iteration of my camera system using OpengGL and GLM. Because I am mostly self taught I am searching for some feedback.

// MainCamera.cpp
#include "MainCamera.h"

using namespace cheetah;
using namespace math;
using namespace input;

MainCamera::MainCamera(const cheetah::PerspectiveCameraParams& params)
    : CameraController(params)
{
}

bool MainCamera::onWindowResize(const WindowResizeEvent& event)
{
    setAspectRatio((float)event.m_width, (float)event.m_height);
    return true;
}

void MainCamera::onUpdate(const float& deltaTime)
{
    handleKeyInput(deltaTime);
}

void MainCamera::handleKeyInput(const float& deltaTime)
{
    // reset
    if (Input::isKeyPressed(keys::R))
    {
        setPosition(vec3(0.0f, 0.0f, 0.0));
    }

    // moving
    if (Input::isKeyPressed(keys::W))
    {
        translate(vec3(0.0f, -(0.001f * deltaTime), 0.0f));
    }
    if (Input::isKeyPressed(keys::A))
    {
        translate(vec3(-(0.001f * deltaTime), 0.0f, 0.0f));
    }
    if (Input::isKeyPressed(keys::S))
    {
        translate(vec3(0.0f, 0.001f * deltaTime, 0.0f));
    }
    if (Input::isKeyPressed(keys::D))
    {
        translate(vec3(0.001f * deltaTime, 0.0f, 0.0f));
    }

    // rotating
    if (Input::isKeyPressed(keys::Q))
    {
        rotate(-(0.001f * deltaTime), vec3(0, 1, 0));
    }
    if (Input::isKeyPressed(keys::E))
    {
        rotate(0.001f * deltaTime, vec3(0, 1, 0));
    }
    if (Input::isKeyPressed(keys::Z))
    {
        translate(vec3(0.0f, 0.0f, 0.001f * deltaTime));
    }
    if (Input::isKeyPressed(keys::X))
    {
        translate(vec3(0.0f, 0.0f, -(0.001f * deltaTime)));
    }
}
Source Link

A camera controller API for my game engine

As a hobby I am working on a game engine in order to learn c++ and graphics programming, now I have completed my first iteration of my camera system using OpengGL and GLM. Because I am mostly self taught I am searching for some feedback.

I am mostly searching for feedback regarding the following points:

  • Is the API easy to understand/implement by another user
  • Are there any obvious mistakes made regarding performance
  • Are there any missing features you would suspect to be in a camera controller
  • Is the API consistent regarding code style and practices

But of course any other feedback is also much appreciated!

Perspective Camera
Low level, responsible for the projection matrix

// PerspectiveCamera.h
#ifndef CHEETAH_ENGINE_RENDERER_PERSPECTIVECAMERA_H_
#define CHEETAH_ENGINE_RENDERER_PERSPECTIVECAMERA_H_

#include "Core/Core.h"
#include "Events/ApplicationEvents.h"
#include "Camera.h"

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

namespace cheetah
{
    struct PerspectiveCameraParams
    {
        const float radians = 45.0f;
        const float zNear = -1.0f;
        const float zFar = 1.0f;
        const float aspectRatio;
        const float zoom;
        const glm::vec3 position = glm::vec3(0.0f);
        const glm::vec3 rotationAxis = glm::vec3(1.0f);
        const float rotationDegrees = 0.0f;
    };

    class CH_API PerspectiveCamera : public Camera
    {
    public:
        PerspectiveCamera(const PerspectiveCameraParams& params);


        inline glm::mat4 getViewProjectionMatrix() const override { return m_viewProjectionMatrix; };
        inline glm::mat4 getProjectionMatrix() const override { return m_projectionMatrix; };
        inline glm::mat4 getViewMatrix() const override { return m_viewMatrix; };
        inline float getZoom() const override { return m_zoom; };
        inline float getAspectRatio() const override { return m_aspectRatio; };

        void setZoom(const float& zoom) override;
        void setAspectRatio(const float& aspectRatio) override;
        void setViewMatrix(const glm::mat4& viewMatrix) override;

        void recalculateViewProjectionMatrix() override;

    private:
        float m_aspectRatio;
        float m_zoom;
        float m_zNear;
        float m_zFar;
        float m_radians;
        glm::mat4 m_projectionMatrix;
        glm::mat4 m_viewMatrix;
        glm::mat4 m_viewProjectionMatrix;
    };
}

#endif // !CHEETAH_ENGINE_RENDERER_PERSPECTIVECAMERA_H_
// PerspectiveCamera.cpp
#include "PerspectiveCamera.h"

namespace cheetah
{
    PerspectiveCamera::PerspectiveCamera(const PerspectiveCameraParams& params)
        :
        m_projectionMatrix(glm::perspective(glm::radians(params.radians), params.aspectRatio, params.zNear, params.zFar)),
        m_viewMatrix(glm::rotate(glm::translate(glm::mat4(1.0f), params.position), params.rotationDegrees, params.rotationAxis)),
        m_viewProjectionMatrix(m_projectionMatrix* m_viewMatrix),
        m_aspectRatio(params.aspectRatio),
        m_zoom(params.zoom),
        m_zNear(params.zNear),
        m_zFar(params.zFar),
        m_radians(params.radians)
    {
    }

    void PerspectiveCamera::setViewMatrix(const glm::mat4& viewMatrix)
    {
        m_viewMatrix = viewMatrix;
        recalculateViewProjectionMatrix();
    }

    void PerspectiveCamera::setZoom(const float& zoom)
    {
        m_zoom = zoom;
        m_projectionMatrix = glm::perspective(glm::radians(m_radians += m_zoom), m_aspectRatio, m_zNear, m_zFar);
        recalculateViewProjectionMatrix();
    }

    void PerspectiveCamera::setAspectRatio(const float& aspectRatio)
    {
        m_aspectRatio = aspectRatio;
        m_projectionMatrix = glm::perspective(glm::radians(m_radians), aspectRatio, m_zNear, m_zFar);
        recalculateViewProjectionMatrix();
    }

    void PerspectiveCamera::recalculateViewProjectionMatrix()
    {
        m_viewProjectionMatrix = m_projectionMatrix * m_viewMatrix;
    }
}

CameraController Higher level, doesn't care about camera type(ortho or perspective)

// CameraController.h
#ifndef CHEETAH_ENGINE_RENDERER_CAMERACONTROLLER_H_
#define CHEETAH_ENGINE_RENDERER_CAMERACONTROLLER_H_

#include "Core/Core.h"
#include "Camera.h"
#include "OrthoGraphicCamera.h"
#include "PerspectiveCamera.h"

#include <glm/gtc/matrix_transform.hpp>
#include <glm/glm.hpp>

#include <memory>

namespace cheetah
{
    class CH_API CameraController
    {
    public:
        CameraController(const OrthoGraphicCameraParams& params);
        CameraController(const PerspectiveCameraParams& params);

        // affect ProjectionMatrix
        void setZoom(const float& zoom);
        void setAspectRatio(const float& width, const float& height);

        // affect ViewMatrix
        void setPosition(const glm::vec3& position);
        void translate(const glm::vec3& position);
        void rotate(const float& degrees, const glm::vec3& axis);

        inline float getZoom() const { return m_camera->getZoom(); };
        inline float getAspectRatio() const { return m_camera->getAspectRatio(); };
        inline glm::vec3 getPosition() const { return m_position; };
        inline glm::vec3 getRotationAxis() const { return m_rotationAxis; };
        inline float getRotationDegrees() const { return m_rotationDegrees; };
        inline Camera& getCamera() const { return *m_camera; };
    private:
        float m_rotationDegrees;
        glm::vec3 m_rotationAxis;
        glm::vec3 m_position;
        std::unique_ptr<Camera> m_camera;
    };
}

#endif // !CHEETAH_ENGINE_RENDERER_CAMERACONTROLLER_H_
// CameraController.cpp
#include "CameraController.h"

namespace cheetah
{
    CameraController::CameraController(const OrthoGraphicCameraParams& params)
        :
        m_camera(std::make_unique<OrthoGraphicCamera>(params)),
        m_position(params.position),
        m_rotationAxis(params.rotationAxis),
        m_rotationDegrees(params.rotationDegrees)
    {
    }

    CameraController::CameraController(const PerspectiveCameraParams& params)
        :
        m_camera(std::make_unique<PerspectiveCamera>(params)),
        m_position(params.position),
        m_rotationAxis(params.rotationAxis),
        m_rotationDegrees(params.rotationDegrees)
    {
    }

    void CameraController::setZoom(const float& zoom)
    {
        m_camera->setZoom(zoom);
    }

    void CameraController::setAspectRatio(const float& width, const float& height)
    {
        m_camera->setAspectRatio(width / height);
    }

    void CameraController::setPosition(const glm::vec3& position)
    {
        m_position = position;
        m_camera->setViewMatrix(glm::rotate(glm::translate(glm::mat4(1.0f), position), m_rotationDegrees, m_rotationAxis));
    }

    void CameraController::translate(const glm::vec3& position)
    {
        m_position = position;
        m_camera->setViewMatrix(glm::translate(m_camera->getViewMatrix(), m_position));
    }

    void CameraController::rotate(const float& degrees, const glm::vec3& axis)
    {
        m_rotationDegrees = degrees;
        m_rotationAxis = axis;
        m_camera->setViewMatrix(glm::rotate(m_camera->getViewMatrix(), degrees, axis));
    }
}

Implementation
Here a possible way of implementing the CameraController

// MainCamera.h
#ifndef GAME_MAINCAMERA_H_
#define GAME_MAINCAMERA_H_

#include "Cheetah.h"

class MainCamera : public cheetah::CameraController
{
public:
    MainCamera(const cheetah::PerspectiveCameraParams& params);
    void onUpdate(const float& deltaTime);
    bool onWindowResize(const cheetah::WindowResizeEvent& event);
private:
    void handleKeyInput(const float& deltaTime);
};

#endif // !GAME_MAINCAMERA_H_

// MainCamera.cpp
#include "MainCamera.h"

using namespace cheetah;
using namespace math;
using namespace input;

MainCamera::MainCamera(const cheetah::PerspectiveCameraParams& params)
    : CameraController(params)
{
}

bool MainCamera::onWindowResize(const WindowResizeEvent& event)
{
    setAspectRatio((float)event.m_width, (float)event.m_height);
    return true;
}

void MainCamera::onUpdate(const float& deltaTime)
{
    handleKeyInput(deltaTime);
}

void MainCamera::handleKeyInput(const float& deltaTime)
{
    // reset
    if (Input::isKeyPressed(keys::R))
    {
        setPosition(vec3(0.0f, 0.0f, 0.0));
    }

    // moving
    if (Input::isKeyPressed(keys::W))
    {
        translate(vec3(0.0f, -(0.001f * deltaTime), 0.0f));
    }
    if (Input::isKeyPressed(keys::A))
    {
        translate(vec3(-(0.001f * deltaTime), 0.0f, 0.0f));
    }
    if (Input::isKeyPressed(keys::S))
    {
        translate(vec3(0.0f, 0.001f * deltaTime, 0.0f));
    }
    if (Input::isKeyPressed(keys::D))
    {
        translate(vec3(0.001f * deltaTime, 0.0f, 0.0f));
    }

    // rotating
    if (Input::isKeyPressed(keys::Q))
    {
        rotate(-(0.001f * deltaTime), vec3(0, 1, 0));
    }
    if (Input::isKeyPressed(keys::E))
    {
        rotate(0.001f * deltaTime, vec3(0, 1, 0));
    }
    if (Input::isKeyPressed(keys::Z))
    {
        translate(vec3(0.0f, 0.0f, 0.001f * deltaTime));
    }
    if (Input::isKeyPressed(keys::X))
    {
        translate(vec3(0.0f, 0.0f, -(0.001f * deltaTime)));
    }
}
```