1 //--------------------------------------------------------------------------------------
\r
4 // Helper functions for Direct3D programming.
\r
6 // Copyright (c) Microsoft Corporation. All rights reserved
\r
7 //--------------------------------------------------------------------------------------
\r
12 //--------------------------------------------------------------------------------------
\r
18 // Functions to change behavior
\r
20 void SetTranslationRadius( FLOAT fRadiusTranslation )
\r
22 m_fRadiusTranslation = fRadiusTranslation;
\r
24 void SetWindow( INT nWidth, INT nHeight, FLOAT fRadius = 0.9f )
\r
26 m_nWidth = nWidth; m_nHeight = nHeight; m_fRadius = fRadius;
\r
27 m_vCenter = D3DXVECTOR2( m_nWidth / 2.0f, m_nHeight / 2.0f );
\r
29 void SetOffset( INT nX, INT nY )
\r
31 m_Offset.x = nX; m_Offset.y = nY;
\r
34 // Call these from client and use GetRotationMatrix() to read new rotation matrix
\r
35 void OnBegin( int nX, int nY ); // start the rotation (pass current mouse position)
\r
36 void OnMove( int nX, int nY ); // continue the rotation (pass current mouse position)
\r
37 void OnEnd(); // end the rotation
\r
39 // Or call this to automatically handle left, middle, right buttons
\r
40 LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
\r
42 // Functions to get/set state
\r
43 const D3DXMATRIX* GetRotationMatrix()
\r
45 return D3DXMatrixRotationQuaternion( &m_mRotation, &m_qNow );
\r
47 const D3DXMATRIX* GetTranslationMatrix() const
\r
49 return &m_mTranslation;
\r
51 const D3DXMATRIX* GetTranslationDeltaMatrix() const
\r
53 return &m_mTranslationDelta;
\r
55 bool IsBeingDragged() const
\r
59 D3DXQUATERNION GetQuatNow() const
\r
63 void SetQuatNow( D3DXQUATERNION q )
\r
68 static D3DXQUATERNION WINAPI QuatFromBallPoints( const D3DXVECTOR3& vFrom, const D3DXVECTOR3& vTo );
\r
72 D3DXMATRIXA16 m_mRotation; // Matrix for arc ball's orientation
\r
73 D3DXMATRIXA16 m_mTranslation; // Matrix for arc ball's position
\r
74 D3DXMATRIXA16 m_mTranslationDelta; // Matrix for arc ball's position
\r
76 POINT m_Offset; // window offset, or upper-left corner of window
\r
77 INT m_nWidth; // arc ball's window width
\r
78 INT m_nHeight; // arc ball's window height
\r
79 D3DXVECTOR2 m_vCenter; // center of arc ball
\r
80 FLOAT m_fRadius; // arc ball's radius in screen coords
\r
81 FLOAT m_fRadiusTranslation; // arc ball's radius for translating the target
\r
83 D3DXQUATERNION m_qDown; // Quaternion before button down
\r
84 D3DXQUATERNION m_qNow; // Composite quaternion for current drag
\r
85 bool m_bDrag; // Whether user is dragging arc ball
\r
87 POINT m_ptLastMouse; // position of last mouse point
\r
88 D3DXVECTOR3 m_vDownPt; // starting point of rotation arc
\r
89 D3DXVECTOR3 m_vCurrentPt; // current point of rotation arc
\r
91 D3DXVECTOR3 ScreenToVector( float fScreenPtX, float fScreenPtY );
\r
95 //--------------------------------------------------------------------------------------
\r
96 // used by CCamera to map WM_KEYDOWN keys
\r
97 //--------------------------------------------------------------------------------------
\r
98 enum D3DUtil_CameraKeys
\r
100 CAM_STRAFE_LEFT = 0,
\r
112 #define KEY_WAS_DOWN_MASK 0x80
\r
113 #define KEY_IS_DOWN_MASK 0x01
\r
115 #define MOUSE_LEFT_BUTTON 0x01
\r
116 #define MOUSE_MIDDLE_BUTTON 0x02
\r
117 #define MOUSE_RIGHT_BUTTON 0x04
\r
118 #define MOUSE_WHEEL 0x08
\r
121 //--------------------------------------------------------------------------------------
\r
122 // Simple base camera class that moves and rotates. The base class
\r
123 // records mouse and keyboard input for use by a derived class, and
\r
124 // keeps common state.
\r
125 //--------------------------------------------------------------------------------------
\r
131 // Call these from client and use Get*Matrix() to read new matrices
\r
132 virtual LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
\r
133 virtual void FrameMove( FLOAT fElapsedTime ) = 0;
\r
135 // Functions to change camera matrices
\r
136 virtual void Reset();
\r
137 virtual void SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt );
\r
138 virtual void SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane, FLOAT fFarPlane );
\r
140 // Functions to change behavior
\r
141 virtual void SetDragRect( RECT& rc )
\r
145 void SetInvertPitch( bool bInvertPitch )
\r
147 m_bInvertPitch = bInvertPitch;
\r
149 void SetDrag( bool bMovementDrag, FLOAT fTotalDragTimeToZero = 0.25f )
\r
151 m_bMovementDrag = bMovementDrag; m_fTotalDragTimeToZero = fTotalDragTimeToZero;
\r
153 void SetEnableYAxisMovement( bool bEnableYAxisMovement )
\r
155 m_bEnableYAxisMovement = bEnableYAxisMovement;
\r
157 void SetEnablePositionMovement( bool bEnablePositionMovement )
\r
159 m_bEnablePositionMovement = bEnablePositionMovement;
\r
161 void SetClipToBoundary( bool bClipToBoundary, D3DXVECTOR3* pvMinBoundary,
\r
162 D3DXVECTOR3* pvMaxBoundary )
\r
164 m_bClipToBoundary = bClipToBoundary; if( pvMinBoundary ) m_vMinBoundary = *pvMinBoundary;
\r
165 if( pvMaxBoundary ) m_vMaxBoundary = *pvMaxBoundary;
\r
167 void SetScalers( FLOAT fRotationScaler = 0.01f, FLOAT fMoveScaler = 5.0f )
\r
169 m_fRotationScaler = fRotationScaler; m_fMoveScaler = fMoveScaler;
\r
171 void SetNumberOfFramesToSmoothMouseData( int nFrames )
\r
173 if( nFrames > 0 ) m_fFramesToSmoothMouseData = ( float )nFrames;
\r
175 void SetResetCursorAfterMove( bool bResetCursorAfterMove )
\r
177 m_bResetCursorAfterMove = bResetCursorAfterMove;
\r
180 // Functions to get state
\r
181 const D3DXMATRIX* GetViewMatrix() const
\r
185 const D3DXMATRIX* GetProjMatrix() const
\r
189 const D3DXVECTOR3* GetEyePt() const
\r
193 const D3DXVECTOR3* GetLookAtPt() const
\r
197 float GetNearClip() const
\r
199 return m_fNearPlane;
\r
201 float GetFarClip() const
\r
203 return m_fFarPlane;
\r
206 bool IsBeingDragged() const
\r
208 return ( m_bMouseLButtonDown || m_bMouseMButtonDown || m_bMouseRButtonDown );
\r
210 bool IsMouseLButtonDown() const
\r
212 return m_bMouseLButtonDown;
\r
214 bool IsMouseMButtonDown() const
\r
216 return m_bMouseMButtonDown;
\r
218 bool IsMouseRButtonDown() const
\r
220 return m_bMouseRButtonDown;
\r
224 // Functions to map a WM_KEYDOWN key to a D3DUtil_CameraKeys enum
\r
225 virtual D3DUtil_CameraKeys MapKey( UINT nKey );
\r
226 bool IsKeyDown( BYTE key ) const
\r
228 return( ( key & KEY_IS_DOWN_MASK ) == KEY_IS_DOWN_MASK );
\r
230 bool WasKeyDown( BYTE key ) const
\r
232 return( ( key & KEY_WAS_DOWN_MASK ) == KEY_WAS_DOWN_MASK );
\r
235 void ConstrainToBoundary( D3DXVECTOR3* pV );
\r
236 void UpdateMouseDelta();
\r
237 void UpdateVelocity( float fElapsedTime );
\r
238 void GetInput( bool bGetKeyboardInput, bool bGetMouseInput, bool bGetGamepadInput,
\r
239 bool bResetCursorAfterMove );
\r
241 D3DXMATRIX m_mView; // View matrix
\r
242 D3DXMATRIX m_mProj; // Projection matrix
\r
244 DXUT_GAMEPAD m_GamePad[DXUT_MAX_CONTROLLERS]; // XInput controller state
\r
245 D3DXVECTOR3 m_vGamePadLeftThumb;
\r
246 D3DXVECTOR3 m_vGamePadRightThumb;
\r
247 double m_GamePadLastActive[DXUT_MAX_CONTROLLERS];
\r
249 int m_cKeysDown; // Number of camera keys that are down.
\r
250 BYTE m_aKeys[CAM_MAX_KEYS]; // State of input - KEY_WAS_DOWN_MASK|KEY_IS_DOWN_MASK
\r
251 D3DXVECTOR3 m_vKeyboardDirection; // Direction vector of keyboard input
\r
252 POINT m_ptLastMousePosition; // Last absolute position of mouse cursor
\r
253 bool m_bMouseLButtonDown; // True if left button is down
\r
254 bool m_bMouseMButtonDown; // True if middle button is down
\r
255 bool m_bMouseRButtonDown; // True if right button is down
\r
256 int m_nCurrentButtonMask; // mask of which buttons are down
\r
257 int m_nMouseWheelDelta; // Amount of middle wheel scroll (+/-)
\r
258 D3DXVECTOR2 m_vMouseDelta; // Mouse relative delta smoothed over a few frames
\r
259 float m_fFramesToSmoothMouseData; // Number of frames to smooth mouse data over
\r
261 D3DXVECTOR3 m_vDefaultEye; // Default camera eye position
\r
262 D3DXVECTOR3 m_vDefaultLookAt; // Default LookAt position
\r
263 D3DXVECTOR3 m_vEye; // Camera eye position
\r
264 D3DXVECTOR3 m_vLookAt; // LookAt position
\r
265 float m_fCameraYawAngle; // Yaw angle of camera
\r
266 float m_fCameraPitchAngle; // Pitch angle of camera
\r
268 RECT m_rcDrag; // Rectangle within which a drag can be initiated.
\r
269 D3DXVECTOR3 m_vVelocity; // Velocity of camera
\r
270 bool m_bMovementDrag; // If true, then camera movement will slow to a stop otherwise movement is instant
\r
271 D3DXVECTOR3 m_vVelocityDrag; // Velocity drag force
\r
272 FLOAT m_fDragTimer; // Countdown timer to apply drag
\r
273 FLOAT m_fTotalDragTimeToZero; // Time it takes for velocity to go from full to 0
\r
274 D3DXVECTOR2 m_vRotVelocity; // Velocity of camera
\r
276 float m_fFOV; // Field of view
\r
277 float m_fAspect; // Aspect ratio
\r
278 float m_fNearPlane; // Near plane
\r
279 float m_fFarPlane; // Far plane
\r
281 float m_fRotationScaler; // Scaler for rotation
\r
282 float m_fMoveScaler; // Scaler for movement
\r
284 bool m_bInvertPitch; // Invert the pitch axis
\r
285 bool m_bEnablePositionMovement; // If true, then the user can translate the camera/model
\r
286 bool m_bEnableYAxisMovement; // If true, then camera can move in the y-axis
\r
288 bool m_bClipToBoundary; // If true, then the camera will be clipped to the boundary
\r
289 D3DXVECTOR3 m_vMinBoundary; // Min point in clip boundary
\r
290 D3DXVECTOR3 m_vMaxBoundary; // Max point in clip boundary
\r
292 bool m_bResetCursorAfterMove;// If true, the class will reset the cursor position so that the cursor always has space to move
\r
296 //--------------------------------------------------------------------------------------
\r
297 // Simple first person camera class that moves and rotates.
\r
298 // It allows yaw and pitch but not roll. It uses WM_KEYDOWN and
\r
299 // GetCursorPos() to respond to keyboard and mouse input and updates the
\r
300 // view matrix based on input.
\r
301 //--------------------------------------------------------------------------------------
\r
302 class CFirstPersonCamera : public CBaseCamera
\r
305 CFirstPersonCamera();
\r
307 // Call these from client and use Get*Matrix() to read new matrices
\r
308 virtual void FrameMove( FLOAT fElapsedTime );
\r
310 // Functions to change behavior
\r
311 void SetRotateButtons( bool bLeft, bool bMiddle, bool bRight, bool bRotateWithoutButtonDown = false );
\r
313 // Functions to get state
\r
314 D3DXMATRIX* GetWorldMatrix()
\r
316 return &m_mCameraWorld;
\r
319 const D3DXVECTOR3* GetWorldRight() const
\r
321 return ( D3DXVECTOR3* )&m_mCameraWorld._11;
\r
323 const D3DXVECTOR3* GetWorldUp() const
\r
325 return ( D3DXVECTOR3* )&m_mCameraWorld._21;
\r
327 const D3DXVECTOR3* GetWorldAhead() const
\r
329 return ( D3DXVECTOR3* )&m_mCameraWorld._31;
\r
331 const D3DXVECTOR3* GetEyePt() const
\r
333 return ( D3DXVECTOR3* )&m_mCameraWorld._41;
\r
337 D3DXMATRIX m_mCameraWorld; // World matrix of the camera (inverse of the view matrix)
\r
339 int m_nActiveButtonMask; // Mask to determine which button to enable for rotation
\r
340 bool m_bRotateWithoutButtonDown;
\r
344 //--------------------------------------------------------------------------------------
\r
345 // Simple model viewing camera class that rotates around the object.
\r
346 //--------------------------------------------------------------------------------------
\r
347 class CModelViewerCamera : public CBaseCamera
\r
350 CModelViewerCamera();
\r
352 // Call these from client and use Get*Matrix() to read new matrices
\r
353 virtual LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
\r
354 virtual void FrameMove( FLOAT fElapsedTime );
\r
357 // Functions to change behavior
\r
358 virtual void SetDragRect( RECT& rc );
\r
360 void SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt );
\r
361 void SetButtonMasks( int nRotateModelButtonMask = MOUSE_LEFT_BUTTON, int nZoomButtonMask = MOUSE_WHEEL,
\r
362 int nRotateCameraButtonMask = MOUSE_RIGHT_BUTTON )
\r
364 m_nRotateModelButtonMask = nRotateModelButtonMask, m_nZoomButtonMask = nZoomButtonMask;
\r
365 m_nRotateCameraButtonMask = nRotateCameraButtonMask;
\r
367 void SetAttachCameraToModel( bool bEnable = false )
\r
369 m_bAttachCameraToModel = bEnable;
\r
371 void SetWindow( int nWidth, int nHeight, float fArcballRadius=0.9f )
\r
373 m_WorldArcBall.SetWindow( nWidth, nHeight, fArcballRadius );
\r
374 m_ViewArcBall.SetWindow( nWidth, nHeight, fArcballRadius );
\r
376 void SetRadius( float fDefaultRadius=5.0f, float fMinRadius=1.0f, float fMaxRadius=FLT_MAX )
\r
378 m_fDefaultRadius = m_fRadius = fDefaultRadius; m_fMinRadius = fMinRadius; m_fMaxRadius = fMaxRadius;
\r
379 m_bDragSinceLastUpdate = true;
\r
381 void SetModelCenter( D3DXVECTOR3 vModelCenter )
\r
383 m_vModelCenter = vModelCenter;
\r
385 void SetLimitPitch( bool bLimitPitch )
\r
387 m_bLimitPitch = bLimitPitch;
\r
389 void SetViewQuat( D3DXQUATERNION q )
\r
391 m_ViewArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true;
\r
393 void SetWorldQuat( D3DXQUATERNION q )
\r
395 m_WorldArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true;
\r
398 // Functions to get state
\r
399 const D3DXMATRIX* GetWorldMatrix() const
\r
403 void SetWorldMatrix( D3DXMATRIX& mWorld )
\r
405 m_mWorld = mWorld; m_bDragSinceLastUpdate = true;
\r
409 CD3DArcBall m_WorldArcBall;
\r
410 CD3DArcBall m_ViewArcBall;
\r
411 D3DXVECTOR3 m_vModelCenter;
\r
412 D3DXMATRIX m_mModelLastRot; // Last arcball rotation matrix for model
\r
413 D3DXMATRIX m_mModelRot; // Rotation matrix of model
\r
414 D3DXMATRIX m_mWorld; // World matrix of model
\r
416 int m_nRotateModelButtonMask;
\r
417 int m_nZoomButtonMask;
\r
418 int m_nRotateCameraButtonMask;
\r
420 bool m_bAttachCameraToModel;
\r
421 bool m_bLimitPitch;
\r
422 float m_fRadius; // Distance from the camera to model
\r
423 float m_fDefaultRadius; // Distance from the camera to model
\r
424 float m_fMinRadius; // Min radius
\r
425 float m_fMaxRadius; // Max radius
\r
426 bool m_bDragSinceLastUpdate; // True if mouse drag has happened since last time FrameMove is called.
\r
428 D3DXMATRIX m_mCameraRotLast;
\r
432 //--------------------------------------------------------------------------------------
\r
433 // Manages the mesh, direction, mouse events of a directional arrow that
\r
434 // rotates around a radius controlled by an arcball
\r
435 //--------------------------------------------------------------------------------------
\r
436 class CDXUTDirectionWidget
\r
439 CDXUTDirectionWidget();
\r
441 static HRESULT WINAPI StaticOnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice );
\r
442 HRESULT OnD3D9ResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
\r
443 HRESULT OnRender9( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj,
\r
444 const D3DXVECTOR3* pEyePt );
\r
445 LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
\r
446 static void WINAPI StaticOnD3D9LostDevice();
\r
447 static void WINAPI StaticOnD3D9DestroyDevice();
\r
449 static HRESULT WINAPI StaticOnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext );
\r
450 HRESULT OnRender11( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj,
\r
451 const D3DXVECTOR3* pEyePt );
\r
452 static void WINAPI StaticOnD3D11DestroyDevice();
\r
454 D3DXVECTOR3 GetLightDirection()
\r
456 return m_vCurrentDir;
\r
458 void SetLightDirection( D3DXVECTOR3 vDir )
\r
460 m_vDefaultDir = m_vCurrentDir = vDir;
\r
462 void SetButtonMask( int nRotate = MOUSE_RIGHT_BUTTON )
\r
464 m_nRotateMask = nRotate;
\r
471 void SetRadius( float fRadius )
\r
473 m_fRadius = fRadius;
\r
476 bool IsBeingDragged()
\r
478 return m_ArcBall.IsBeingDragged();
\r
482 HRESULT UpdateLightDir();
\r
485 static IDirect3DDevice9* s_pd3d9Device;
\r
486 static ID3DXEffect* s_pD3D9Effect;
\r
487 static ID3DXMesh* s_pD3D9Mesh;
\r
488 static D3DXHANDLE s_hRenderWith1LightNoTexture;
\r
489 static D3DXHANDLE s_hMaterialDiffuseColor;
\r
490 static D3DXHANDLE s_hLightDir;
\r
491 static D3DXHANDLE s_hWorldViewProjection;
\r
492 static D3DXHANDLE s_hWorld;
\r
495 //static ID3D10Device* s_pd3d10Device;
\r
496 //static ID3D10Effect* s_pD3D10Effect;
\r
497 //TODO: add some sort of d3d10 mesh object here
\r
498 //static ID3D10InputLayout* s_pVertexLayout;
\r
499 //static ID3D10EffectTechnique* s_pRenderTech;
\r
500 //static ID3D10EffectVectorVariable* g_pMaterialDiffuseColor;
\r
501 //static ID3D10EffectVectorVariable* g_pLightDir;
\r
502 //static ID3D10EffectMatrixVariable* g_pmWorld;
\r
503 //static ID3D10EffectMatrixVariable* g_pmWorldViewProjection;
\r
505 D3DXMATRIXA16 m_mRot;
\r
506 D3DXMATRIXA16 m_mRotSnapshot;
\r
509 CD3DArcBall m_ArcBall;
\r
510 D3DXVECTOR3 m_vDefaultDir;
\r
511 D3DXVECTOR3 m_vCurrentDir;
\r
512 D3DXMATRIX m_mView;
\r