<p>In order to orbit the camera around a specific point, you need to have that point available to the function that's doing the orbiting.  So lets have the signatures reflect that...</p>
<pre><code>inline void Camera::horizontalRotationOrbit(const Math::Vec3 &amp; center, Math::Radian angle)
</code></pre>
<p>You want to orbit the point relative to the center of rotation</p>
<pre><code>    auto v = m_position - center;
</code></pre>
<p>Now you need to construct a rotation matrix for the angle.  I don't know what your Math API looks like, but you'll probably want something like</p>
<pre><code>    static const auto UP = Math::Vec3{0, 0, -1};
    auto m = Math::rotate(Math::Mat4{}, angle, UP);
</code></pre>
<p>Most matrix math libraries will include a function like this to build a rotation matrix out of an axis and an angle.</p>
<p>Now you want to actually apply the rotation</p>
<pre><code>    v = m * v;
</code></pre>
<p>And then you want to put it back, relative to the origin, and store the new value.</p>
<pre><code>    m_position = v + center;
 
</code></pre>
<p>Finally, you want to alter the camera direction to account for the rotation</p>
<pre><code>    m_hAngle -= angle;
</code></pre>
<p>This approach should work for horizontal orbiting (yaw around the point), but the vertical orbiting is slightly more complex, because your rotation isn't about a cardinal direction, like the up vector in the previous code.  Instead you need to use <code>m_hAngle</code> to calculate the axis around which to pitch.  Our starting axis is the X axis, around which you normally pitch.</p>
<pre><code>    static const auto LEFT = Math::Vec3{1, 0, 0};
</code></pre>
<p>We want to make a new axis that rotates that by <code>m_hAngle</code>.  The result should still be a unit vector in the XZ plane, and it should be orthogonal to the required pitch direction.</p>
<pre><code>    auto axis = Math::rotate(Math::Mat4{}, m_hAngle, UP) * LEFT;
</code></pre>
<p>We can use this axis to build the final rotation matrix</p>
<pre><code>    auto m = Math::rotate(Math::Mat4{}, angle, axis);
</code></pre>
<p>The rest of the function works the same, rotating your point around <code>m</code> and subtracting the <code>angle</code> value from <code>m_vAngle</code> when you're done.</p>

CC BY-SA 4.0
2024-08-14T02:22:17.483Z
Thank you! I got the horizontal rotation working. However vertical rotation doesnt. I get this: https://youtu.be/znBxppvT5sk
Look at the mouse cursor. When i drag rotation does not follow properly. I disabled horizontal rotation for this test.

Please can you clarify "The rest of the function works the same, rotating your point around m and subtracting the angle value from m_vAngle when you're done." ? Here the current code: https://www.dropbox.com/scl/fi/j6db2s1vjs675xe5t9b30/Camera.cpp?rlkey=1jbs86613yxhqmtl4sb3kezqx&st=kpk2ohea&dl=0
TheChamp
CC BY-SA 4.0
2024-08-12T21:18:44.437Z
2024-08-12T21:18:44.437Z
Jherico
<p>I made C++ rendering application that use one camera. The camera has 3 important members: A position(m_position), an horizontal angle(m_hAngle) and a vertical angle(m_vAngle)</p>
<p>The application currently  support &quot;Fly rotation&quot; whick look like this:<br />
<a href="https://youtu.be/HdyoTcLq7tg" rel="nofollow noreferrer">https://youtu.be/HdyoTcLq7tg</a><br />
When rotation should be applied the camera horizontal and vertical angles are updated, but the position remains the same.</p>
<p>I want to support &quot;Orbit rotation&quot; where the camera position is rotated: <a href="https://youtu.be/Wq0FxFp5cu8" rel="nofollow noreferrer">https://youtu.be/Wq0FxFp5cu8</a></p>
<p>The C++ class look like this:</p>
<pre><code>class Camera
{
public:
    void onMouseMove(const Math::Uvec2&amp; windowSize, const Math::Vec2&amp; mousePos);

    Math::Vec3 getCurrentTarget() const;
    Math::Vec3 getCurrentDirection() const;

    void moveForward(nbFloat32 intensity);

    // Fly mode rotation.
    void horizontalRotationFly(Math::Radian angle);
    void verticalRotationFly(Math::Radian angle);

    // Orbit mode rotation to IMPLEMENT.
    void horizontalRotationOrbit(Math::Radian angle);
    void verticalRotationOrbit(Math::Radian angle);

    Math::Mat4 getViewMatrix() const;

    // Non required code to understand question
    //....
    //
private:
    Math::Vec3 m_up = Math::Vec3(0.0f, 1.0f, 0.0f);

    Math::Vec3 m_position;
    Math::Radian m_hAngle;
    Math::Radian m_vAngle;

    bool m_mousePressed;
};

inline Math::Vec3 Camera::getCurrentTarget() const
{
    return m_position + getCurrentDirection();
}

inline Math::Vec3 Camera::getCurrentDirection() const
{
    // Dont remember where that code is from but it works.
    return glm::normalize(
        Math::Vec3(
            std::cosf(-m_hAngle.getValue()),
            std::tanf(m_vAngle.getValue()),
            std::sin(-m_hAngle.getValue())
        )
    );
}

