summaryrefslogtreecommitdiff
path: root/demo/common/DXUTcamera.h
blob: c29b10443ffd4632c91b1da470794d8336aefde6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
//--------------------------------------------------------------------------------------
// File: Camera.h
//
// Helper functions for Direct3D programming.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//--------------------------------------------------------------------------------------
#pragma once
#ifndef CAMERA_H
#define CAMERA_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