c ++ – 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 mainly self-taught, I look for comments.

I mainly seek feedback on the following points:

  • Is the API easy to understand / implement by another user
  • Are there obvious performance errors
  • Are there any missing features that you suspect to be in a camera controller
  • Is the API consistent with regard to code style and practices

But of course, any other comments are also greatly 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, regardless of the type of camera (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 
#include 

#include 

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 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(params)),
        m_position(params.position),
        m_rotationAxis(params.rotationAxis),
        m_rotationDegrees(params.rotationDegrees)
    {
    }

    CameraController::CameraController(const PerspectiveCameraParams& params)
        :
        m_camera(std::make_unique(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 is a possible way to implement 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)));
    }
}

Recommended equipment – What medium format film camera should an SLR guy watch?

The Mamiya RB67 will be a very good candidate for what you need.

The 6×7 is "almost" 6×6, you have the option to crop.

Make sure you get a good feedback, preferably a pro-sd. I have had 2 pro-s backs (ugly state) and one of them has strange light leaks which I still haven't been able to fix with gaskets. I just received a 120 pro-sd like new and it should make me happy.

The cost of the film is nothing compared to the pleasure you feel, taking your time to compose and shoot. Digital somewhat takes away the pleasure of "slowness".

Appreciate and report what you have chosen and how you like it.

cleaning – How do I remove dirt from inside the lens system of a compact camera?

Context

I have a compact Panasonic Lumix camera, which, out of nowhere, caught a little dirt between the lenses or on the sensor.
I made sure it wasn’t sure outside the lens.
During the (optical) zoom, it did not change in size or position, but at best became more or less diffuse (but never sharp).
Here's what the bottom left quarter of a photo looked like:

lower left quarter of a photo

I have tried to expose the camera to moderate forces (shake, rotation) at different lens positions (i.e. optical zoom levels), but the particle did not move at all.
I have not opened the camera.

Then when I tried to take another photo to show you the effect, the thing disappeared as suddenly as it came.
Obviously, I did something that I made move, but I do not know what.

Years later, this happened again. Here is the bottom right corner of a photo of a white background:

lower right quarter of a photo

Real question

My problem was solved by luck, but I wonder what targeted efforts I could have made. So I ask: If a piece of dirt gets stuck somewhere in the optical path of a compact camera, what are the possible actions that can remove it? I am only interested in solutions which do not involve disassembly of the device.

unit – Rigidbody seems to tremble when placed as a brother to a first-person camera

In my game, the player can pick up an object (which is related to the camera in the first person), or the player can push an object (which is related to the player, but not his camera in the first person). Both mechanics use very similar implementations when it comes to moving objects, but I get a fairly large amount of “ perceived '' jitter. Pushing – the object, as far as I know, is not actually shaky.

