Hello,
After messing with the latest version of the GCC Source Code i am trying to program a custom Model Viewer using the framework.
I checked in the DXUT10 an implementation of a ModelViewer Camera class based on Quaternions and i wanted to adapt this implementation to an ArcBall MovementController inside the framework, but im unable to get the camera to rotate around the target object as it should...
Some time ago i managed to implement a camera system based on UVN vectors (I dont know if this is the correct name) which worked flawlessly, so im not sure if it would be better to try the DXUT system or adapt what i already had...
Any suggestion?
Regards,
Display All
After messing with the latest version of the GCC Source Code i am trying to program a custom Model Viewer using the framework.
I checked in the DXUT10 an implementation of a ModelViewer Camera class based on Quaternions and i wanted to adapt this implementation to an ArcBall MovementController inside the framework, but im unable to get the camera to rotate around the target object as it should...
Some time ago i managed to implement a camera system based on UVN vectors (I dont know if this is the correct name) which worked flawlessly, so im not sure if it would be better to try the DXUT system or adapt what i already had...
Any suggestion?
Regards,
C Source Code
- #pragma once
- #include "Geometry.h"
- // Forward declarations
- class SceneNode;
- class MovementController;
- class ArcBallCamMovementController : public MovementController
- {
- public:
- ArcBallCamMovementController (shared_ptr<SceneNode> object, float initialYaw, float initialPitch, bool rotateWhenLButtonDown);
- void Reset();
- virtual void OnUpdate(DWORD const elapsedMs);
- virtual bool VOnLButtonDown(const CPoint &mousePos);
- bool VOnMouseMove(const CPoint &mousePos);
- Vec3 ScreenToVector( float fScreenPtX, float fScreenPtY );
- Quaternion QuatFromBallPoints( Vec3 &vFrom, Vec3 &vTo );
- virtual void SetObject(shared_ptr<SceneNode> newObject);
- private:
- bool m_bUpdateObject;
- shared_ptr<CameraNode> m_pSceneCam;
- shared_ptr<SceneNode> m_pCamTarget;
- //from MovController
- //CRect m_WindowClientRect;
- Quaternion m_qDown; // Quaternion before button down
- Quaternion m_qNow; // Composite quaternion for current drag
- float m_fRadius; // arc ball's radius in screen coords
- float m_fRadiusTranslation; // arc ball's radius for translating the target
- Vec3 m_vDownPt; // starting point of rotation arc
- Vec3 m_vCurrentPt; // current point of rotation arc
- Vec3 m_vEye; // Camera eye position
- Vec3 m_vLookAt; // LookAt position
- Mat4x4 m_CameraRotLast;
- };
- -----------
- #include "u3dVisorStd.h"
- #include "..\GameCode.h"
- #include "..\Actors.h"
- #include "SceneNodes.h"
- #include "u3dSceneNodes.h"
- /*
- MovementController::MovementController(shared_ptr<SceneNode> object, float initialYaw, float initialPitch, bool rotateWhenLButtonDown)
- : m_object(object)
- {
- m_object->VGet()->Transform(&m_matToWorld, &m_matFromWorld);
- }
- */
- ArcBallCamMovementController ::ArcBallCamMovementController (shared_ptr<SceneNode> object, float initialYaw, float initialPitch, bool rotateWhenLButtonDown)
- :MovementController(object, initialYaw, initialPitch,rotateWhenLButtonDown),
- m_pSceneCam((CameraNode*)(&*m_object))
- {
- Reset();
- assert(m_object);
- m_pCamTarget = m_pSceneCam->GetTarget();
- //eye and lookat from the camera
- m_vEye = m_pSceneCam->GetPosition();
- m_vLookAt = Vec3(m_matToWorld._31, m_matToWorld._32, m_matToWorld._33);
- //Build quat from the camera object
- m_qNow.Build(m_matToWorld);
- // Set the radius according to the distance
- if(m_pCamTarget)
- {
- Vec3 v(m_pCamTarget->GetPosition() - m_vEye);
- m_fRadius = v.Length();
- }
- m_bUpdateObject = false;
- }
- void ArcBallCamMovementController::SetObject(shared_ptr<SceneNode> newObject)
- {
- // Set the radius according to the distance
- m_pCamTarget = m_pSceneCam->GetTarget();
- m_vLookAt = m_pCamTarget->GetPosition();
- Vec3 v(m_vLookAt - m_vEye);
- m_fRadius = v.Length();
- }
- //--------------------------------------------------------------------------------------
- void ArcBallCamMovementController::Reset()
- {
- m_qDown.Build(Mat4x4::g_Identity);
- m_qNow.Build(Mat4x4::g_Identity);
- m_fRadiusTranslation = 1.0f;
- m_fRadius = 1.0f;
- }
- //--------------------------------------------------------------------------------------
- Vec3 ArcBallCamMovementController::ScreenToVector( float fScreenPtX, float fScreenPtY )
- {
- // Scale to screen
- float x = -(fScreenPtX - m_WinOffset.x - m_nWidth/2) / (m_fRadius*m_nWidth/2);
- float y = (fScreenPtY - m_WinOffset.y - m_nHeight/2) / (m_fRadius*m_nHeight/2);
- 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 vector
- return Vec3( x, y, z );
- }
- //--------------------------------------------------------------------------------------
- Quaternion ArcBallCamMovementController::QuatFromBallPoints( Vec3 &vFrom, Vec3 &vTo )
- {
- Vec3 vPart;
- float fDot = vFrom.Dot(vTo);
- vPart = vFrom.Cross(vTo);
- return Quaternion(D3DXQUATERNION(vPart.x, vPart.y, vPart.z, fDot));
- }
- //--------------------------------------------------------------------------------------
- #define MAX(a, b) ((a) >= (b) ? (a) : (b))
- #define MIN(a, b) ((a) < (b) ? (a) : (b))
- #define RADIANS_TO_DEGREES(x) ((x) * 180.0f / D3DX_PI)
- #define DEGREES_TO_RADIANS(x) ((x) * D3DX_PI / 180.0f)
- //--------------------------------------------------------------------------------------
- bool ArcBallCamMovementController::VOnLButtonDown(const CPoint &mousePos)
- {
- m_mouseLButtonDown = true;
- // We want mouise movement to be relative to the position
- // the cursor was at when the user first presses down on
- // the left button
- if( mousePos.x >= m_WinOffset.x &&
- mousePos.x < m_WinOffset.x + m_nWidth &&
- mousePos.y >= m_WinOffset.y &&
- mousePos.y < m_WinOffset.y + m_nHeight )
- {
- m_qDown = m_qNow;
- m_vDownPt = ScreenToVector( mousePos.x, mousePos.y );
- m_lastMousePos = mousePos;
- }
- return true;
- }
- bool ArcBallCamMovementController::VOnMouseMove(const CPoint &mousePos)
- {
- if (m_bRotateWhenLButtonDown)
- {
- // Mode 1 - rotate the view only when the left mouse button is down
- // Only look around if the left button is down
- if(m_lastMousePos!=mousePos && m_mouseLButtonDown)
- {
- m_vCurrentPt = ScreenToVector( mousePos.x, mousePos.y );
- m_qNow = m_qDown * QuatFromBallPoints( m_vDownPt, m_vCurrentPt );
- //m_qNow.Normalize();
- m_bUpdateObject = true;
- //m_fTargetYaw = m_fTargetYaw + (m_lastMousePos.x - mousePos.x);
- //m_fTargetPitch = m_fTargetPitch + (mousePos.y - m_lastMousePos.y);
- m_fTargetYaw = (m_lastMousePos.x - mousePos.x);
- m_fTargetPitch = (mousePos.y - m_lastMousePos.y);
- m_lastMousePos = mousePos;
- }
- }
- else if(m_lastMousePos!=mousePos)
- {
- m_vCurrentPt = ScreenToVector( mousePos.x, mousePos.y );
- m_qNow = m_qDown * QuatFromBallPoints( m_vDownPt, m_vCurrentPt );
- //m_qNow.Normalize();
- m_bUpdateObject = true;
- // Mode 2 - rotate the controller when the mouse buttons are up
- //m_fTargetYaw = m_fTargetYaw + (m_lastMousePos.x - mousePos.x);
- //m_fTargetPitch = m_fTargetPitch + (mousePos.y - m_lastMousePos.y);
- m_fTargetYaw = (m_lastMousePos.x - mousePos.x);
- m_fTargetPitch = (mousePos.y - m_lastMousePos.y);
- m_lastMousePos = mousePos;
- }
- return true;
- }
- void ArcBallCamMovementController::OnUpdate(DWORD const deltaMilliseconds)
- {
- if(!m_bUpdateObject)
- return;
- float elapsedTime = (float)deltaMilliseconds / 1000.0f;
- // Ramp the acceleration by the elapsed time.
- float numberOfSeconds = 5.f;
- m_currentSpeed += m_maxSpeed * ( (elapsedTime*elapsedTime) / numberOfSeconds);
- if (m_currentSpeed > m_maxSpeed)
- m_currentSpeed = m_maxSpeed;
- //Vec3 direction(m_fTargetYaw, m_fTargetPitch, 0.f),
- Vec3 direction(m_fTargetYaw, m_fTargetPitch, 0.f),
- posDelta;
- //Calculate delta position
- posDelta = direction * m_currentSpeed;
- // Get the inverse of the arcball's rotation matrix = camera rotation matrix
- Mat4x4 CameraRot;
- CameraRot.BuildRotationQuat(m_qNow);
- CameraRot.Inverse();
- Vec3 atToWorld(CameraRot.Xform(g_Forward4)),
- upToWorld(CameraRot.Xform(g_Up4)),
- vposDeltaWorld( CameraRot.Xform(posDelta));//,
- //vLookAt;
- //??
- //D3DXVec3TransformCoord(&temp, &v, this);
- // Move the lookAt position
- m_vLookAt += vposDeltaWorld;
- // Update the eye point based on a radius away from the lookAt position
- m_vEye = m_vLookAt - atToWorld * m_fRadius;
- // Update the view matrix
- D3DXMATRIX mView;
- D3DXMatrixLookAtLH( &mView, &m_vEye, &m_vLookAt, &upToWorld );
- Mat4x4 mMView(mView), InvmMView(mMView.Inverse());
- InvmMView._41 = InvmMView._42 = InvmMView._43 = 0.f;
- //-------------
- Mat4x4 matToWorld, matLastToWorldInv(m_matLastToWorld.Inverse()), CameraRotLastInv(m_CameraRotLast.Inverse());
- //equals to the camera??????????
- matToWorld.BuildRotationQuat(m_qNow);
- matToWorld = matToWorld * mMView * matLastToWorldInv * matToWorld * InvmMView;
- //??????
- //Update world??? according to target-model movement?
- matToWorld = matToWorld * CameraRotLastInv * CameraRot;
- m_CameraRotLast = CameraRot;
- m_matLastToWorld = matToWorld;
- Vec3 XBasis(matToWorld._11, matToWorld._12, matToWorld._13),
- YBasis(matToWorld._21, matToWorld._22, matToWorld._23),
- ZBasis(matToWorld._31, matToWorld._32, matToWorld._33);
- XBasis.Normalize();
- YBasis.Normalize();
- ZBasis.Normalize();
- matToWorld._11 = XBasis.x; matToWorld._12 = XBasis.y; matToWorld._13 = XBasis.z;
- matToWorld._21 = YBasis.x; matToWorld._22 = YBasis.y; matToWorld._23 = YBasis.z;
- matToWorld._31 = ZBasis.x; matToWorld._32 = ZBasis.y; matToWorld._33 = ZBasis.z;
- matToWorld.SetPosition(m_vLookAt);
- //matToWorld.SetPosition(m_vEye);
- //m_matPosition.BuildTranslation(m_vEye * -1.0f);
- m_matPosition.BuildTranslation(m_vEye);
- m_matToWorld = m_matPosition * matToWorld;
- m_matFromWorld = m_matToWorld.Inverse();
- m_object->VSetTransform(&m_matToWorld, &m_matFromWorld);
- //m_object->VSetTransform(&mMView, NULL);
- m_bUpdateObject = false;