text: //--------------------------------------------------------------------------------------
  // File: Camera.h
  //
  // Helper functions for Direct3D programming.
  //
  // Copyright (c) Microsoft Corporation. All rights reserved
  //--------------------------------------------------------------------------------------
  #pragma once
  #ifndef CAMERA_H
  #define CAMERA_H
  
  #include <d3d11.h>
  #include <d3dx10math.h>
  
  //--------------------------------------------------------------------------------------
  class CD3DArcBall
  {
  public:
                                      CD3DArcBall();
  
      // Functions to change behavior
      void                            Reset();
      void                            SetTranslationRadius( FLOAT fRadiusTranslation )
      {
          m_fRadiusTranslation = fRadiusTranslation;
      }
      void                            SetWindow( INT nWidth, INT nHeight, FLOAT fRadius = 0.9f )
      {
          m_nWidth = nWidth; m_nHeight = nHeight; m_fRadius = fRadius;
          m_vCenter = D3DXVECTOR2( m_nWidth / 2.0f, m_nHeight / 2.0f );
      }
      void                            SetOffset( INT nX, INT nY )
      {
          m_Offset.x = nX; m_Offset.y = nY;
      }
  
      // Call these from client and use GetRotationMatrix() to read new rotation matrix
      void                            OnBegin( int nX, int nY );  // start the rotation (pass current mouse position)
      void                            OnMove( int nX, int nY );   // continue the rotation (pass current mouse position)
      void                            OnEnd();                    // end the rotation 
  
      // Or call this to automatically handle left, middle, right buttons
      LRESULT                         HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  
      // Functions to get/set state
      const D3DXMATRIX* GetRotationMatrix()
      {
          return D3DXMatrixRotationQuaternion( &m_mRotation, &m_qNow );
      };
      const D3DXMATRIX* GetTranslationMatrix() const
      {
          return &m_mTranslation;
      }
      const D3DXMATRIX* GetTranslationDeltaMatrix() const
      {
          return &m_mTranslationDelta;
      }
      bool                            IsBeingDragged() const
      {
          return m_bDrag;
      }
      D3DXQUATERNION                  GetQuatNow() const
      {
          return m_qNow;
      }
      void                            SetQuatNow( D3DXQUATERNION q )
      {
          m_qNow = q;
      }
  
      static D3DXQUATERNION WINAPI    QuatFromBallPoints( const D3DXVECTOR3& vFrom, const D3DXVECTOR3& vTo );
  
  
  protected:
      D3DXMATRIXA16 m_mRotation;         // Matrix for arc ball's orientation
      D3DXMATRIXA16 m_mTranslation;      // Matrix for arc ball's position
      D3DXMATRIXA16 m_mTranslationDelta; // Matrix for arc ball's position
  
      POINT m_Offset;   // window offset, or upper-left corner of window
      INT m_nWidth;   // arc ball's window width
      INT m_nHeight;  // arc ball's window height
      D3DXVECTOR2 m_vCenter;  // center of arc ball 
      FLOAT m_fRadius;  // arc ball's radius in screen coords
      FLOAT m_fRadiusTranslation; // arc ball's radius for translating the target
  
      D3DXQUATERNION m_qDown;             // Quaternion before button down
      D3DXQUATERNION m_qNow;              // Composite quaternion for current drag
      bool m_bDrag;             // Whether user is dragging arc ball
  
      POINT m_ptLastMouse;      // position of last mouse point
      D3DXVECTOR3 m_vDownPt;           // starting point of rotation arc
      D3DXVECTOR3 m_vCurrentPt;        // current point of rotation arc
  
      D3DXVECTOR3                     ScreenToVector( float fScreenPtX, float fScreenPtY );
  };
  
  
  //--------------------------------------------------------------------------------------
  // used by CCamera to map WM_KEYDOWN keys
  //--------------------------------------------------------------------------------------
  enum D3DUtil_CameraKeys
  {
      CAM_STRAFE_LEFT = 0,
      CAM_STRAFE_RIGHT,
      CAM_MOVE_FORWARD,
      CAM_MOVE_BACKWARD,
      CAM_MOVE_UP,
      CAM_MOVE_DOWN,
      CAM_RESET,
      CAM_CONTROLDOWN,
      CAM_MAX_KEYS,
      CAM_UNKNOWN     = 0xFF
  };
  
  #define KEY_WAS_DOWN_MASK 0x80
  #define KEY_IS_DOWN_MASK  0x01
  
  #define MOUSE_LEFT_BUTTON   0x01
  #define MOUSE_MIDDLE_BUTTON 0x02
  #define MOUSE_RIGHT_BUTTON  0x04
  #define MOUSE_WHEEL         0x08
  
  
  //--------------------------------------------------------------------------------------
  // Simple base camera class that moves and rotates.  The base class
  //       records mouse and keyboard input for use by a derived class, and 
  //       keeps common state.
  //--------------------------------------------------------------------------------------
  class CBaseCamera
  {
  public:
                                  CBaseCamera();
  
      // Call these from client and use Get*Matrix() to read new matrices
      virtual LRESULT             HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
      virtual void                FrameMove( FLOAT fElapsedTime ) = 0;
  
      // Functions to change camera matrices
      virtual void                Reset();
      virtual void                SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt );
      virtual void                SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane, FLOAT fFarPlane );
  
      // Functions to change behavior
      virtual void                SetDragRect( RECT& rc )
      {
          m_rcDrag = rc;
      }
      void                        SetInvertPitch( bool bInvertPitch )
      {
          m_bInvertPitch = bInvertPitch;
      }
      void                        SetDrag( bool bMovementDrag, FLOAT fTotalDragTimeToZero = 0.25f )
      {
          m_bMovementDrag = bMovementDrag; m_fTotalDragTimeToZero = fTotalDragTimeToZero;
      }
      void                        SetEnableYAxisMovement( bool bEnableYAxisMovement )
      {
          m_bEnableYAxisMovement = bEnableYAxisMovement;
      }
      void                        SetEnablePositionMovement( bool bEnablePositionMovement )
      {
          m_bEnablePositionMovement = bEnablePositionMovement;
      }
      void                        SetClipToBoundary( bool bClipToBoundary, D3DXVECTOR3* pvMinBoundary,
                                                     D3DXVECTOR3* pvMaxBoundary )
      {
          m_bClipToBoundary = bClipToBoundary; if( pvMinBoundary ) m_vMinBoundary = *pvMinBoundary;
          if( pvMaxBoundary ) m_vMaxBoundary = *pvMaxBoundary;
      }
      void                        SetScalers( FLOAT fRotationScaler = 0.01f, FLOAT fMoveScaler = 5.0f )
      {
          m_fRotationScaler = fRotationScaler; m_fMoveScaler = fMoveScaler;
      }
      void                        SetNumberOfFramesToSmoothMouseData( int nFrames )
      {
          if( nFrames > 0 ) m_fFramesToSmoothMouseData = ( float )nFrames;
      }
      void                        SetResetCursorAfterMove( bool bResetCursorAfterMove )
      {
          m_bResetCursorAfterMove = bResetCursorAfterMove;
      }
  
      // Functions to get state
      const D3DXMATRIX* GetViewMatrix() const
      {
          return &m_mView;
      }
      const D3DXMATRIX* GetProjMatrix() const
      {
          return &m_mProj;
      }
      const D3DXVECTOR3* GetEyePt() const
      {
          return &m_vEye;
      }
      const D3DXVECTOR3* GetLookAtPt() const
      {
          return &m_vLookAt;
      }
      float                       GetNearClip() const
      {
          return m_fNearPlane;
      }
      float                       GetFarClip() const
      {
          return m_fFarPlane;
      }
  
      bool                        IsBeingDragged() const
      {
          return ( m_bMouseLButtonDown || m_bMouseMButtonDown || m_bMouseRButtonDown );
      }
      bool                        IsMouseLButtonDown() const
      {
          return m_bMouseLButtonDown;
      }
      bool                        IsMouseMButtonDown() const
      {
          return m_bMouseMButtonDown;
      }
      bool                        IsMouseRButtonDown() const
      {
          return m_bMouseRButtonDown;
      }
  
  protected:
      // Functions to map a WM_KEYDOWN key to a D3DUtil_CameraKeys enum
      virtual D3DUtil_CameraKeys  MapKey( UINT nKey );
      bool                        IsKeyDown( BYTE key ) const
      {
          return( ( key & KEY_IS_DOWN_MASK ) == KEY_IS_DOWN_MASK );
      }
      bool                        WasKeyDown( BYTE key ) const
      {
          return( ( key & KEY_WAS_DOWN_MASK ) == KEY_WAS_DOWN_MASK );
      }
  
      void                        ConstrainToBoundary( D3DXVECTOR3* pV );
      void                        UpdateMouseDelta();
      void                        UpdateVelocity( float fElapsedTime );
      void                        GetInput( bool bGetKeyboardInput, bool bGetMouseInput, bool bGetGamepadInput,
                                            bool bResetCursorAfterMove );
  
      D3DXMATRIX m_mView;              // View matrix 
      D3DXMATRIX m_mProj;              // Projection matrix
  
      //DXUT_GAMEPAD                m_GamePad[DXUT_MAX_CONTROLLERS];  // XInput controller state
      D3DXVECTOR3 m_vGamePadLeftThumb;
      D3DXVECTOR3 m_vGamePadRightThumb;
      //double                      m_GamePadLastActive[DXUT_MAX_CONTROLLERS];
  
      int m_cKeysDown;            // Number of camera keys that are down.
      BYTE                        m_aKeys[CAM_MAX_KEYS];  // State of input - KEY_WAS_DOWN_MASK|KEY_IS_DOWN_MASK
      D3DXVECTOR3 m_vKeyboardDirection;   // Direction vector of keyboard input
      POINT m_ptLastMousePosition;  // Last absolute position of mouse cursor
      bool m_bMouseLButtonDown;    // True if left button is down 
      bool m_bMouseMButtonDown;    // True if middle button is down 
      bool m_bMouseRButtonDown;    // True if right button is down 
      int m_nCurrentButtonMask;   // mask of which buttons are down
      int m_nMouseWheelDelta;     // Amount of middle wheel scroll (+/-) 
      D3DXVECTOR2 m_vMouseDelta;          // Mouse relative delta smoothed over a few frames
      float m_fFramesToSmoothMouseData; // Number of frames to smooth mouse data over
  
      D3DXVECTOR3 m_vDefaultEye;          // Default camera eye position
      D3DXVECTOR3 m_vDefaultLookAt;       // Default LookAt position
      D3DXVECTOR3 m_vEye;                 // Camera eye position
      D3DXVECTOR3 m_vLookAt;              // LookAt position
      float m_fCameraYawAngle;      // Yaw angle of camera
      float m_fCameraPitchAngle;    // Pitch angle of camera
  
      RECT m_rcDrag;               // Rectangle within which a drag can be initiated.
      D3DXVECTOR3 m_vVelocity;            // Velocity of camera
      bool m_bMovementDrag;        // If true, then camera movement will slow to a stop otherwise movement is instant
      D3DXVECTOR3 m_vVelocityDrag;        // Velocity drag force
      FLOAT m_fDragTimer;           // Countdown timer to apply drag
      FLOAT m_fTotalDragTimeToZero; // Time it takes for velocity to go from full to 0
      D3DXVECTOR2 m_vRotVelocity;         // Velocity of camera
  
      float m_fFOV;                 // Field of view
      float m_fAspect;              // Aspect ratio
      float m_fNearPlane;           // Near plane
      float m_fFarPlane;            // Far plane
  
      float m_fRotationScaler;      // Scaler for rotation
      float m_fMoveScaler;          // Scaler for movement
  
      bool m_bInvertPitch;         // Invert the pitch axis
      bool m_bEnablePositionMovement; // If true, then the user can translate the camera/model 
      bool m_bEnableYAxisMovement; // If true, then camera can move in the y-axis
  
      bool m_bClipToBoundary;      // If true, then the camera will be clipped to the boundary
      D3DXVECTOR3 m_vMinBoundary;         // Min point in clip boundary
      D3DXVECTOR3 m_vMaxBoundary;         // Max point in clip boundary
  
      bool m_bResetCursorAfterMove;// If true, the class will reset the cursor position so that the cursor always has space to move 
  };
  
  
  //--------------------------------------------------------------------------------------
  // Simple first person camera class that moves and rotates.
  //       It allows yaw and pitch but not roll.  It uses WM_KEYDOWN and 
  //       GetCursorPos() to respond to keyboard and mouse input and updates the 
  //       view matrix based on input.  
  //--------------------------------------------------------------------------------------
  class CFirstPersonCamera : public CBaseCamera
  {
  public:
                      CFirstPersonCamera();
  
      // Call these from client and use Get*Matrix() to read new matrices
      virtual void    FrameMove( FLOAT fElapsedTime );
  
      // Functions to change behavior
      void            SetRotateButtons( bool bLeft, bool bMiddle, bool bRight, bool bRotateWithoutButtonDown = false );
  
      // Functions to get state
      D3DXMATRIX* GetWorldMatrix()
      {
          return &m_mCameraWorld;
      }
  
      const D3DXVECTOR3* GetWorldRight() const
      {
          return ( D3DXVECTOR3* )&m_mCameraWorld._11;
      }
      const D3DXVECTOR3* GetWorldUp() const
      {
          return ( D3DXVECTOR3* )&m_mCameraWorld._21;
      }
      const D3DXVECTOR3* GetWorldAhead() const
      {
          return ( D3DXVECTOR3* )&m_mCameraWorld._31;
      }
      const D3DXVECTOR3* GetEyePt() const
      {
          return ( D3DXVECTOR3* )&m_mCameraWorld._41;
      }
  
  protected:
      D3DXMATRIX m_mCameraWorld;       // World matrix of the camera (inverse of the view matrix)
  
      int m_nActiveButtonMask;  // Mask to determine which button to enable for rotation
      bool m_bRotateWithoutButtonDown;
  };
  
  
  //--------------------------------------------------------------------------------------
  // Simple model viewing camera class that rotates around the object.
  //--------------------------------------------------------------------------------------
  class CModelViewerCamera : public CBaseCamera
  {
  public:
                      CModelViewerCamera();
  
      // Call these from client and use Get*Matrix() to read new matrices
      virtual LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
      virtual void    FrameMove( FLOAT fElapsedTime );
  
  
      // Functions to change behavior
      virtual void    SetDragRect( RECT& rc );
      void            Reset();
      void            SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt );
      void            SetButtonMasks( int nRotateModelButtonMask = MOUSE_LEFT_BUTTON, int nZoomButtonMask = MOUSE_WHEEL,
                                      int nRotateCameraButtonMask = MOUSE_RIGHT_BUTTON )
      {
          m_nRotateModelButtonMask = nRotateModelButtonMask, m_nZoomButtonMask = nZoomButtonMask;
          m_nRotateCameraButtonMask = nRotateCameraButtonMask;
      }
      void            SetAttachCameraToModel( bool bEnable = false )
      {
          m_bAttachCameraToModel = bEnable;
      }
      void            SetWindow( int nWidth, int nHeight, float fArcballRadius=0.9f )
      {
          m_WorldArcBall.SetWindow( nWidth, nHeight, fArcballRadius );
          m_ViewArcBall.SetWindow( nWidth, nHeight, fArcballRadius );
      }
      void            SetRadius( float fDefaultRadius=5.0f, float fMinRadius=1.0f, float fMaxRadius=FLT_MAX )
      {
          m_fDefaultRadius = m_fRadius = fDefaultRadius; m_fMinRadius = fMinRadius; m_fMaxRadius = fMaxRadius;
          m_bDragSinceLastUpdate = true;
      }
      void            SetModelCenter( D3DXVECTOR3 vModelCenter )
      {
          m_vModelCenter = vModelCenter;
      }
      void            SetLimitPitch( bool bLimitPitch )
      {
          m_bLimitPitch = bLimitPitch;
      }
      void            SetViewQuat( D3DXQUATERNION q )
      {
          m_ViewArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true;
      }
      void            SetWorldQuat( D3DXQUATERNION q )
      {
          m_WorldArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true;
      }
  
      // Functions to get state
      const D3DXMATRIX* GetWorldMatrix() const
      {
          return &m_mWorld;
      }
      void            SetWorldMatrix( D3DXMATRIX& mWorld )
      {
          m_mWorld = mWorld; m_bDragSinceLastUpdate = true;
      }
  
  protected:
      CD3DArcBall m_WorldArcBall;
      CD3DArcBall m_ViewArcBall;
      D3DXVECTOR3 m_vModelCenter;
      D3DXMATRIX m_mModelLastRot;        // Last arcball rotation matrix for model 
      D3DXMATRIX m_mModelRot;            // Rotation matrix of model
      D3DXMATRIX m_mWorld;               // World matrix of model
  
      int m_nRotateModelButtonMask;
      int m_nZoomButtonMask;
      int m_nRotateCameraButtonMask;
  
      bool m_bAttachCameraToModel;
      bool m_bLimitPitch;
      float m_fRadius;              // Distance from the camera to model 
      float m_fDefaultRadius;       // Distance from the camera to model 
      float m_fMinRadius;           // Min radius
      float m_fMaxRadius;           // Max radius
      bool m_bDragSinceLastUpdate; // True if mouse drag has happened since last time FrameMove is called.
  
      D3DXMATRIX m_mCameraRotLast;
  
  };
  
  //--------------------------------------------------------------------------------------
  // Manages the mesh, direction, mouse events of a directional arrow that 
  // rotates around a radius controlled by an arcball 
  //--------------------------------------------------------------------------------------
  /*
  class CDXUTDirectionWidget
  {
  public:
                              CDXUTDirectionWidget();
  
      static HRESULT WINAPI   StaticOnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice );
      HRESULT                 OnD3D9ResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
      HRESULT                 OnRender9( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj,
                                         const D3DXVECTOR3* pEyePt );
      LRESULT                 HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
      static void WINAPI      StaticOnD3D9LostDevice();
      static void WINAPI      StaticOnD3D9DestroyDevice();
  
      static HRESULT WINAPI   StaticOnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext );
      HRESULT                 OnRender11( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj,
                                          const D3DXVECTOR3* pEyePt );
      static void WINAPI      StaticOnD3D11DestroyDevice();
  
      D3DXVECTOR3             GetLightDirection()
      {
          return m_vCurrentDir;
      };
      void                    SetLightDirection( D3DXVECTOR3 vDir )
      {
          m_vDefaultDir = m_vCurrentDir = vDir;
      };
      void                    SetButtonMask( int nRotate = MOUSE_RIGHT_BUTTON )
      {
          m_nRotateMask = nRotate;
      }
  
      float                   GetRadius()
      {
          return m_fRadius;
      };
      void                    SetRadius( float fRadius )
      {
          m_fRadius = fRadius;
      };
  
      bool                    IsBeingDragged()
      {
          return m_ArcBall.IsBeingDragged();
      };
  
  protected:
      HRESULT                 UpdateLightDir();
  
      // D3D9 objects
      static IDirect3DDevice9* s_pd3d9Device;
      static ID3DXEffect* s_pD3D9Effect;
      static ID3DXMesh* s_pD3D9Mesh;
      static D3DXHANDLE s_hRenderWith1LightNoTexture;
      static D3DXHANDLE s_hMaterialDiffuseColor;
      static D3DXHANDLE s_hLightDir;
      static D3DXHANDLE s_hWorldViewProjection;
      static D3DXHANDLE s_hWorld;
  
      // D3D10 objects 
      //static ID3D10Device* s_pd3d10Device;
      //static ID3D10Effect* s_pD3D10Effect;
      //TODO: add some sort of d3d10 mesh object here
      //static ID3D10InputLayout* s_pVertexLayout;
      //static ID3D10EffectTechnique* s_pRenderTech;
      //static ID3D10EffectVectorVariable* g_pMaterialDiffuseColor;
      //static ID3D10EffectVectorVariable* g_pLightDir;
      //static ID3D10EffectMatrixVariable* g_pmWorld;
      //static ID3D10EffectMatrixVariable* g_pmWorldViewProjection;
  
      D3DXMATRIXA16 m_mRot;
      D3DXMATRIXA16 m_mRotSnapshot;
      float m_fRadius;
      int m_nRotateMask;
      CD3DArcBall m_ArcBall;
      D3DXVECTOR3 m_vDefaultDir;
      D3DXVECTOR3 m_vCurrentDir;
      D3DXMATRIX m_mView;
  };
  */
  
  
  #endif
  