inline void Camera::moveForward(nbFloat32 intensity)
{
    const Math::Vec3 direction = getCurrentDirection();
    m_position += (direction * intensity);
}


inline Math::Mat4 Camera::getViewMatrix() const
{
    return glm::lookAt(m_position, getCurrentTarget(), m_up);
}
</code></pre>
<p>When mouse is dragged I perform the rotation</p>
<pre><code>void Camera::onMouseMove(const Math::Uvec2&amp; windowSize, const Math::Vec2&amp; mousePos)
{
    if (!m_mousePressed)
        return;

    Math::Vec2 deltaRatio = mousePos - m_currentMousePosition;
    deltaRatio.x /= (nbFloat32)windowSize.x;
    deltaRatio.y /= (nbFloat32)windowSize.y;

    m_currentMousePosition = mousePos;

    static const float rotationSensibility = 2.40f;
    static const bool flyRotation = true;

    if (flyRotation)
    {
        horizontalRotationFly(Math::Radian(-deltaRatio.x * rotationSensibility));
        verticalRotationFly(Math::Radian(-deltaRatio.y * rotationSensibility));
    }
    else
    {
        // HERE to implement
        horizontalRotationOrbit(Math::Radian(-deltaRatio.x * rotationSensibility));
        verticalRotationOrbit(Math::Radian(-deltaRatio.y * rotationSensibility));
    }
}
</code></pre>
<p><strong>The FLY rotation functions are implemented this this:</strong></p>
<pre><code>inline void Camera::horizontalRotationFly(Math::Radian angle)
{
    m_hAngle += angle;
}

inline void Camera::verticalRotationFly(Math::Radian angle)
{
    m_vAngle += angle;
}
</code></pre>
<p><strong>Now I need to implement the ORBIT ones:</strong></p>
<pre><code>inline void Camera::horizontalRotationOrbit(Math::Radian angle)
{
    //TODO.
}

inline void Camera::verticalRotationOrbit(Math::Radian angle)
{
    //TODO.
}
</code></pre>
<p>Thanks for helping!</p>

CC BY-SA 4.0
2024-08-12T03:36:19.337Z
What is it you want your camera to orbit around?  The scene origin?  The unit vector you're using to construct the `at` parameter to `lookat`?  A point in screen space?  All of those have valid, but different answers.
Jherico
CC BY-SA 4.0
2024-08-12T19:06:44.450Z
Hello Jherico,
Thank you very much for helping. Lets say i want to rotate camera around a given point P(Px, Py, Pz)
TheChamp
CC BY-SA 4.0
2024-08-12T19:10:58.933Z
I use a right handed coordinate system:
https://learn.microsoft.com/en-us/previous-versions/windows/desktop/bb324490%28v=vs.85%29
TheChamp
CC BY-SA 4.0
2024-08-13T15:37:33.423Z
I have a code for a 'uv camera': https://github.com/sjhalayka/opengl1_stlview
shawn_halayka
<opengl><vulkan><directx12><directx>
How to orbit rotate a camera from a C++ program?
TheChamp
# How to orbit rotate a camera from a C++ program?

(Asked by: username_0 on 2024-08-12)

I made C++ rendering application that use one camera. The camera has 3 important members: A position(m\_position), an horizontal angle(m\_hAngle) and a vertical angle(m\_vAngle)

The application currently support "Fly rotation" whick look like this:  
<https://youtu.be/HdyoTcLq7tg>  
When rotation should be applied the camera horizontal and vertical angles are updated, but the position remains the same.

I want to support "Orbit rotation" where the camera position is rotated: <https://youtu.be/Wq0FxFp5cu8>

The C++ class look like this:

```
class Camera
{
public:
    void onMouseMove(const Math::Uvec2& windowSize, const Math::Vec2& mousePos);

    Math::Vec3 getCurrentTarget() const;
    Math::Vec3 getCurrentDirection() const;

    void moveForward(nbFloat32 intensity);

    // Fly mode rotation.
    void horizontalRotationFly(Math::Radian angle);
    void verticalRotationFly(Math::Radian angle);

    // Orbit mode rotation to IMPLEMENT.
    void horizontalRotationOrbit(Math::Radian angle);
    void verticalRotationOrbit(Math::Radian angle);

    Math::Mat4 getViewMatrix() const;

    // Non required code to understand question
    //....
    //
private:
    Math::Vec3 m_up = Math::Vec3(0.0f, 1.0f, 0.0f);

    Math::Vec3 m_position;
    Math::Radian m_hAngle;
    Math::Radian m_vAngle;

    bool m_mousePressed;
};

inline Math::Vec3 Camera::getCurrentTarget() const
{
    return m_position + getCurrentDirection();
}

inline Math::Vec3 Camera::getCurrentDirection() const
{
    // Dont remember where that code is from but it works.
    return glm::normalize(
        Math::Vec3(
            std::cosf(-m_hAngle.getValue()),
            std::tanf(m_vAngle.getValue()),
            std::sin(-m_hAngle.getValue())
        )
    );
}

inline void Camera::moveForward(nbFloat32 intensity)
{
    const Math::Vec3 direction = getCurrentDirection();
    m_position += (direction * intensity);
}

inline Math::Mat4 Camera::getViewMatrix() const
{
    return glm::lookAt(m_position, getCurrentTarget(), m_up);
}

```

