//-------------------------------------------------------------------------------------- // Figure out the velocity based on keyboard input & drag if any //-------------------------------------------------------------------------------------- void CBaseCamera::GetInput( bool bGetKeyboardInput, bool bGetMouseInput, bool bGetGamepadInput, bool bResetCursorAfterMove ) { mKeyboardDirection = vec3( 0, 0, 0 ); if( bGetKeyboardInput ) { // Update acceleration vector based on keyboard state if( IsKeyDown( mKeys[CAM_MOVE_FORWARD] ) ) mKeyboardDirection.z -= 1.0f; if( IsKeyDown( mKeys[CAM_MOVE_BACKWARD] ) ) mKeyboardDirection.z += 1.0f; if( mEnableYAxisMovement ) { if( IsKeyDown( mKeys[CAM_MOVE_UP] ) ) mKeyboardDirection.y += 1.0f; if( IsKeyDown( mKeys[CAM_MOVE_DOWN] ) ) mKeyboardDirection.y -= 1.0f; } if( IsKeyDown( mKeys[CAM_STRAFE_RIGHT] ) ) mKeyboardDirection.x += 1.0f; if( IsKeyDown( mKeys[CAM_STRAFE_LEFT] ) ) mKeyboardDirection.x -= 1.0f; } if( bGetMouseInput ) { UpdateMouseDelta(); } else { mMouseDelta = vec2(0.0); } }
//-------------------------------------------------------------------------------------- // Update the view matrix based on user input & elapsed time //-------------------------------------------------------------------------------------- void FirstPersonCamera::FrameMove( float fElapsedTime ) { // if( Base::Timer::GlobalTimer().IsStopped() ) // fElapsedTime = static_cast<float>(Base::Timer::GlobalTimer().FrameDelta()); if( IsKeyDown(m_aKeys[CAM_RESET]) ) Reset(); // Get the mouse movement (if any) if the mouse button are down if( m_nActiveButtonMask & m_nCurrentButtonMask ) UpdateMouseDelta( fElapsedTime ); // Get amount of velocity based on the keyboard input and drag (if any) UpdateVelocity( fElapsedTime ); // Simple euler method to calculate position delta vector3 vPosDelta = m_vVelocity * fElapsedTime; // If rotating the camera if( m_nActiveButtonMask & m_nCurrentButtonMask ) { // Update the pitch & yaw angle based on mouse movement float fYawDelta = m_vRotVelocity.x; float fPitchDelta = m_vRotVelocity.y; // Invert pitch if requested if( m_bInvertPitch ) fPitchDelta = -fPitchDelta; m_fCameraPitchAngle += fPitchDelta; m_fCameraYawAngle += fYawDelta; // Limit pitch to straight up or straight down m_fCameraPitchAngle = std::max( -floatPi/2.0f, m_fCameraPitchAngle ); m_fCameraPitchAngle = std::min( +floatPi/2.0f, m_fCameraPitchAngle ); } // Make a rotation matrix based on the camera's yaw & pitch matrix44 mCameraRot; mCameraRot.rotate_y( m_fCameraYawAngle ); mCameraRot.rotate_x( m_fCameraPitchAngle ); mCameraRot.rotate_z( 0 ); // Transform vectors based on camera's rotation matrix vector3 vLocalUp = vector3(0,1,0); vector3 vLocalAhead = vector3(0,0,1); vector3 vWorldUp = mCameraRot.transform_coord( vLocalUp ); vector3 vWorldAhead = mCameraRot.transform_coord( vLocalAhead ); // Transform the position delta by the camera's rotation vector3 vPosDeltaWorld = mCameraRot.transform_coord(vPosDelta); vPosDeltaWorld.x *= -1; //vPosDeltaWorld.y *= -1; // Base::debugLog << "y delta " << vPosDeltaWorld.y << std::endl; if( !m_bEnableYAxisMovement ) vPosDeltaWorld.y = 0.0f; // Move the eye position m_vEye += vPosDeltaWorld; if( m_bClipToBoundary ) ConstrainToBoundary( &m_vEye ); // Update the lookAt position based on the eye position m_vLookAt = m_vEye + vWorldAhead; // Update the view matrix m_mView.ident(); m_mView.set_translation ( m_vEye ); //m_mView.lookatRh( m_vLookAt, vLocalUp ); m_mView *= mCameraRot; m_mCameraWorld = m_mView; m_mCameraWorld.invert(); }
//-------------------------------------------------------------------------------------- // Update the view matrix & the model's world matrix based // on user input & elapsed time //-------------------------------------------------------------------------------------- VOID CModelViewerCamera::FrameMove( FLOAT fElapsedTime ) { if( IsKeyDown(m_aKeys[CAM_RESET]) ) Reset(); // Get the mouse movement (if any) if the mouse button are down if( m_nCurrentButtonMask != 0 ) UpdateMouseDelta( fElapsedTime ); // Get amount of velocity based on the keyboard input and drag (if any) UpdateVelocity( fElapsedTime ); // Simple euler method to calculate position delta D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime; // Change the radius from the camera to the model based on wheel scrolling if( m_nMouseWheelDelta && m_nZoomButtonMask == MOUSE_WHEEL ) m_fRadius -= m_nMouseWheelDelta * m_fRadius * 0.1f; m_fRadius = min( m_fMaxRadius, m_fRadius ); m_fRadius = max( m_fMinRadius, m_fRadius ); m_nMouseWheelDelta = 0; // Get the inverse of the arcball's rotation matrix D3DXMATRIX mCameraRot; D3DXMatrixInverse( &mCameraRot, NULL, m_ViewArcBall.GetRotationMatrix() ); // Transform vectors based on camera's rotation matrix D3DXVECTOR3 vWorldUp, vWorldAhead; D3DXVECTOR3 vLocalUp = D3DXVECTOR3(0,1,0); D3DXVECTOR3 vLocalAhead = D3DXVECTOR3(0,0,1); D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot ); D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot ); // Transform the position delta by the camera's rotation D3DXVECTOR3 vPosDeltaWorld; D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot ); // Move the lookAt position m_vLookAt += vPosDeltaWorld; if( m_bClipToBoundary ) ConstrainToBoundary( &m_vLookAt ); // Update the eye point based on a radius away from the lookAt position m_vEye = m_vLookAt - vWorldAhead * m_fRadius; // Update the view matrix D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp ); D3DXMATRIX mInvView; D3DXMatrixInverse( &mInvView, NULL, &m_mView ); mInvView._41 = mInvView._42 = mInvView._43 = 0; D3DXMATRIX mModelLastRotInv; D3DXMatrixInverse(&mModelLastRotInv, NULL, &m_mModelLastRot); // Accumulate the delta of the arcball's rotation in view space. // Note that per-frame delta rotations could be problematic over long periods of time. D3DXMATRIX mModelRot; mModelRot = *m_WorldArcBall.GetRotationMatrix(); m_mModelRot *= m_mView * mModelLastRotInv * mModelRot * mInvView; if( m_ViewArcBall.IsBeingDragged() && m_bAttachCameraToModel && !IsKeyDown(m_aKeys[CAM_CONTROLDOWN]) ) { // Attach camera to model by inverse of the model rotation D3DXMATRIX mCameraLastRotInv; D3DXMatrixInverse(&mCameraLastRotInv, NULL, &m_mCameraRotLast); D3DXMATRIX mCameraRotDelta = mCameraLastRotInv * mCameraRot; // local to world matrix m_mModelRot *= mCameraRotDelta; } m_mCameraRotLast = mCameraRot; m_mModelLastRot = mModelRot; // Since we're accumulating delta rotations, we need to orthonormalize // the matrix to prevent eventual matrix skew D3DXVECTOR3* pXBasis = (D3DXVECTOR3*) &m_mModelRot._11; D3DXVECTOR3* pYBasis = (D3DXVECTOR3*) &m_mModelRot._21; D3DXVECTOR3* pZBasis = (D3DXVECTOR3*) &m_mModelRot._31; D3DXVec3Normalize( pXBasis, pXBasis ); D3DXVec3Cross( pYBasis, pZBasis, pXBasis ); D3DXVec3Normalize( pYBasis, pYBasis ); D3DXVec3Cross( pZBasis, pXBasis, pYBasis ); // Translate the rotation matrix to the same position as the lookAt position m_mModelRot._41 = m_vLookAt.x; m_mModelRot._42 = m_vLookAt.y; m_mModelRot._43 = m_vLookAt.z; // Translate world matrix so its at the center of the model D3DXMATRIX mTrans; D3DXMatrixTranslation( &mTrans, -m_vModelCenter.x, -m_vModelCenter.y, -m_vModelCenter.z ); m_mWorld = mTrans * m_mModelRot; }