1
\$\begingroup\$

I'm looking for a basic example of rotating camera using the mouse. the only problem is I'm not sure of how to rotating the camera around it target. should i do this by an algorithm or is there a method of doing this? I am also only using managed dirextx and no wrappers

\$\endgroup\$
1
\$\begingroup\$

A very short cutoff tk fhis problem, if you don't want to use trigonometry, is to first translate the view matrix with the distance between the camera and the player on the +z axis, then rozate the matrix, and after that, move it to the correct place, by translating it to the player's position.

However, this is the worst and laziest solution I could think of, so if you want to have a method, that makes sort of sense, then use trigonometry.

You will need the angle aeound the y and x axis, in my example, i refer them to as xa, and ya, they also need to be in radians.

x = cos(xa) * cos(ya) y = sin(xa) * cos(ya) z = sin(ya)

To create a view matrix, first, you simply need a 4 * 4 identity matrix, then translate in the negative direction with the distance you want between the camera and player, in this example, 5.

1 0 0  0
0 1 0  0
0 0 1 -5
0 0 0  0

After this is done, rotate it on the y and x axis. The y angle is the angle around the player, the x is the "distance" from the ground.

You then multiply these matrices together

translateMatrix * rotationMatrix //Note: By doing the multiplication the other way around messes up things, so be aware

Now, you have it around the player. Only problem is, that it is placed according to the player, not the world coordinates, So, you need to translate it. The translation matrix should be made like

1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1

where x, y and z are the player position. After this, you simply multiply the two matrices together, and voilá, you're done.

I can't help in retrieving mouse coordinates in DirectX, because I never actually used it, only OpenGL, I'm just a math guy. My way of doing it would be to always get the distance between the middle of the screen, and the mouse, and do things according to that, and finally, place the mouse back at the middle of the screen.

\$\endgroup\$
  • \$\begingroup\$ any examples of using the matrix? and thanks \$\endgroup\$ – SukottoSama Jan 25 '16 at 20:36
  • \$\begingroup\$ You probably know what a matrix is, if you're making a 3D game, and you also should know, how create a view matrix. I edit it in the post \$\endgroup\$ – Bálint Jan 26 '16 at 15:41
0
\$\begingroup\$

A classic solution is to use an arcball.

Here's an example implementation using the SimpleMath wrapper for DirectXMath in the DirectX Tool Kit:

class ArcBall
{
public:
    ArcBall() :
        m_width(800.f),
        m_height(400.f),
        m_radius(1.f),
        m_drag(false) { Reset();  }

    void Reset()
    {
        m_qdown = m_qnow = DirectX::SimpleMath::Quaternion::Identity;
    }

    void OnBegin( int x, int y )
    {
        m_drag = true;
        m_qdown = m_qnow;
        m_downPoint = ScreenToVector(float(x), float(y));
    }

    void OnMove(int x, int y)
    {
        using namespace DirectX;
        if (m_drag)
        {
            XMVECTOR curr = ScreenToVector(float(x), float(y));

            m_qnow = XMQuaternionMultiply(m_qdown, QuatFromBallPoints(m_downPoint, curr));
            m_qnow.Normalize();
        }
    }

    void OnEnd()
    {
        m_drag = false;
    }

    void SetWindow(int width, int height)
    {
        m_width = float(width);
        m_height = float(height);
    }

    void SetRadius(float radius)
    {
        m_radius = radius;
    }

    DirectX::SimpleMath::Quaternion GetQuat() const { return m_qnow; }

    bool IsDragging() const { return m_drag; }

private:
    float                           m_width;
    float                           m_height;
    float                           m_radius;
    DirectX::SimpleMath::Quaternion m_qdown;
    DirectX::SimpleMath::Quaternion m_qnow;
    DirectX::SimpleMath::Vector3    m_downPoint;
    bool                            m_drag;

    DirectX::XMVECTOR ScreenToVector(float screenx, float screeny)
    {
        float x = -( screenx - m_width / 2.f ) / ( m_radius * m_width / 2.f );
        float y = ( screeny - m_height / 2.f ) / ( m_radius * m_height / 2.f );

        float z = 0.0f;
        float mag = x * x + y * y;

        if( mag > 1.0f )
        {
            float scale = 1.0f / sqrtf( mag );
            x *= scale;
            y *= scale;
        }
        else
            z = sqrtf( 1.0f - mag );

        return DirectX::XMVectorSet( x, y, z, 0 );
    }

    static DirectX::XMVECTOR QuatFromBallPoints( DirectX::FXMVECTOR vFrom, DirectX::FXMVECTOR vTo )
    {
        using namespace DirectX;
        XMVECTOR dot = XMVector3Dot( vFrom, vTo );
        XMVECTOR vPart = XMVector3Cross( vFrom, vTo );
        return XMVectorSelect( dot, vPart, g_XMSelect1110 );
    }
};

To use this class:

ArcBall m_ballCamera;

m_ballCamera.SetWindow(m_outputWidth, m_outputHeight);

if (m_ballCamera.IsDragging())
{
    // Rotate camera
    m_ballCamera.OnMove(mouse.x, mouse.y);
    Quaternion q = m_ballCamera.GetQuat();
    q.Inverse(m_cameraRot);
}
else if (m_mouseButtonTracker.leftButton == Mouse::ButtonStateTracker::PRESSED)
{
    m_ballCamera.OnBegin(mouse.x, mouse.y);
}

if (m_mouseButtonTracker.leftButton == Mouse::ButtonStateTracker::RELEASED)
{
    m_ballCamera.OnEnd();
}

See Ken Shoemake, "Arcball Rotation Control", Graphics Gems IV, pg 176 - 192

\$\endgroup\$
  • \$\begingroup\$ someone edited out that i was only using managed directx \$\endgroup\$ – SukottoSama Jan 25 '16 at 20:00
  • \$\begingroup\$ And what version of "Managed DirectX"? are you using exactly? Hopefully SlimDX, SharpDX, Mono, or XNA GS since the legacy Managed DirectX 1.1 assemblies have been deprecated for ages. \$\endgroup\$ – Chuck Walbourn Jan 25 '16 at 23:19
  • \$\begingroup\$ using the managed directx from the 2010 release which is the same of the 2007 version. i only doing to for fun and a learning experience \$\endgroup\$ – SukottoSama Jan 25 '16 at 23:45
  • \$\begingroup\$ Which is the same as the 2006 version. Super ancient, not particularly relevant, and doesn't work with .NET 4.x without hacks. Read DirectX and .NET. SlimDX is basically an updated version of the same design assemblies, so take a look at that. \$\endgroup\$ – Chuck Walbourn Jan 26 '16 at 0:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.