When mouse is dragged I perform the rotation

```
void Camera::onMouseMove(const Math::Uvec2& windowSize, const Math::Vec2& mousePos)
{
    if (!m_mousePressed)
        return;

    Math::Vec2 deltaRatio = mousePos - m_currentMousePosition;
    deltaRatio.x /= (nbFloat32)windowSize.x;
    deltaRatio.y /= (nbFloat32)windowSize.y;

    m_currentMousePosition = mousePos;

    static const float rotationSensibility = 2.40f;
    static const bool flyRotation = true;

    if (flyRotation)
    {
        horizontalRotationFly(Math::Radian(-deltaRatio.x * rotationSensibility));
        verticalRotationFly(Math::Radian(-deltaRatio.y * rotationSensibility));
    }
    else
    {
        // HERE to implement
        horizontalRotationOrbit(Math::Radian(-deltaRatio.x * rotationSensibility));
        verticalRotationOrbit(Math::Radian(-deltaRatio.y * rotationSensibility));
    }
}

```

**The FLY rotation functions are implemented this this:**

```
inline void Camera::horizontalRotationFly(Math::Radian angle)
{
    m_hAngle += angle;
}

inline void Camera::verticalRotationFly(Math::Radian angle)
{
    m_vAngle += angle;
}

```

**Now I need to implement the ORBIT ones:**

```
inline void Camera::horizontalRotationOrbit(Math::Radian angle)
{
    //TODO.
}

inline void Camera::verticalRotationOrbit(Math::Radian angle)
{
    //TODO.
}

```

Thanks for helping!

**Tags:** opengl, vulkan, directx12, directx

> **Comments:**
> **username_1**: What is it you want your camera to orbit around?  The scene origin?  The unit vector you're using to construct the `at` parameter to `lookat`?  A point in screen space?  All of those have valid, but different answers.  
> **username_0**: Hello username_1, Thank you very much for helping. Lets say i want to rotate camera around a given point P(Px, Py, Pz)  
> **username_0**: I use a right handed coordinate system: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/bb324490%28v=vs.85%29  
> **username_2**: I have a code for a 'uv camera': https://github.com/sjhalayka/opengl1_stlview  

---

## 1 answers

### Answer by username_1 on 2024-08-12. Score: 1

In order to orbit the camera around a specific point, you need to have that point available to the function that's doing the orbiting. So lets have the signatures reflect that...

```
inline void Camera::horizontalRotationOrbit(const Math::Vec3 & center, Math::Radian angle)

```

You want to orbit the point relative to the center of rotation

```
    auto v = m_position - center;

```

Now you need to construct a rotation matrix for the angle. I don't know what your Math API looks like, but you'll probably want something like

```
    static const auto UP = Math::Vec3{0, 0, -1};
    auto m = Math::rotate(Math::Mat4{}, angle, UP);

```

Most matrix math libraries will include a function like this to build a rotation matrix out of an axis and an angle.

Now you want to actually apply the rotation

```
    v = m * v;

```

And then you want to put it back, relative to the origin, and store the new value.

```
    m_position = v + center;
 

```

Finally, you want to alter the camera direction to account for the rotation

```
    m_hAngle -= angle;

```

This approach should work for horizontal orbiting (yaw around the point), but the vertical orbiting is slightly more complex, because your rotation isn't about a cardinal direction, like the up vector in the previous code. Instead you need to use `m_hAngle` to calculate the axis around which to pitch. Our starting axis is the X axis, around which you normally pitch.

```
    static const auto LEFT = Math::Vec3{1, 0, 0};

```

We want to make a new axis that rotates that by `m_hAngle`. The result should still be a unit vector in the XZ plane, and it should be orthogonal to the required pitch direction.

```
    auto axis = Math::rotate(Math::Mat4{}, m_hAngle, UP) * LEFT;

```

We can use this axis to build the final rotation matrix

```
    auto m = Math::rotate(Math::Mat4{}, angle, axis);

```

The rest of the function works the same, rotating your point around `m` and subtracting the `angle` value from `m_vAngle` when you're done.

> **Comments:**
> **username_0**: Thank you! I got the horizontal rotation working. However vertical rotation doesnt. I get this: https://youtu.be/znBxppvT5sk Look at the mouse cursor. When i drag rotation does not follow properly. I disabled horizontal rotation for this test.  Please can you clarify "The rest of the function works the same, rotating your point around m and subtracting the angle value from m_vAngle when you're done." ? Here the current code: https://www.dropbox.com/scl/fi/j6db2s1vjs675xe5t9b30/Camera.cpp?rlkey=1jbs86613yxhqmtl4sb3kezqx&st=kpk2ohea&dl=0  

---

