1 //--------------------------------------------------------------------------------------
2 // File: DXUTMisc.h
3 //
4 // Helper functions for Direct3D programming.
5 //
6 // Copyright (c) Microsoft Corporation. All rights reserved
7 //--------------------------------------------------------------------------------------
8 #pragma once
9 #ifndef DXUT_MISC_H
10 #define DXUT_MISC_H
11
12 //--------------------------------------------------------------------------------------
13 // XInput helper state/function
14 // This performs extra processing on XInput gamepad data to make it slightly more convenient to use
15 //
16 // Example usage:
17 //
18 // DXUT_GAMEPAD gamepad[4];
19 // for( DWORD iPort=0; iPort<DXUT_MAX_CONTROLLERS; iPort++ )
20 // DXUTGetGamepadState( iPort, gamepad[iPort] );
21 //
22 //--------------------------------------------------------------------------------------
23 #define DXUT_MAX_CONTROLLERS 4 // XInput handles up to 4 controllers
24
25 struct DXUT_GAMEPAD
26 {
27 // From XINPUT_GAMEPAD
28 WORD wButtons;
29 BYTE bLeftTrigger;
30 BYTE bRightTrigger;
31 SHORT sThumbLX;
32 SHORT sThumbLY;
33 SHORT sThumbRX;
34 SHORT sThumbRY;
35
36 // Device properties
37 XINPUT_CAPABILITIES caps;
38 bool bConnected; // If the controller is currently connected
39 bool bInserted; // If the controller was inserted this frame
40 bool bRemoved; // If the controller was removed this frame
41
42 // Thumb stick values converted to range [-1,+1]
43 float fThumbRX;
44 float fThumbRY;
45 float fThumbLX;
46 float fThumbLY;
47
48 // Records which buttons were pressed this frame.
49 // These are only set on the first frame that the button is pressed
50 WORD wPressedButtons;
51 bool bPressedLeftTrigger;
52 bool bPressedRightTrigger;
53
54 // Last state of the buttons
55 WORD wLastButtons;
56 bool bLastLeftTrigger;
57 bool bLastRightTrigger;
58 };
59
60 HRESULT DXUTGetGamepadState( DWORD dwPort, DXUT_GAMEPAD* pGamePad, bool bThumbstickDeadZone = true, bool bSnapThumbstickToCardinals = true );
61 HRESULT DXUTStopRumbleOnAllControllers();
62 void DXUTEnableXInput( bool bEnable );
63
64
65 //--------------------------------------------------------------------------------------
66 // A growable array
67 //--------------------------------------------------------------------------------------
68 template< typename TYPE >
69 class CGrowableArray
70 {
71 public:
CGrowableArray()72 CGrowableArray() { m_pData = NULL; m_nSize = 0; m_nMaxSize = 0; }
CGrowableArray(const CGrowableArray<TYPE> & a)73 CGrowableArray( const CGrowableArray<TYPE>& a ) { for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); }
~CGrowableArray()74 ~CGrowableArray() { RemoveAll(); }
75
76 const TYPE& operator[]( int nIndex ) const { return GetAt( nIndex ); }
77 TYPE& operator[]( int nIndex ) { return GetAt( nIndex ); }
78
79 CGrowableArray& operator=( const CGrowableArray<TYPE>& a ) { if( this == &a ) return *this; RemoveAll(); for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); return *this; }
80
81 HRESULT SetSize( int nNewMaxSize );
82 HRESULT Add( const TYPE& value );
83 HRESULT Insert( int nIndex, const TYPE& value );
84 HRESULT SetAt( int nIndex, const TYPE& value );
GetAt(int nIndex)85 TYPE& GetAt( int nIndex ) { assert( nIndex >= 0 && nIndex < m_nSize ); return m_pData[nIndex]; }
GetSize()86 int GetSize() const { return m_nSize; }
GetData()87 TYPE* GetData() { return m_pData; }
Contains(const TYPE & value)88 bool Contains( const TYPE& value ){ return ( -1 != IndexOf( value ) ); }
89
IndexOf(const TYPE & value)90 int IndexOf( const TYPE& value ) { return ( m_nSize > 0 ) ? IndexOf( value, 0, m_nSize ) : -1; }
IndexOf(const TYPE & value,int iStart)91 int IndexOf( const TYPE& value, int iStart ) { return IndexOf( value, iStart, m_nSize - iStart ); }
92 int IndexOf( const TYPE& value, int nIndex, int nNumElements );
93
LastIndexOf(const TYPE & value)94 int LastIndexOf( const TYPE& value ) { return ( m_nSize > 0 ) ? LastIndexOf( value, m_nSize-1, m_nSize ) : -1; }
LastIndexOf(const TYPE & value,int nIndex)95 int LastIndexOf( const TYPE& value, int nIndex ) { return LastIndexOf( value, nIndex, nIndex+1 ); }
96 int LastIndexOf( const TYPE& value, int nIndex, int nNumElements );
97
98 HRESULT Remove( int nIndex );
RemoveAll()99 void RemoveAll() { SetSize(0); }
100
101 protected:
102 TYPE* m_pData; // the actual array of data
103 int m_nSize; // # of elements (upperBound - 1)
104 int m_nMaxSize; // max allocated
105
106 HRESULT SetSizeInternal( int nNewMaxSize ); // This version doesn't call ctor or dtor.
107 };
108
109
110 //--------------------------------------------------------------------------------------
111 // Performs timer operations
112 // Use DXUTGetGlobalTimer() to get the global instance
113 //--------------------------------------------------------------------------------------
114 class CDXUTTimer
115 {
116 public:
117 CDXUTTimer();
118
119 void Reset(); // resets the timer
120 void Start(); // starts the timer
121 void Stop(); // stop (or pause) the timer
122 void Advance(); // advance the timer by 0.1 seconds
123 double GetAbsoluteTime(); // get the absolute system time
124 double GetTime(); // get the current time
125 double GetElapsedTime(); // get the time that elapsed between Get*ElapsedTime() calls
126 void GetTimeValues( double* pfTime, double* pfAbsoluteTime, float* pfElapsedTime ); // get all time values at once
127 bool IsStopped(); // returns true if timer stopped
128
129 // Limit the current thread to one processor (the current one). This ensures that timing code runs
130 // on only one processor, and will not suffer any ill effects from power management.
131 void LimitThreadAffinityToCurrentProc();
132
133 protected:
134 LARGE_INTEGER GetAdjustedCurrentTime();
135
136 bool m_bTimerStopped;
137 LONGLONG m_llQPFTicksPerSec;
138
139 LONGLONG m_llStopTime;
140 LONGLONG m_llLastElapsedTime;
141 LONGLONG m_llBaseTime;
142 };
143
144 CDXUTTimer* DXUTGetGlobalTimer();
145
146
147 //-----------------------------------------------------------------------------
148 // Resource cache for textures, fonts, meshs, and effects.
149 // Use DXUTGetGlobalResourceCache() to access the global cache
150 //-----------------------------------------------------------------------------
151
152 enum DXUTCACHE_SOURCELOCATION { DXUTCACHE_LOCATION_FILE, DXUTCACHE_LOCATION_RESOURCE };
153
154 struct DXUTCache_Texture
155 {
156 DXUTCACHE_SOURCELOCATION Location;
157 WCHAR wszSource[MAX_PATH];
158 HMODULE hSrcModule;
159 UINT Width;
160 UINT Height;
161 UINT Depth;
162 UINT MipLevels;
163 DWORD Usage;
164 D3DFORMAT Format;
165 D3DPOOL Pool;
166 D3DRESOURCETYPE Type;
167 IDirect3DBaseTexture9 *pTexture;
168 };
169
170 struct DXUTCache_Font : public D3DXFONT_DESC
171 {
172 ID3DXFont *pFont;
173 };
174
175 struct DXUTCache_Effect
176 {
177 DXUTCACHE_SOURCELOCATION Location;
178 WCHAR wszSource[MAX_PATH];
179 HMODULE hSrcModule;
180 DWORD dwFlags;
181 ID3DXEffect *pEffect;
182 };
183
184
185 class CDXUTResourceCache
186 {
187 public:
188 ~CDXUTResourceCache();
189
190 HRESULT CreateTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DTEXTURE9 *ppTexture );
191 HRESULT CreateTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, UINT Height, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DTEXTURE9 *ppTexture );
192 HRESULT CreateTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DTEXTURE9 *ppTexture );
193 HRESULT CreateTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Width, UINT Height, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DTEXTURE9 *ppTexture );
194 HRESULT CreateCubeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture );
195 HRESULT CreateCubeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture );
196 HRESULT CreateCubeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture );
197 HRESULT CreateCubeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture );
198 HRESULT CreateVolumeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DVOLUMETEXTURE9 *ppVolumeTexture );
199 HRESULT CreateVolumeTextureFromFileEx( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, UINT Width, UINT Height, UINT Depth, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DVOLUMETEXTURE9 *ppTexture );
200 HRESULT CreateVolumeTextureFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, LPDIRECT3DVOLUMETEXTURE9 *ppVolumeTexture );
201 HRESULT CreateVolumeTextureFromResourceEx( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, UINT Width, UINT Height, UINT Depth, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey, D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DVOLUMETEXTURE9 *ppVolumeTexture );
202 HRESULT CreateFont( LPDIRECT3DDEVICE9 pDevice, UINT Height, UINT Width, UINT Weight, UINT MipLevels, BOOL Italic, DWORD CharSet, DWORD OutputPrecision, DWORD Quality, DWORD PitchAndFamily, LPCTSTR pFacename, LPD3DXFONT *ppFont );
203 HRESULT CreateFontIndirect( LPDIRECT3DDEVICE9 pDevice, CONST D3DXFONT_DESC *pDesc, LPD3DXFONT *ppFont );
204 HRESULT CreateEffectFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, const D3DXMACRO *pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT *ppEffect, LPD3DXBUFFER *ppCompilationErrors );
205 HRESULT CreateEffectFromResource( LPDIRECT3DDEVICE9 pDevice, HMODULE hSrcModule, LPCTSTR pSrcResource, const D3DXMACRO *pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXEFFECTPOOL pPool, LPD3DXEFFECT *ppEffect, LPD3DXBUFFER *ppCompilationErrors );
206
207 public:
208 HRESULT OnCreateDevice( IDirect3DDevice9 *pd3dDevice );
209 HRESULT OnResetDevice( IDirect3DDevice9 *pd3dDevice );
210 HRESULT OnLostDevice();
211 HRESULT OnDestroyDevice();
212
213 protected:
214 friend CDXUTResourceCache& DXUTGetGlobalResourceCache();
215 friend HRESULT DXUTInitialize3DEnvironment();
216 friend HRESULT DXUTReset3DEnvironment();
217 friend void DXUTCleanup3DEnvironment( bool bReleaseSettings );
218
CDXUTResourceCache()219 CDXUTResourceCache() { }
220
221 CGrowableArray< DXUTCache_Texture > m_TextureCache;
222 CGrowableArray< DXUTCache_Effect > m_EffectCache;
223 CGrowableArray< DXUTCache_Font > m_FontCache;
224 };
225
226 CDXUTResourceCache& DXUTGetGlobalResourceCache();
227
228
229 //--------------------------------------------------------------------------------------
230 class CD3DArcBall
231 {
232 public:
233 CD3DArcBall();
234
235 // Functions to change behavior
236 void Reset();
SetTranslationRadius(FLOAT fRadiusTranslation)237 void SetTranslationRadius( FLOAT fRadiusTranslation ) { m_fRadiusTranslation = fRadiusTranslation; }
238 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); }
SetOffset(INT nX,INT nY)239 void SetOffset( INT nX, INT nY ) { m_Offset.x = nX; m_Offset.y = nY; }
240
241 // Call these from client and use GetRotationMatrix() to read new rotation matrix
242 void OnBegin( int nX, int nY ); // start the rotation (pass current mouse position)
243 void OnMove( int nX, int nY ); // continue the rotation (pass current mouse position)
244 void OnEnd(); // end the rotation
245
246 // Or call this to automatically handle left, middle, right buttons
247 LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
248
249 // Functions to get/set state
GetRotationMatrix()250 const D3DXMATRIX* GetRotationMatrix() { return D3DXMatrixRotationQuaternion(&m_mRotation, &m_qNow); };
GetTranslationMatrix()251 const D3DXMATRIX* GetTranslationMatrix() const { return &m_mTranslation; }
GetTranslationDeltaMatrix()252 const D3DXMATRIX* GetTranslationDeltaMatrix() const { return &m_mTranslationDelta; }
IsBeingDragged()253 bool IsBeingDragged() const { return m_bDrag; }
GetQuatNow()254 D3DXQUATERNION GetQuatNow() const { return m_qNow; }
SetQuatNow(D3DXQUATERNION q)255 void SetQuatNow( D3DXQUATERNION q ) { m_qNow = q; }
256
257 static D3DXQUATERNION QuatFromBallPoints( const D3DXVECTOR3 &vFrom, const D3DXVECTOR3 &vTo );
258
259
260 protected:
261 D3DXMATRIXA16 m_mRotation; // Matrix for arc ball's orientation
262 D3DXMATRIXA16 m_mTranslation; // Matrix for arc ball's position
263 D3DXMATRIXA16 m_mTranslationDelta; // Matrix for arc ball's position
264
265 POINT m_Offset; // window offset, or upper-left corner of window
266 INT m_nWidth; // arc ball's window width
267 INT m_nHeight; // arc ball's window height
268 D3DXVECTOR2 m_vCenter; // center of arc ball
269 FLOAT m_fRadius; // arc ball's radius in screen coords
270 FLOAT m_fRadiusTranslation; // arc ball's radius for translating the target
271
272 D3DXQUATERNION m_qDown; // Quaternion before button down
273 D3DXQUATERNION m_qNow; // Composite quaternion for current drag
274 bool m_bDrag; // Whether user is dragging arc ball
275
276 POINT m_ptLastMouse; // position of last mouse point
277 D3DXVECTOR3 m_vDownPt; // starting point of rotation arc
278 D3DXVECTOR3 m_vCurrentPt; // current point of rotation arc
279
280 D3DXVECTOR3 ScreenToVector( float fScreenPtX, float fScreenPtY );
281 };
282
283
284 //--------------------------------------------------------------------------------------
285 // used by CCamera to map WM_KEYDOWN keys
286 //--------------------------------------------------------------------------------------
287 enum D3DUtil_CameraKeys
288 {
289 CAM_STRAFE_LEFT = 0,
290 CAM_STRAFE_RIGHT,
291 CAM_MOVE_FORWARD,
292 CAM_MOVE_BACKWARD,
293 CAM_MOVE_UP,
294 CAM_MOVE_DOWN,
295 CAM_RESET,
296 CAM_CONTROLDOWN,
297 CAM_MAX_KEYS,
298 CAM_UNKNOWN = 0xFF
299 };
300
301 #define KEY_WAS_DOWN_MASK 0x80
302 #define KEY_IS_DOWN_MASK 0x01
303
304 #define MOUSE_LEFT_BUTTON 0x01
305 #define MOUSE_MIDDLE_BUTTON 0x02
306 #define MOUSE_RIGHT_BUTTON 0x04
307 #define MOUSE_WHEEL 0x08
308
309
310 //--------------------------------------------------------------------------------------
311 // Simple base camera class that moves and rotates. The base class
312 // records mouse and keyboard input for use by a derived class, and
313 // keeps common state.
314 //--------------------------------------------------------------------------------------
315 class CBaseCamera
316 {
317 public:
318 CBaseCamera();
319
320 // Call these from client and use Get*Matrix() to read new matrices
321 virtual LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
322 virtual void FrameMove( FLOAT fElapsedTime ) = 0;
323
324 // Functions to change camera matrices
325 virtual void Reset();
326 virtual void SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt );
327 virtual void SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane, FLOAT fFarPlane );
328
329 // Functions to change behavior
SetDragRect(RECT & rc)330 virtual void SetDragRect( RECT &rc ) { m_rcDrag = rc; }
SetInvertPitch(bool bInvertPitch)331 void SetInvertPitch( bool bInvertPitch ) { m_bInvertPitch = bInvertPitch; }
332 void SetDrag( bool bMovementDrag, FLOAT fTotalDragTimeToZero = 0.25f ) { m_bMovementDrag = bMovementDrag; m_fTotalDragTimeToZero = fTotalDragTimeToZero; }
SetEnableYAxisMovement(bool bEnableYAxisMovement)333 void SetEnableYAxisMovement( bool bEnableYAxisMovement ) { m_bEnableYAxisMovement = bEnableYAxisMovement; }
SetEnablePositionMovement(bool bEnablePositionMovement)334 void SetEnablePositionMovement( bool bEnablePositionMovement ) { m_bEnablePositionMovement = bEnablePositionMovement; }
SetClipToBoundary(bool bClipToBoundary,D3DXVECTOR3 * pvMinBoundary,D3DXVECTOR3 * pvMaxBoundary)335 void SetClipToBoundary( bool bClipToBoundary, D3DXVECTOR3* pvMinBoundary, D3DXVECTOR3* pvMaxBoundary ) { m_bClipToBoundary = bClipToBoundary; if( pvMinBoundary ) m_vMinBoundary = *pvMinBoundary; if( pvMaxBoundary ) m_vMaxBoundary = *pvMaxBoundary; }
336 void SetScalers( FLOAT fRotationScaler = 0.01f, FLOAT fMoveScaler = 5.0f ) { m_fRotationScaler = fRotationScaler; m_fMoveScaler = fMoveScaler; }
SetNumberOfFramesToSmoothMouseData(int nFrames)337 void SetNumberOfFramesToSmoothMouseData( int nFrames ) { if( nFrames > 0 ) m_fFramesToSmoothMouseData = (float)nFrames; }
338
339 // Functions to get state
GetViewMatrix()340 const D3DXMATRIX* GetViewMatrix() const { return &m_mView; }
GetProjMatrix()341 const D3DXMATRIX* GetProjMatrix() const { return &m_mProj; }
GetEyePt()342 const D3DXVECTOR3* GetEyePt() const { return &m_vEye; }
GetLookAtPt()343 const D3DXVECTOR3* GetLookAtPt() const { return &m_vLookAt; }
GetNearClip()344 float GetNearClip() const { return m_fNearPlane; }
GetFarClip()345 float GetFarClip() const { return m_fFarPlane; }
346
IsBeingDragged()347 bool IsBeingDragged() const { return (m_bMouseLButtonDown || m_bMouseMButtonDown || m_bMouseRButtonDown); }
IsMouseLButtonDown()348 bool IsMouseLButtonDown() const { return m_bMouseLButtonDown; }
IsMouseMButtonDown()349 bool IsMouseMButtonDown() const { return m_bMouseMButtonDown; }
IsMouseRButtonDown()350 bool IsMouseRButtonDown() const { return m_bMouseRButtonDown; }
351
352 protected:
353 // Functions to map a WM_KEYDOWN key to a D3DUtil_CameraKeys enum
354 virtual D3DUtil_CameraKeys MapKey( UINT nKey );
IsKeyDown(BYTE key)355 bool IsKeyDown( BYTE key ) const { return( (key & KEY_IS_DOWN_MASK) == KEY_IS_DOWN_MASK ); }
WasKeyDown(BYTE key)356 bool WasKeyDown( BYTE key ) const { return( (key & KEY_WAS_DOWN_MASK) == KEY_WAS_DOWN_MASK ); }
357
358 void ConstrainToBoundary( D3DXVECTOR3* pV );
359 void UpdateVelocity( float fElapsedTime );
360 void GetInput( bool bGetKeyboardInput, bool bGetMouseInput, bool bGetGamepadInput, bool bResetCursorAfterMove );
361
362 D3DXMATRIX m_mView; // View matrix
363 D3DXMATRIX m_mProj; // Projection matrix
364
365 DXUT_GAMEPAD m_GamePad[DXUT_MAX_CONTROLLERS]; // XInput controller state
366 D3DXVECTOR3 m_vGamePadLeftThumb;
367 D3DXVECTOR3 m_vGamePadRightThumb;
368 double m_GamePadLastActive[DXUT_MAX_CONTROLLERS];
369
370 int m_cKeysDown; // Number of camera keys that are down.
371 BYTE m_aKeys[CAM_MAX_KEYS]; // State of input - KEY_WAS_DOWN_MASK|KEY_IS_DOWN_MASK
372 D3DXVECTOR3 m_vKeyboardDirection; // Direction vector of keyboard input
373 POINT m_ptLastMousePosition; // Last absolute position of mouse cursor
374 bool m_bMouseLButtonDown; // True if left button is down
375 bool m_bMouseMButtonDown; // True if middle button is down
376 bool m_bMouseRButtonDown; // True if right button is down
377 int m_nCurrentButtonMask; // mask of which buttons are down
378 int m_nMouseWheelDelta; // Amount of middle wheel scroll (+/-)
379 D3DXVECTOR2 m_vMouseDelta; // Mouse relative delta smoothed over a few frames
380 float m_fFramesToSmoothMouseData; // Number of frames to smooth mouse data over
381
382 D3DXVECTOR3 m_vDefaultEye; // Default camera eye position
383 D3DXVECTOR3 m_vDefaultLookAt; // Default LookAt position
384 D3DXVECTOR3 m_vEye; // Camera eye position
385 D3DXVECTOR3 m_vLookAt; // LookAt position
386 float m_fCameraYawAngle; // Yaw angle of camera
387 float m_fCameraPitchAngle; // Pitch angle of camera
388
389 RECT m_rcDrag; // Rectangle within which a drag can be initiated.
390 D3DXVECTOR3 m_vVelocity; // Velocity of camera
391 bool m_bMovementDrag; // If true, then camera movement will slow to a stop otherwise movement is instant
392 D3DXVECTOR3 m_vVelocityDrag; // Velocity drag force
393 FLOAT m_fDragTimer; // Countdown timer to apply drag
394 FLOAT m_fTotalDragTimeToZero; // Time it takes for velocity to go from full to 0
395 D3DXVECTOR2 m_vRotVelocity; // Velocity of camera
396
397 float m_fFOV; // Field of view
398 float m_fAspect; // Aspect ratio
399 float m_fNearPlane; // Near plane
400 float m_fFarPlane; // Far plane
401
402 float m_fRotationScaler; // Scaler for rotation
403 float m_fMoveScaler; // Scaler for movement
404
405 bool m_bInvertPitch; // Invert the pitch axis
406 bool m_bEnablePositionMovement; // If true, then the user can translate the camera/model
407 bool m_bEnableYAxisMovement; // If true, then camera can move in the y-axis
408
409 bool m_bClipToBoundary; // If true, then the camera will be clipped to the boundary
410 D3DXVECTOR3 m_vMinBoundary; // Min point in clip boundary
411 D3DXVECTOR3 m_vMaxBoundary; // Max point in clip boundary
412 };
413
414
415 //--------------------------------------------------------------------------------------
416 // Simple first person camera class that moves and rotates.
417 // It allows yaw and pitch but not roll. It uses WM_KEYDOWN and
418 // GetCursorPos() to respond to keyboard and mouse input and updates the
419 // view matrix based on input.
420 //--------------------------------------------------------------------------------------
421 class CFirstPersonCamera : public CBaseCamera
422 {
423 public:
424 CFirstPersonCamera();
425
426 // Call these from client and use Get*Matrix() to read new matrices
427 virtual void FrameMove( FLOAT fElapsedTime );
428
429 // Functions to change behavior
430 void SetRotateButtons( bool bLeft, bool bMiddle, bool bRight, bool bRotateWithoutButtonDown = false );
431
SetResetCursorAfterMove(bool bResetCursorAfterMove)432 void SetResetCursorAfterMove( bool bResetCursorAfterMove ) { m_bResetCursorAfterMove = bResetCursorAfterMove; }
433
434 // Functions to get state
GetWorldMatrix()435 D3DXMATRIX* GetWorldMatrix() { return &m_mCameraWorld; }
436
GetWorldRight()437 const D3DXVECTOR3* GetWorldRight() const { return (D3DXVECTOR3*)&m_mCameraWorld._11; }
GetWorldUp()438 const D3DXVECTOR3* GetWorldUp() const { return (D3DXVECTOR3*)&m_mCameraWorld._21; }
GetWorldAhead()439 const D3DXVECTOR3* GetWorldAhead() const { return (D3DXVECTOR3*)&m_mCameraWorld._31; }
GetEyePt()440 const D3DXVECTOR3* GetEyePt() const { return (D3DXVECTOR3*)&m_mCameraWorld._41; }
441
442 protected:
443 D3DXMATRIX m_mCameraWorld; // World matrix of the camera (inverse of the view matrix)
444
445 int m_nActiveButtonMask; // Mask to determine which button to enable for rotation
446 bool m_bRotateWithoutButtonDown;
447
448 bool m_bResetCursorAfterMove;// If true, the class will reset the cursor position so that the cursor always has space to move
449 };
450
451
452 //--------------------------------------------------------------------------------------
453 // Simple model viewing camera class that rotates around the object.
454 //--------------------------------------------------------------------------------------
455 class CModelViewerCamera : public CBaseCamera
456 {
457 public:
458 CModelViewerCamera();
459
460 // Call these from client and use Get*Matrix() to read new matrices
461 virtual LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
462 virtual void FrameMove( FLOAT fElapsedTime );
463
464
465 // Functions to change behavior
466 virtual void SetDragRect( RECT &rc );
467 void Reset();
468 void SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt );
469 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; }
470
471 void SetAttachCameraToModel( bool bEnable = false ) { m_bAttachCameraToModel = bEnable; }
472 void SetWindow( int nWidth, int nHeight, float fArcballRadius=0.9f ) { m_WorldArcBall.SetWindow( nWidth, nHeight, fArcballRadius ); m_ViewArcBall.SetWindow( nWidth, nHeight, fArcballRadius ); }
473 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; }
SetModelCenter(D3DXVECTOR3 vModelCenter)474 void SetModelCenter( D3DXVECTOR3 vModelCenter ) { m_vModelCenter = vModelCenter; }
SetLimitPitch(bool bLimitPitch)475 void SetLimitPitch( bool bLimitPitch ) { m_bLimitPitch = bLimitPitch; }
SetViewQuat(D3DXQUATERNION q)476 void SetViewQuat( D3DXQUATERNION q ) { m_ViewArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true; }
SetWorldQuat(D3DXQUATERNION q)477 void SetWorldQuat( D3DXQUATERNION q ) { m_WorldArcBall.SetQuatNow( q ); m_bDragSinceLastUpdate = true; }
478
479 // Functions to get state
GetWorldMatrix()480 const D3DXMATRIX* GetWorldMatrix() const { return &m_mWorld; }
SetWorldMatrix(D3DXMATRIX & mWorld)481 void SetWorldMatrix( D3DXMATRIX &mWorld ) { m_mWorld = mWorld; m_bDragSinceLastUpdate = true; }
482
483 protected:
484 CD3DArcBall m_WorldArcBall;
485 CD3DArcBall m_ViewArcBall;
486 D3DXVECTOR3 m_vModelCenter;
487 D3DXMATRIX m_mModelLastRot; // Last arcball rotation matrix for model
488 D3DXMATRIX m_mModelRot; // Rotation matrix of model
489 D3DXMATRIX m_mWorld; // World matrix of model
490
491 int m_nRotateModelButtonMask;
492 int m_nZoomButtonMask;
493 int m_nRotateCameraButtonMask;
494
495 bool m_bAttachCameraToModel;
496 bool m_bLimitPitch;
497 float m_fRadius; // Distance from the camera to model
498 float m_fDefaultRadius; // Distance from the camera to model
499 float m_fMinRadius; // Min radius
500 float m_fMaxRadius; // Max radius
501 bool m_bDragSinceLastUpdate; // True if mouse drag has happened since last time FrameMove is called.
502
503 D3DXMATRIX m_mCameraRotLast;
504
505 };
506
507
508 //--------------------------------------------------------------------------------------
509 // Manages the intertion point when drawing text
510 //--------------------------------------------------------------------------------------
511 class CDXUTTextHelper
512 {
513 public:
514 CDXUTTextHelper( ID3DXFont* pFont, ID3DXSprite* pSprite, int nLineHeight );
515
SetInsertionPos(int x,int y)516 void SetInsertionPos( int x, int y ) { m_pt.x = x; m_pt.y = y; }
SetForegroundColor(D3DXCOLOR clr)517 void SetForegroundColor( D3DXCOLOR clr ) { m_clr = clr; }
518
519 void Begin();
520 HRESULT DrawFormattedTextLine( const WCHAR* strMsg, ... );
521 HRESULT DrawTextLine( const WCHAR* strMsg );
522 HRESULT DrawFormattedTextLine( RECT &rc, DWORD dwFlags, const WCHAR* strMsg, ... );
523 HRESULT DrawTextLine( RECT &rc, DWORD dwFlags, const WCHAR* strMsg );
524 void End();
525
526 protected:
527 ID3DXFont* m_pFont;
528 ID3DXSprite* m_pSprite;
529 D3DXCOLOR m_clr;
530 POINT m_pt;
531 int m_nLineHeight;
532 };
533
534
535 //--------------------------------------------------------------------------------------
536 // Manages a persistent list of lines and draws them using ID3DXLine
537 //--------------------------------------------------------------------------------------
538 class CDXUTLineManager
539 {
540 public:
541 CDXUTLineManager();
542 ~CDXUTLineManager();
543
544 HRESULT OnCreatedDevice( IDirect3DDevice9* pd3dDevice );
545 HRESULT OnResetDevice();
546 HRESULT OnRender();
547 HRESULT OnLostDevice();
548 HRESULT OnDeletedDevice();
549
550 HRESULT AddLine( int* pnLineID, D3DXVECTOR2* pVertexList, DWORD dwVertexListCount, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias );
551 HRESULT AddRect( int* pnLineID, RECT rc, D3DCOLOR Color, float fWidth, float fScaleRatio, bool bAntiAlias );
552 HRESULT RemoveLine( int nLineID );
553 HRESULT RemoveAllLines();
554
555 protected:
556 struct LINE_NODE
557 {
558 int nLineID;
559 D3DCOLOR Color;
560 float fWidth;
561 bool bAntiAlias;
562 float fScaleRatio;
563 D3DXVECTOR2* pVertexList;
564 DWORD dwVertexListCount;
565 };
566
567 CGrowableArray<LINE_NODE*> m_LinesList;
568 IDirect3DDevice9* m_pd3dDevice;
569 ID3DXLine* m_pD3DXLine;
570 };
571
572
573 //--------------------------------------------------------------------------------------
574 // Manages the mesh, direction, mouse events of a directional arrow that
575 // rotates around a radius controlled by an arcball
576 //--------------------------------------------------------------------------------------
577 class CDXUTDirectionWidget
578 {
579 public:
580 CDXUTDirectionWidget();
581
582 static HRESULT StaticOnCreateDevice( IDirect3DDevice9* pd3dDevice );
583 HRESULT OnResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
584 HRESULT OnRender( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj, const D3DXVECTOR3* pEyePt );
585 LRESULT HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
586 static void StaticOnLostDevice();
587 static void StaticOnDestroyDevice();
588
GetLightDirection()589 D3DXVECTOR3 GetLightDirection() { return m_vCurrentDir; };
SetLightDirection(D3DXVECTOR3 vDir)590 void SetLightDirection( D3DXVECTOR3 vDir ) { m_vDefaultDir = m_vCurrentDir = vDir; };
591 void SetButtonMask( int nRotate = MOUSE_RIGHT_BUTTON ) { m_nRotateMask = nRotate; }
592
GetRadius()593 float GetRadius() { return m_fRadius; };
SetRadius(float fRadius)594 void SetRadius( float fRadius ) { m_fRadius = fRadius; };
595
IsBeingDragged()596 bool IsBeingDragged() { return m_ArcBall.IsBeingDragged(); };
597
598 protected:
599 HRESULT UpdateLightDir();
600
601 D3DXMATRIXA16 m_mRot;
602 D3DXMATRIXA16 m_mRotSnapshot;
603 static IDirect3DDevice9* s_pd3dDevice;
604 static ID3DXEffect* s_pEffect;
605 static ID3DXMesh* s_pMesh;
606
607 float m_fRadius;
608 int m_nRotateMask;
609 CD3DArcBall m_ArcBall;
610 D3DXVECTOR3 m_vDefaultDir;
611 D3DXVECTOR3 m_vCurrentDir;
612 D3DXMATRIX m_mView;
613 };
614
615
616 //--------------------------------------------------------------------------------------
617 // Shared code for samples to ask user if they want to use a REF device or quit
618 //--------------------------------------------------------------------------------------
619 void DXUTDisplaySwitchingToREFWarning();
620
621 //--------------------------------------------------------------------------------------
622 // Tries to finds a media file by searching in common locations
623 //--------------------------------------------------------------------------------------
624 HRESULT DXUTFindDXSDKMediaFileCch( WCHAR* strDestPath, int cchDest, LPCWSTR strFilename );
625 HRESULT DXUTSetMediaSearchPath( LPCWSTR strPath );
626 LPCWSTR DXUTGetMediaSearchPath();
627
628
629 //--------------------------------------------------------------------------------------
630 // Returns the string for the given D3DFORMAT.
631 // bWithPrefix determines whether the string should include the "D3DFMT_"
632 //--------------------------------------------------------------------------------------
633 LPCWSTR DXUTD3DFormatToString( D3DFORMAT format, bool bWithPrefix );
634
635
636 //--------------------------------------------------------------------------------------
637 // Returns a view matrix for rendering to a face of a cubemap.
638 //--------------------------------------------------------------------------------------
639 D3DXMATRIX DXUTGetCubeMapViewMatrix( DWORD dwFace );
640
641
642 //--------------------------------------------------------------------------------------
643 // Helper function to launch the Media Center UI after the program terminates
644 //--------------------------------------------------------------------------------------
645 bool DXUTReLaunchMediaCenter();
646
647
648 //--------------------------------------------------------------------------------------
649 // Debug printing support
650 // See dxerr.h for more debug printing support
651 //--------------------------------------------------------------------------------------
652 void DXUTOutputDebugStringW( LPCWSTR strMsg, ... );
653 void DXUTOutputDebugStringA( LPCSTR strMsg, ... );
654 HRESULT WINAPI DXUTTrace( const CHAR* strFile, DWORD dwLine, HRESULT hr, const WCHAR* strMsg, bool bPopMsgBox );
655 void DXUTTraceDecl( D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE] );
656 WCHAR* DXUTTraceD3DDECLUSAGEtoString( BYTE u );
657 WCHAR* DXUTTraceD3DDECLMETHODtoString( BYTE m );
658 WCHAR* DXUTTraceD3DDECLTYPEtoString( BYTE t );
659
660 #ifdef UNICODE
661 #define DXUTOutputDebugString DXUTOutputDebugStringW
662 #else
663 #define DXUTOutputDebugString DXUTOutputDebugStringA
664 #endif
665
666 // These macros are very similar to dxerr's but it special cases the HRESULT defined
667 // by DXUT to pop better message boxes.
668 #if defined(DEBUG) || defined(_DEBUG)
669 #define DXUT_ERR(str,hr) DXUTTrace( __FILE__, (DWORD)__LINE__, hr, str, false )
670 #define DXUT_ERR_MSGBOX(str,hr) DXUTTrace( __FILE__, (DWORD)__LINE__, hr, str, true )
671 #define DXUTTRACE DXUTOutputDebugString
672 #else
673 #define DXUT_ERR(str,hr) (hr)
674 #define DXUT_ERR_MSGBOX(str,hr) (hr)
675 #define DXUTTRACE (__noop)
676 #endif
677
678
679 //--------------------------------------------------------------------------------------
680 // Direct3D9 dynamic linking support -- calls top-level D3D9 APIs with graceful
681 // failure if APIs are not present.
682 //--------------------------------------------------------------------------------------
683
684 IDirect3D9 * WINAPI DXUT_Dynamic_Direct3DCreate9(UINT SDKVersion);
685 int WINAPI DXUT_Dynamic_D3DPERF_BeginEvent( D3DCOLOR col, LPCWSTR wszName );
686 int WINAPI DXUT_Dynamic_D3DPERF_EndEvent( void );
687 void WINAPI DXUT_Dynamic_D3DPERF_SetMarker( D3DCOLOR col, LPCWSTR wszName );
688 void WINAPI DXUT_Dynamic_D3DPERF_SetRegion( D3DCOLOR col, LPCWSTR wszName );
689 BOOL WINAPI DXUT_Dynamic_D3DPERF_QueryRepeatFrame( void );
690 void WINAPI DXUT_Dynamic_D3DPERF_SetOptions( DWORD dwOptions );
691 DWORD WINAPI DXUT_Dynamic_D3DPERF_GetStatus( void );
692
693
694 //--------------------------------------------------------------------------------------
695 // Profiling/instrumentation support
696 //--------------------------------------------------------------------------------------
697
698 //--------------------------------------------------------------------------------------
699 // Some D3DPERF APIs take a color that can be used when displaying user events in
700 // performance analysis tools. The following constants are provided for your
701 // convenience, but you can use any colors you like.
702 //--------------------------------------------------------------------------------------
703 const D3DCOLOR DXUT_PERFEVENTCOLOR = D3DCOLOR_XRGB(200,100,100);
704 const D3DCOLOR DXUT_PERFEVENTCOLOR2 = D3DCOLOR_XRGB(100,200,100);
705 const D3DCOLOR DXUT_PERFEVENTCOLOR3 = D3DCOLOR_XRGB(100,100,200);
706
707 //--------------------------------------------------------------------------------------
708 // The following macros provide a convenient way for your code to call the D3DPERF
709 // functions only when PROFILE is defined. If PROFILE is not defined (as for the final
710 // release version of a program), these macros evaluate to nothing, so no detailed event
711 // information is embedded in your shipping program. It is recommended that you create
712 // and use three build configurations for your projects:
713 // Debug (nonoptimized code, asserts active, PROFILE defined to assist debugging)
714 // Profile (optimized code, asserts disabled, PROFILE defined to assist optimization)
715 // Release (optimized code, asserts disabled, PROFILE not defined)
716 //--------------------------------------------------------------------------------------
717 #ifdef PROFILE
718 // PROFILE is defined, so these macros call the D3DPERF functions
719 #define DXUT_BeginPerfEvent( color, pstrMessage ) DXUT_Dynamic_D3DPERF_BeginEvent( color, pstrMessage )
720 #define DXUT_EndPerfEvent() DXUT_Dynamic_D3DPERF_EndEvent()
721 #define DXUT_SetPerfMarker( color, pstrMessage ) DXUT_Dynamic_D3DPERF_SetMarker( color, pstrMessage )
722 #else
723 // PROFILE is not defined, so these macros do nothing
724 #define DXUT_BeginPerfEvent( color, pstrMessage ) (__noop)
725 #define DXUT_EndPerfEvent() (__noop)
726 #define DXUT_SetPerfMarker( color, pstrMessage ) (__noop)
727 #endif
728
729 //--------------------------------------------------------------------------------------
730 // CDXUTPerfEventGenerator is a helper class that makes it easy to attach begin and end
731 // events to a block of code. Simply define a CDXUTPerfEventGenerator variable anywhere
732 // in a block of code, and the class's constructor will call DXUT_BeginPerfEvent when
733 // the block of code begins, and the class's destructor will call DXUT_EndPerfEvent when
734 // the block ends.
735 //--------------------------------------------------------------------------------------
736 class CDXUTPerfEventGenerator
737 {
738 public:
CDXUTPerfEventGenerator(D3DCOLOR color,LPCWSTR pstrMessage)739 CDXUTPerfEventGenerator( D3DCOLOR color, LPCWSTR pstrMessage ) { DXUT_BeginPerfEvent( color, pstrMessage ); }
~CDXUTPerfEventGenerator(void)740 ~CDXUTPerfEventGenerator( void ) { DXUT_EndPerfEvent(); }
741 };
742
743
744 //--------------------------------------------------------------------------------------
745 // Multimon handling to support OSes with or without multimon API support.
746 // Purposely avoiding the use of multimon.h so DXUT.lib doesn't require
747 // COMPILE_MULTIMON_STUBS and cause complication with MFC or other users of multimon.h
748 //--------------------------------------------------------------------------------------
749 #ifndef MONITOR_DEFAULTTOPRIMARY
750 #define MONITORINFOF_PRIMARY 0x00000001
751 #define MONITOR_DEFAULTTONULL 0x00000000
752 #define MONITOR_DEFAULTTOPRIMARY 0x00000001
753 #define MONITOR_DEFAULTTONEAREST 0x00000002
754 typedef struct tagMONITORINFO
755 {
756 DWORD cbSize;
757 RECT rcMonitor;
758 RECT rcWork;
759 DWORD dwFlags;
760 } MONITORINFO, *LPMONITORINFO;
761 typedef struct tagMONITORINFOEXW : public tagMONITORINFO
762 {
763 WCHAR szDevice[CCHDEVICENAME];
764 } MONITORINFOEXW, *LPMONITORINFOEXW;
765 typedef MONITORINFOEXW MONITORINFOEX;
766 typedef LPMONITORINFOEXW LPMONITORINFOEX;
767 #endif
768
769 HMONITOR DXUTMonitorFromWindow( HWND hWnd, DWORD dwFlags );
770 BOOL DXUTGetMonitorInfo( HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo );
771 void DXUTGetDesktopResolution( UINT AdapterOrdinal, UINT* pWidth, UINT* pHeight );
772
773
774 //--------------------------------------------------------------------------------------
775 // Implementation of CGrowableArray
776 //--------------------------------------------------------------------------------------
777
778 // This version doesn't call ctor or dtor.
779 template< typename TYPE >
SetSizeInternal(int nNewMaxSize)780 HRESULT CGrowableArray<TYPE>::SetSizeInternal( int nNewMaxSize )
781 {
782 if( nNewMaxSize < 0 )
783 {
784 assert( false );
785 return E_INVALIDARG;
786 }
787
788 if( nNewMaxSize == 0 )
789 {
790 // Shrink to 0 size & cleanup
791 if( m_pData )
792 {
793 free( m_pData );
794 m_pData = NULL;
795 }
796
797 m_nMaxSize = 0;
798 m_nSize = 0;
799 }
800 else if( m_pData == NULL || nNewMaxSize > m_nMaxSize )
801 {
802 // Grow array
803 int nGrowBy = ( m_nMaxSize == 0 ) ? 16 : m_nMaxSize;
804 nNewMaxSize = __max( nNewMaxSize, m_nMaxSize + nGrowBy );
805
806 TYPE* pDataNew = (TYPE*) realloc( m_pData, nNewMaxSize * sizeof(TYPE) );
807 if( pDataNew == NULL )
808 return E_OUTOFMEMORY;
809
810 m_pData = pDataNew;
811 m_nMaxSize = nNewMaxSize;
812 }
813
814 return S_OK;
815 }
816
817
818 //--------------------------------------------------------------------------------------
819 template< typename TYPE >
SetSize(int nNewMaxSize)820 HRESULT CGrowableArray<TYPE>::SetSize( int nNewMaxSize )
821 {
822 int nOldSize = m_nSize;
823
824 if( nOldSize > nNewMaxSize )
825 {
826 // Removing elements. Call dtor.
827
828 for( int i = nNewMaxSize; i < nOldSize; ++i )
829 m_pData[i].~TYPE();
830 }
831
832 // Adjust buffer. Note that there's no need to check for error
833 // since if it happens, nOldSize == nNewMaxSize will be true.)
834 HRESULT hr = SetSizeInternal( nNewMaxSize );
835
836 if( nOldSize < nNewMaxSize )
837 {
838 // Adding elements. Call ctor.
839
840 for( int i = nOldSize; i < nNewMaxSize; ++i )
841 ::new (&m_pData[i]) TYPE;
842 }
843
844 return hr;
845 }
846
847
848 //--------------------------------------------------------------------------------------
849 template< typename TYPE >
Add(const TYPE & value)850 HRESULT CGrowableArray<TYPE>::Add( const TYPE& value )
851 {
852 HRESULT hr;
853 if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) )
854 return hr;
855
856 // Construct the new element
857 ::new (&m_pData[m_nSize]) TYPE;
858
859 // Assign
860 m_pData[m_nSize] = value;
861 ++m_nSize;
862
863 return S_OK;
864 }
865
866
867 //--------------------------------------------------------------------------------------
868 template< typename TYPE >
Insert(int nIndex,const TYPE & value)869 HRESULT CGrowableArray<TYPE>::Insert( int nIndex, const TYPE& value )
870 {
871 HRESULT hr;
872
873 // Validate index
874 if( nIndex < 0 ||
875 nIndex > m_nSize )
876 {
877 assert( false );
878 return E_INVALIDARG;
879 }
880
881 // Prepare the buffer
882 if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) )
883 return hr;
884
885 // Shift the array
886 MoveMemory( &m_pData[nIndex+1], &m_pData[nIndex], sizeof(TYPE) * (m_nSize - nIndex) );
887
888 // Construct the new element
889 ::new (&m_pData[nIndex]) TYPE;
890
891 // Set the value and increase the size
892 m_pData[nIndex] = value;
893 ++m_nSize;
894
895 return S_OK;
896 }
897
898
899 //--------------------------------------------------------------------------------------
900 template< typename TYPE >
SetAt(int nIndex,const TYPE & value)901 HRESULT CGrowableArray<TYPE>::SetAt( int nIndex, const TYPE& value )
902 {
903 // Validate arguments
904 if( nIndex < 0 ||
905 nIndex >= m_nSize )
906 {
907 assert( false );
908 return E_INVALIDARG;
909 }
910
911 m_pData[nIndex] = value;
912 return S_OK;
913 }
914
915
916 //--------------------------------------------------------------------------------------
917 // Searches for the specified value and returns the index of the first occurrence
918 // within the section of the data array that extends from iStart and contains the
919 // specified number of elements. Returns -1 if value is not found within the given
920 // section.
921 //--------------------------------------------------------------------------------------
922 template< typename TYPE >
IndexOf(const TYPE & value,int iStart,int nNumElements)923 int CGrowableArray<TYPE>::IndexOf( const TYPE& value, int iStart, int nNumElements )
924 {
925 // Validate arguments
926 if( iStart < 0 ||
927 iStart >= m_nSize ||
928 nNumElements < 0 ||
929 iStart + nNumElements > m_nSize )
930 {
931 assert( false );
932 return -1;
933 }
934
935 // Search
936 for( int i = iStart; i < (iStart + nNumElements); i++ )
937 {
938 if( value == m_pData[i] )
939 return i;
940 }
941
942 // Not found
943 return -1;
944 }
945
946
947 //--------------------------------------------------------------------------------------
948 // Searches for the specified value and returns the index of the last occurrence
949 // within the section of the data array that contains the specified number of elements
950 // and ends at iEnd. Returns -1 if value is not found within the given section.
951 //--------------------------------------------------------------------------------------
952 template< typename TYPE >
LastIndexOf(const TYPE & value,int iEnd,int nNumElements)953 int CGrowableArray<TYPE>::LastIndexOf( const TYPE& value, int iEnd, int nNumElements )
954 {
955 // Validate arguments
956 if( iEnd < 0 ||
957 iEnd >= m_nSize ||
958 nNumElements < 0 ||
959 iEnd - nNumElements < 0 )
960 {
961 assert( false );
962 return -1;
963 }
964
965 // Search
966 for( int i = iEnd; i > (iEnd - nNumElements); i-- )
967 {
968 if( value == m_pData[i] )
969 return i;
970 }
971
972 // Not found
973 return -1;
974 }
975
976
977
978 //--------------------------------------------------------------------------------------
979 template< typename TYPE >
Remove(int nIndex)980 HRESULT CGrowableArray<TYPE>::Remove( int nIndex )
981 {
982 if( nIndex < 0 ||
983 nIndex >= m_nSize )
984 {
985 assert( false );
986 return E_INVALIDARG;
987 }
988
989 // Destruct the element to be removed
990 m_pData[nIndex].~TYPE();
991
992 // Compact the array and decrease the size
993 MoveMemory( &m_pData[nIndex], &m_pData[nIndex+1], sizeof(TYPE) * (m_nSize - (nIndex+1)) );
994 --m_nSize;
995
996 return S_OK;
997 }
998
999
1000 //--------------------------------------------------------------------------------------
1001 // Creates a REF or NULLREF device and returns that device. The caller should call
1002 // Release() when done with the device.
1003 //--------------------------------------------------------------------------------------
1004 IDirect3DDevice9* DXUTCreateRefDevice( HWND hWnd, bool bNullRef = true );
1005
1006
1007 #endif
1008