(Side note – I didn't know where to download images, so I used mega ones which can be used just to view the images)

Thrust images, with visible jitter

Elevator images for comparison

Thrust images but related to the camera in the first person

Frame-by-frame push images from the side at a scale of 0.50

Frame-by-frame elevator images at a scale of 0.50

The object is moved to FixedUpdate and the camera is moved to LateUpdate. You can see quite clearly that in the side view, the camera is moving after the object. Since the object is the parent of the camera on Lift, it moves with it and no change is seen. However, on Push, it does not move and therefore seems to tremble.

I do not know how to solve this problem. I have tried:

  • Allow interpolation on the rigid body,
  • Disable gravity on the rb / take off from the ground (for example, not caused by a collision with the ground),
  • Do not parent the object at all to the reader (the object is always perceived as trembling because the camera moves in LateUpdate out of synchronization with the object)
  • Object parenting on camera (but this is not intentional as they are only meant to push causes all kinds of rotation problems etc. – but the jitter is stop as seen in the third link),
  • The following code in LateUpdate to push it forward –
    protected void CheckCameraPosition()
    {
        if (m_LastCameraPosition == Vector3.zero)
            return;

        Vector3 newPosition = m_FPCamera.Transform.position;
        if (newPosition == m_LastCameraPosition)
            return;

        Vector3 newOffset = newPosition - m_LastCameraPosition;
        newOffset.y = 0f;
        Transform.position += newOffset;
    }

But the object is still shaking and if I were to seriously consider the above code, I would be worried about the racing conditions since the camera movement is also executed in LateUpdate.

camera – FUJIFILM X-T4 live streaming capabilities

I'm trying to find out how useful the FUJIFILM X-T4 will be as a streaming device.

According to the specifications, it is capable of recording a decent DCI4K 60 fps 10bits.

It is also capable of transmitting them correctly via the HDMI interface.

It has a USB port which should technically be able to transmit video while acting as UVC (Look Sigma fp for example)
Instead, it appears that only Tethering mode is available (via USB or Wi-Fi). I discovered that it could be the PTP protocol.

So here are my questions:
What is "thethering mode" What are the properties of the PTP image?

Please correct the tags, I could not find the correct one
Asked there too: https://video.stackexchange.com/questions/29795/fujifilm-x-t4-live-stream-capabilites

unit – How to cache the main camera as a global variable?

You must use an example below to call FindGameObjectWithTag every time:

    public static Camera MainCamera => Camera.main;

In your example, the camera is assigned once.

Although there is a problem with static: their initialization is not the same as normal, with Unity it is difficult to find a deterministic way to check when the camera is actually affected. It can be in Edit mode or when the camera is not yet created. If the camera is destroyed or the scene is changed (and you are not using DontDestroyOnLoad), you will get exceptions on missing calls MainCamera.

Consider an assignment directly from the camera controller:

public class CameraController : Monobehaviour {

    private void Awake() {
        Utils.MainCamera = GetComponent();
    }
}

Obviously, MainCamera will need an audience set; for that.

This way you can guarantee that the camera is assigned exactly the time it is initialized during runtime. Any new CameraController will replace the previous one (if the old one is destroyed, for example).

It is doubtful to introduce such things when you have already Camera.main, although the static reference would work slightly faster. This trick also allows you to create references to any object without global access.

I would also like to note that creating global references and utility classes is not considered best practice. It's pretty amazing how much you can configure benchmarks with singletons and statistics, but it creates dependencies that are difficult to modify, delete, and test. And probably more difficult to understand. Choose wisely!

The zoom ring on my Nikon D5300 does not rotate and the camera keeps saying that the error lens is not attached

The zoom ring on my Nikon D5300 does not rotate and I get an error on the camera stating that the lens is not attached. I have tried everything. I was zooming in for a photo and when I tried to zoom out, the zoom ring did not move. Help me, please.

How to have a fake camera on Ubuntu without having a real physical camera?

I am writing a module that uses chrome to allow access to the camera. However, this will be deployed on computers without a real camera, so Google Chrome won't even ask for permission.

Note that using chrome settings to start is not an option. I need to install something in ubuntu which will serve as a fake camera detectable by Chrome.

Is it possible and how?

computer vision – Using a rotation matrix to transform / shift a pinhole camera

I have a pinhole camera model with the following extrinsic parameters (in the Earth Centered system, Earth Fixed Coordinate, (ECEF)) and intrinsic.

focal length (x, y) = 55000 px, optical center = (2400540)

camera center (x, y, z), (ground coordinates) = -2322996.2171387854 -3875494.0767072071 5183320.6008059494 (ECEF)

Rotation matrix (3×3, from camera to mass frame) = ((0.89882706839551795, -0.45517069374030594, 0.032053516353234932), (-0.44472722029994571, -0.84940151315102252, 0.28413864394171567), (-0 , 102708972-0707.88

I need to move the camera so that it points to the right position on the ground based on an ECEF transformation matrix (4 X 4), which looks like this:

((0.99999922456661872, 0.00043965959331068635, -0.0011651461883787318, 7033,5303197340108),
(-0.00044011741039666426, 0.99999982604190574, -0.00039269946235032278, 814.02427618065849),
(0.0011649733316053631, 0.00039321195895935108, 0.99999924411047925, 4139.9400998316705), (0, 0, 0, 1))

The 3 x 3 matrix part formed by the first three rows and columns is the rotation component, the first three values ​​in the last column are the translation component. My general understanding is that I need to add the translation component to the center coordinates of the camera, while multiplying the rotation matrix of the camera on the ground with the rotation component. Is this enough or should I do something more?

Macbook Pro mid-2012 camera does not work

HDD to SSD recently replaced. After replacing it, the camera stopped working – the green light is not displayed. When I open the FaceTime app, I only see a black screen.