Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / DX11ClothDemo / DXUT / Optional / DXUTcamera.cpp
1 //--------------------------------------------------------------------------------------\r
2 // File: DXUTcamera.cpp\r
3 //\r
4 // Copyright (c) Microsoft Corporation. All rights reserved\r
5 //--------------------------------------------------------------------------------------\r
6 #include "DXUT.h"\r
7 #include "DXUTcamera.h"\r
8 #include "DXUTres.h"\r
9 #undef min // use __min instead\r
10 #undef max // use __max instead\r
11 \r
12 //--------------------------------------------------------------------------------------\r
13 CD3DArcBall::CD3DArcBall()\r
14 {\r
15     Reset();\r
16     m_vDownPt = D3DXVECTOR3( 0, 0, 0 );\r
17     m_vCurrentPt = D3DXVECTOR3( 0, 0, 0 );\r
18     m_Offset.x = m_Offset.y = 0;\r
19 \r
20     RECT rc;\r
21     GetClientRect( GetForegroundWindow(), &rc );\r
22     SetWindow( rc.right, rc.bottom );\r
23 }\r
24 \r
25 \r
26 \r
27 \r
28 \r
29 //--------------------------------------------------------------------------------------\r
30 void CD3DArcBall::Reset()\r
31 {\r
32     D3DXQuaternionIdentity( &m_qDown );\r
33     D3DXQuaternionIdentity( &m_qNow );\r
34     D3DXMatrixIdentity( &m_mRotation );\r
35     D3DXMatrixIdentity( &m_mTranslation );\r
36     D3DXMatrixIdentity( &m_mTranslationDelta );\r
37     m_bDrag = FALSE;\r
38     m_fRadiusTranslation = 1.0f;\r
39     m_fRadius = 1.0f;\r
40 }\r
41 \r
42 \r
43 \r
44 \r
45 //--------------------------------------------------------------------------------------\r
46 D3DXVECTOR3 CD3DArcBall::ScreenToVector( float fScreenPtX, float fScreenPtY )\r
47 {\r
48     // Scale to screen\r
49     FLOAT x = -( fScreenPtX - m_Offset.x - m_nWidth / 2 ) / ( m_fRadius * m_nWidth / 2 );\r
50     FLOAT y = ( fScreenPtY - m_Offset.y - m_nHeight / 2 ) / ( m_fRadius * m_nHeight / 2 );\r
51 \r
52     FLOAT z = 0.0f;\r
53     FLOAT mag = x * x + y * y;\r
54 \r
55     if( mag > 1.0f )\r
56     {\r
57         FLOAT scale = 1.0f / sqrtf( mag );\r
58         x *= scale;\r
59         y *= scale;\r
60     }\r
61     else\r
62         z = sqrtf( 1.0f - mag );\r
63 \r
64     // Return vector\r
65     return D3DXVECTOR3( x, y, z );\r
66 }\r
67 \r
68 \r
69 \r
70 \r
71 //--------------------------------------------------------------------------------------\r
72 D3DXQUATERNION CD3DArcBall::QuatFromBallPoints( const D3DXVECTOR3& vFrom, const D3DXVECTOR3& vTo )\r
73 {\r
74     D3DXVECTOR3 vPart;\r
75     float fDot = D3DXVec3Dot( &vFrom, &vTo );\r
76     D3DXVec3Cross( &vPart, &vFrom, &vTo );\r
77 \r
78     return D3DXQUATERNION( vPart.x, vPart.y, vPart.z, fDot );\r
79 }\r
80 \r
81 \r
82 \r
83 \r
84 //--------------------------------------------------------------------------------------\r
85 void CD3DArcBall::OnBegin( int nX, int nY )\r
86 {\r
87     // Only enter the drag state if the click falls\r
88     // inside the click rectangle.\r
89     if( nX >= m_Offset.x &&\r
90         nX < m_Offset.x + m_nWidth &&\r
91         nY >= m_Offset.y &&\r
92         nY < m_Offset.y + m_nHeight )\r
93     {\r
94         m_bDrag = true;\r
95         m_qDown = m_qNow;\r
96         m_vDownPt = ScreenToVector( ( float )nX, ( float )nY );\r
97     }\r
98 }\r
99 \r
100 \r
101 \r
102 \r
103 //--------------------------------------------------------------------------------------\r
104 void CD3DArcBall::OnMove( int nX, int nY )\r
105 {\r
106     if( m_bDrag )\r
107     {\r
108         m_vCurrentPt = ScreenToVector( ( float )nX, ( float )nY );\r
109         m_qNow = m_qDown * QuatFromBallPoints( m_vDownPt, m_vCurrentPt );\r
110     }\r
111 }\r
112 \r
113 \r
114 \r
115 \r
116 //--------------------------------------------------------------------------------------\r
117 void CD3DArcBall::OnEnd()\r
118 {\r
119     m_bDrag = false;\r
120 }\r
121 \r
122 \r
123 \r
124 \r
125 //--------------------------------------------------------------------------------------\r
126 // Desc:\r
127 //--------------------------------------------------------------------------------------\r
128 LRESULT CD3DArcBall::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )\r
129 {\r
130     // Current mouse position\r
131     int iMouseX = ( short )LOWORD( lParam );\r
132     int iMouseY = ( short )HIWORD( lParam );\r
133 \r
134     switch( uMsg )\r
135     {\r
136         case WM_LBUTTONDOWN:\r
137         case WM_LBUTTONDBLCLK:\r
138             SetCapture( hWnd );\r
139             OnBegin( iMouseX, iMouseY );\r
140             return TRUE;\r
141 \r
142         case WM_LBUTTONUP:\r
143             ReleaseCapture();\r
144             OnEnd();\r
145             return TRUE;\r
146         case WM_CAPTURECHANGED:\r
147             if( ( HWND )lParam != hWnd )\r
148             {\r
149                 ReleaseCapture();\r
150                 OnEnd();\r
151             }\r
152             return TRUE;\r
153 \r
154         case WM_RBUTTONDOWN:\r
155         case WM_RBUTTONDBLCLK:\r
156         case WM_MBUTTONDOWN:\r
157         case WM_MBUTTONDBLCLK:\r
158             SetCapture( hWnd );\r
159             // Store off the position of the cursor when the button is pressed\r
160             m_ptLastMouse.x = iMouseX;\r
161             m_ptLastMouse.y = iMouseY;\r
162             return TRUE;\r
163 \r
164         case WM_RBUTTONUP:\r
165         case WM_MBUTTONUP:\r
166             ReleaseCapture();\r
167             return TRUE;\r
168 \r
169         case WM_MOUSEMOVE:\r
170             if( MK_LBUTTON & wParam )\r
171             {\r
172                 OnMove( iMouseX, iMouseY );\r
173             }\r
174             else if( ( MK_RBUTTON & wParam ) || ( MK_MBUTTON & wParam ) )\r
175             {\r
176                 // Normalize based on size of window and bounding sphere radius\r
177                 FLOAT fDeltaX = ( m_ptLastMouse.x - iMouseX ) * m_fRadiusTranslation / m_nWidth;\r
178                 FLOAT fDeltaY = ( m_ptLastMouse.y - iMouseY ) * m_fRadiusTranslation / m_nHeight;\r
179 \r
180                 if( wParam & MK_RBUTTON )\r
181                 {\r
182                     D3DXMatrixTranslation( &m_mTranslationDelta, -2 * fDeltaX, 2 * fDeltaY, 0.0f );\r
183                     D3DXMatrixMultiply( &m_mTranslation, &m_mTranslation, &m_mTranslationDelta );\r
184                 }\r
185                 else  // wParam & MK_MBUTTON\r
186                 {\r
187                     D3DXMatrixTranslation( &m_mTranslationDelta, 0.0f, 0.0f, 5 * fDeltaY );\r
188                     D3DXMatrixMultiply( &m_mTranslation, &m_mTranslation, &m_mTranslationDelta );\r
189                 }\r
190 \r
191                 // Store mouse coordinate\r
192                 m_ptLastMouse.x = iMouseX;\r
193                 m_ptLastMouse.y = iMouseY;\r
194             }\r
195             return TRUE;\r
196     }\r
197 \r
198     return FALSE;\r
199 }\r
200 \r
201 \r
202 \r
203 \r
204 //--------------------------------------------------------------------------------------\r
205 // Constructor\r
206 //--------------------------------------------------------------------------------------\r
207 CBaseCamera::CBaseCamera()\r
208 {\r
209     m_cKeysDown = 0;\r
210     ZeroMemory( m_aKeys, sizeof( BYTE ) * CAM_MAX_KEYS );\r
211     ZeroMemory( m_GamePad, sizeof( DXUT_GAMEPAD ) * DXUT_MAX_CONTROLLERS );\r
212 \r
213     // Set attributes for the view matrix\r
214     D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );\r
215     D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );\r
216 \r
217     // Setup the view matrix\r
218     SetViewParams( &vEyePt, &vLookatPt );\r
219 \r
220     // Setup the projection matrix\r
221     SetProjParams( D3DX_PI / 4, 1.0f, 1.0f, 1000.0f );\r
222 \r
223     GetCursorPos( &m_ptLastMousePosition );\r
224     m_bMouseLButtonDown = false;\r
225     m_bMouseMButtonDown = false;\r
226     m_bMouseRButtonDown = false;\r
227     m_nCurrentButtonMask = 0;\r
228     m_nMouseWheelDelta = 0;\r
229 \r
230     m_fCameraYawAngle = 0.0f;\r
231     m_fCameraPitchAngle = 0.0f;\r
232 \r
233     SetRect( &m_rcDrag, LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX );\r
234     m_vVelocity = D3DXVECTOR3( 0, 0, 0 );\r
235     m_bMovementDrag = false;\r
236     m_vVelocityDrag = D3DXVECTOR3( 0, 0, 0 );\r
237     m_fDragTimer = 0.0f;\r
238     m_fTotalDragTimeToZero = 0.25;\r
239     m_vRotVelocity = D3DXVECTOR2( 0, 0 );\r
240 \r
241     m_fRotationScaler = 0.01f;\r
242     m_fMoveScaler = 5.0f;\r
243 \r
244     m_bInvertPitch = false;\r
245     m_bEnableYAxisMovement = true;\r
246     m_bEnablePositionMovement = true;\r
247 \r
248     m_vMouseDelta = D3DXVECTOR2( 0, 0 );\r
249     m_fFramesToSmoothMouseData = 2.0f;\r
250 \r
251     m_bClipToBoundary = false;\r
252     m_vMinBoundary = D3DXVECTOR3( -1, -1, -1 );\r
253     m_vMaxBoundary = D3DXVECTOR3( 1, 1, 1 );\r
254 \r
255     m_bResetCursorAfterMove = false;\r
256 }\r
257 \r
258 \r
259 //--------------------------------------------------------------------------------------\r
260 // Client can call this to change the position and direction of camera\r
261 //--------------------------------------------------------------------------------------\r
262 VOID CBaseCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt )\r
263 {\r
264     if( NULL == pvEyePt || NULL == pvLookatPt )\r
265         return;\r
266 \r
267     m_vDefaultEye = m_vEye = *pvEyePt;\r
268     m_vDefaultLookAt = m_vLookAt = *pvLookatPt;\r
269 \r
270     // Calc the view matrix\r
271     D3DXVECTOR3 vUp( 0,1,0 );\r
272     D3DXMatrixLookAtLH( &m_mView, pvEyePt, pvLookatPt, &vUp );\r
273 \r
274     D3DXMATRIX mInvView;\r
275     D3DXMatrixInverse( &mInvView, NULL, &m_mView );\r
276 \r
277     // The axis basis vectors and camera position are stored inside the \r
278     // position matrix in the 4 rows of the camera's world matrix.\r
279     // To figure out the yaw/pitch of the camera, we just need the Z basis vector\r
280     D3DXVECTOR3* pZBasis = ( D3DXVECTOR3* )&mInvView._31;\r
281 \r
282     m_fCameraYawAngle = atan2f( pZBasis->x, pZBasis->z );\r
283     float fLen = sqrtf( pZBasis->z * pZBasis->z + pZBasis->x * pZBasis->x );\r
284     m_fCameraPitchAngle = -atan2f( pZBasis->y, fLen );\r
285 }\r
286 \r
287 \r
288 \r
289 \r
290 //--------------------------------------------------------------------------------------\r
291 // Calculates the projection matrix based on input params\r
292 //--------------------------------------------------------------------------------------\r
293 VOID CBaseCamera::SetProjParams( FLOAT fFOV, FLOAT fAspect, FLOAT fNearPlane,\r
294                                  FLOAT fFarPlane )\r
295 {\r
296     // Set attributes for the projection matrix\r
297     m_fFOV = fFOV;\r
298     m_fAspect = fAspect;\r
299     m_fNearPlane = fNearPlane;\r
300     m_fFarPlane = fFarPlane;\r
301 \r
302     D3DXMatrixPerspectiveFovLH( &m_mProj, fFOV, fAspect, fNearPlane, fFarPlane );\r
303 }\r
304 \r
305 \r
306 \r
307 \r
308 //--------------------------------------------------------------------------------------\r
309 // Call this from your message proc so this class can handle window messages\r
310 //--------------------------------------------------------------------------------------\r
311 LRESULT CBaseCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )\r
312 {\r
313     UNREFERENCED_PARAMETER( hWnd );\r
314     UNREFERENCED_PARAMETER( lParam );\r
315 \r
316     switch( uMsg )\r
317     {\r
318         case WM_KEYDOWN:\r
319         {\r
320             // Map this key to a D3DUtil_CameraKeys enum and update the\r
321             // state of m_aKeys[] by adding the KEY_WAS_DOWN_MASK|KEY_IS_DOWN_MASK mask\r
322             // only if the key is not down\r
323             D3DUtil_CameraKeys mappedKey = MapKey( ( UINT )wParam );\r
324             if( mappedKey != CAM_UNKNOWN )\r
325             {\r
326                 if( FALSE == IsKeyDown( m_aKeys[mappedKey] ) )\r
327                 {\r
328                     m_aKeys[ mappedKey ] = KEY_WAS_DOWN_MASK | KEY_IS_DOWN_MASK;\r
329                     ++m_cKeysDown;\r
330                 }\r
331             }\r
332             break;\r
333         }\r
334 \r
335         case WM_KEYUP:\r
336         {\r
337             // Map this key to a D3DUtil_CameraKeys enum and update the\r
338             // state of m_aKeys[] by removing the KEY_IS_DOWN_MASK mask.\r
339             D3DUtil_CameraKeys mappedKey = MapKey( ( UINT )wParam );\r
340             if( mappedKey != CAM_UNKNOWN && ( DWORD )mappedKey < 8 )\r
341             {\r
342                 m_aKeys[ mappedKey ] &= ~KEY_IS_DOWN_MASK;\r
343                 --m_cKeysDown;\r
344             }\r
345             break;\r
346         }\r
347 \r
348         case WM_RBUTTONDOWN:\r
349         case WM_MBUTTONDOWN:\r
350         case WM_LBUTTONDOWN:\r
351         case WM_RBUTTONDBLCLK:\r
352         case WM_MBUTTONDBLCLK:\r
353         case WM_LBUTTONDBLCLK:\r
354             {\r
355                 // Compute the drag rectangle in screen coord.\r
356                 POINT ptCursor =\r
357                 {\r
358                     ( short )LOWORD( lParam ), ( short )HIWORD( lParam )\r
359                 };\r
360 \r
361                 // Update member var state\r
362                 if( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )\r
363                 {\r
364                     m_bMouseLButtonDown = true; m_nCurrentButtonMask |= MOUSE_LEFT_BUTTON;\r
365                 }\r
366                 if( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )\r
367                 {\r
368                     m_bMouseMButtonDown = true; m_nCurrentButtonMask |= MOUSE_MIDDLE_BUTTON;\r
369                 }\r
370                 if( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && PtInRect( &m_rcDrag, ptCursor ) )\r
371                 {\r
372                     m_bMouseRButtonDown = true; m_nCurrentButtonMask |= MOUSE_RIGHT_BUTTON;\r
373                 }\r
374 \r
375                 // Capture the mouse, so if the mouse button is \r
376                 // released outside the window, we'll get the WM_LBUTTONUP message\r
377                 SetCapture( hWnd );\r
378                 GetCursorPos( &m_ptLastMousePosition );\r
379                 return TRUE;\r
380             }\r
381 \r
382         case WM_RBUTTONUP:\r
383         case WM_MBUTTONUP:\r
384         case WM_LBUTTONUP:\r
385             {\r
386                 // Update member var state\r
387                 if( uMsg == WM_LBUTTONUP )\r
388                 {\r
389                     m_bMouseLButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON;\r
390                 }\r
391                 if( uMsg == WM_MBUTTONUP )\r
392                 {\r
393                     m_bMouseMButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON;\r
394                 }\r
395                 if( uMsg == WM_RBUTTONUP )\r
396                 {\r
397                     m_bMouseRButtonDown = false; m_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON;\r
398                 }\r
399 \r
400                 // Release the capture if no mouse buttons down\r
401                 if( !m_bMouseLButtonDown &&\r
402                     !m_bMouseRButtonDown &&\r
403                     !m_bMouseMButtonDown )\r
404                 {\r
405                     ReleaseCapture();\r
406                 }\r
407                 break;\r
408             }\r
409 \r
410         case WM_CAPTURECHANGED:\r
411         {\r
412             if( ( HWND )lParam != hWnd )\r
413             {\r
414                 if( ( m_nCurrentButtonMask & MOUSE_LEFT_BUTTON ) ||\r
415                     ( m_nCurrentButtonMask & MOUSE_MIDDLE_BUTTON ) ||\r
416                     ( m_nCurrentButtonMask & MOUSE_RIGHT_BUTTON ) )\r
417                 {\r
418                     m_bMouseLButtonDown = false;\r
419                     m_bMouseMButtonDown = false;\r
420                     m_bMouseRButtonDown = false;\r
421                     m_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON;\r
422                     m_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON;\r
423                     m_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON;\r
424                     ReleaseCapture();\r
425                 }\r
426             }\r
427             break;\r
428         }\r
429 \r
430         case WM_MOUSEWHEEL:\r
431             // Update member var state\r
432             m_nMouseWheelDelta += ( short )HIWORD( wParam );\r
433             break;\r
434     }\r
435 \r
436     return FALSE;\r
437 }\r
438 \r
439 //--------------------------------------------------------------------------------------\r
440 // Figure out the velocity based on keyboard input & drag if any\r
441 //--------------------------------------------------------------------------------------\r
442 void CBaseCamera::GetInput( bool bGetKeyboardInput, bool bGetMouseInput, bool bGetGamepadInput,\r
443                             bool bResetCursorAfterMove )\r
444 {\r
445     m_vKeyboardDirection = D3DXVECTOR3( 0, 0, 0 );\r
446     if( bGetKeyboardInput )\r
447     {\r
448         // Update acceleration vector based on keyboard state\r
449         if( IsKeyDown( m_aKeys[CAM_MOVE_FORWARD] ) )\r
450             m_vKeyboardDirection.z += 1.0f;\r
451         if( IsKeyDown( m_aKeys[CAM_MOVE_BACKWARD] ) )\r
452             m_vKeyboardDirection.z -= 1.0f;\r
453         if( m_bEnableYAxisMovement )\r
454         {\r
455             if( IsKeyDown( m_aKeys[CAM_MOVE_UP] ) )\r
456                 m_vKeyboardDirection.y += 1.0f;\r
457             if( IsKeyDown( m_aKeys[CAM_MOVE_DOWN] ) )\r
458                 m_vKeyboardDirection.y -= 1.0f;\r
459         }\r
460         if( IsKeyDown( m_aKeys[CAM_STRAFE_RIGHT] ) )\r
461             m_vKeyboardDirection.x += 1.0f;\r
462         if( IsKeyDown( m_aKeys[CAM_STRAFE_LEFT] ) )\r
463             m_vKeyboardDirection.x -= 1.0f;\r
464     }\r
465 \r
466     if( bGetMouseInput )\r
467     {\r
468         UpdateMouseDelta();\r
469     }\r
470 \r
471     if( bGetGamepadInput )\r
472     {\r
473         m_vGamePadLeftThumb = D3DXVECTOR3( 0, 0, 0 );\r
474         m_vGamePadRightThumb = D3DXVECTOR3( 0, 0, 0 );\r
475 \r
476         // Get controller state\r
477         for( DWORD iUserIndex = 0; iUserIndex < DXUT_MAX_CONTROLLERS; iUserIndex++ )\r
478         {\r
479             DXUTGetGamepadState( iUserIndex, &m_GamePad[iUserIndex], true, true );\r
480 \r
481             // Mark time if the controller is in a non-zero state\r
482             if( m_GamePad[iUserIndex].wButtons ||\r
483                 m_GamePad[iUserIndex].sThumbLX || m_GamePad[iUserIndex].sThumbLX ||\r
484                 m_GamePad[iUserIndex].sThumbRX || m_GamePad[iUserIndex].sThumbRY ||\r
485                 m_GamePad[iUserIndex].bLeftTrigger || m_GamePad[iUserIndex].bRightTrigger )\r
486             {\r
487                 m_GamePadLastActive[iUserIndex] = DXUTGetTime();\r
488             }\r
489         }\r
490 \r
491         // Find out which controller was non-zero last\r
492         int iMostRecentlyActive = -1;\r
493         double fMostRecentlyActiveTime = 0.0f;\r
494         for( DWORD iUserIndex = 0; iUserIndex < DXUT_MAX_CONTROLLERS; iUserIndex++ )\r
495         {\r
496             if( m_GamePadLastActive[iUserIndex] > fMostRecentlyActiveTime )\r
497             {\r
498                 fMostRecentlyActiveTime = m_GamePadLastActive[iUserIndex];\r
499                 iMostRecentlyActive = iUserIndex;\r
500             }\r
501         }\r
502 \r
503         // Use the most recent non-zero controller if its connected\r
504         if( iMostRecentlyActive >= 0 && m_GamePad[iMostRecentlyActive].bConnected )\r
505         {\r
506             m_vGamePadLeftThumb.x = m_GamePad[iMostRecentlyActive].fThumbLX;\r
507             m_vGamePadLeftThumb.y = 0.0f;\r
508             m_vGamePadLeftThumb.z = m_GamePad[iMostRecentlyActive].fThumbLY;\r
509 \r
510             m_vGamePadRightThumb.x = m_GamePad[iMostRecentlyActive].fThumbRX;\r
511             m_vGamePadRightThumb.y = 0.0f;\r
512             m_vGamePadRightThumb.z = m_GamePad[iMostRecentlyActive].fThumbRY;\r
513         }\r
514     }\r
515 }\r
516 \r
517 \r
518 //--------------------------------------------------------------------------------------\r
519 // Figure out the mouse delta based on mouse movement\r
520 //--------------------------------------------------------------------------------------\r
521 void CBaseCamera::UpdateMouseDelta()\r
522 {\r
523     POINT ptCurMouseDelta;\r
524     POINT ptCurMousePos;\r
525 \r
526     // Get current position of mouse\r
527     GetCursorPos( &ptCurMousePos );\r
528 \r
529     // Calc how far it's moved since last frame\r
530     ptCurMouseDelta.x = ptCurMousePos.x - m_ptLastMousePosition.x;\r
531     ptCurMouseDelta.y = ptCurMousePos.y - m_ptLastMousePosition.y;\r
532 \r
533     // Record current position for next time\r
534     m_ptLastMousePosition = ptCurMousePos;\r
535 \r
536     if( m_bResetCursorAfterMove && DXUTIsActive() )\r
537     {\r
538         // Set position of camera to center of desktop, \r
539         // so it always has room to move.  This is very useful\r
540         // if the cursor is hidden.  If this isn't done and cursor is hidden, \r
541         // then invisible cursor will hit the edge of the screen \r
542         // and the user can't tell what happened\r
543         POINT ptCenter;\r
544 \r
545         // Get the center of the current monitor\r
546         MONITORINFO mi;\r
547         mi.cbSize = sizeof( MONITORINFO );\r
548         DXUTGetMonitorInfo( DXUTMonitorFromWindow( DXUTGetHWND(), MONITOR_DEFAULTTONEAREST ), &mi );\r
549         ptCenter.x = ( mi.rcMonitor.left + mi.rcMonitor.right ) / 2;\r
550         ptCenter.y = ( mi.rcMonitor.top + mi.rcMonitor.bottom ) / 2;\r
551         SetCursorPos( ptCenter.x, ptCenter.y );\r
552         m_ptLastMousePosition = ptCenter;\r
553     }\r
554 \r
555     // Smooth the relative mouse data over a few frames so it isn't \r
556     // jerky when moving slowly at low frame rates.\r
557     float fPercentOfNew = 1.0f / m_fFramesToSmoothMouseData;\r
558     float fPercentOfOld = 1.0f - fPercentOfNew;\r
559     m_vMouseDelta.x = m_vMouseDelta.x * fPercentOfOld + ptCurMouseDelta.x * fPercentOfNew;\r
560     m_vMouseDelta.y = m_vMouseDelta.y * fPercentOfOld + ptCurMouseDelta.y * fPercentOfNew;\r
561 \r
562     m_vRotVelocity = m_vMouseDelta * m_fRotationScaler;\r
563 }\r
564 \r
565 \r
566 \r
567 \r
568 //--------------------------------------------------------------------------------------\r
569 // Figure out the velocity based on keyboard input & drag if any\r
570 //--------------------------------------------------------------------------------------\r
571 void CBaseCamera::UpdateVelocity( float fElapsedTime )\r
572 {\r
573     D3DXMATRIX mRotDelta;\r
574     D3DXVECTOR2 vGamePadRightThumb = D3DXVECTOR2( m_vGamePadRightThumb.x, -m_vGamePadRightThumb.z );\r
575     m_vRotVelocity = m_vMouseDelta * m_fRotationScaler + vGamePadRightThumb * 0.02f;\r
576 \r
577     D3DXVECTOR3 vAccel = m_vKeyboardDirection + m_vGamePadLeftThumb;\r
578 \r
579     // Normalize vector so if moving 2 dirs (left & forward), \r
580     // the camera doesn't move faster than if moving in 1 dir\r
581     D3DXVec3Normalize( &vAccel, &vAccel );\r
582 \r
583     // Scale the acceleration vector\r
584     vAccel *= m_fMoveScaler;\r
585 \r
586     if( m_bMovementDrag )\r
587     {\r
588         // Is there any acceleration this frame?\r
589         if( D3DXVec3LengthSq( &vAccel ) > 0 )\r
590         {\r
591             // If so, then this means the user has pressed a movement key\\r
592             // so change the velocity immediately to acceleration \r
593             // upon keyboard input.  This isn't normal physics\r
594             // but it will give a quick response to keyboard input\r
595             m_vVelocity = vAccel;\r
596             m_fDragTimer = m_fTotalDragTimeToZero;\r
597             m_vVelocityDrag = vAccel / m_fDragTimer;\r
598         }\r
599         else\r
600         {\r
601             // If no key being pressed, then slowly decrease velocity to 0\r
602             if( m_fDragTimer > 0 )\r
603             {\r
604                 // Drag until timer is <= 0\r
605                 m_vVelocity -= m_vVelocityDrag * fElapsedTime;\r
606                 m_fDragTimer -= fElapsedTime;\r
607             }\r
608             else\r
609             {\r
610                 // Zero velocity\r
611                 m_vVelocity = D3DXVECTOR3( 0, 0, 0 );\r
612             }\r
613         }\r
614     }\r
615     else\r
616     {\r
617         // No drag, so immediately change the velocity\r
618         m_vVelocity = vAccel;\r
619     }\r
620 }\r
621 \r
622 \r
623 \r
624 \r
625 //--------------------------------------------------------------------------------------\r
626 // Clamps pV to lie inside m_vMinBoundary & m_vMaxBoundary\r
627 //--------------------------------------------------------------------------------------\r
628 void CBaseCamera::ConstrainToBoundary( D3DXVECTOR3* pV )\r
629 {\r
630     // Constrain vector to a bounding box \r
631     pV->x = __max( pV->x, m_vMinBoundary.x );\r
632     pV->y = __max( pV->y, m_vMinBoundary.y );\r
633     pV->z = __max( pV->z, m_vMinBoundary.z );\r
634 \r
635     pV->x = __min( pV->x, m_vMaxBoundary.x );\r
636     pV->y = __min( pV->y, m_vMaxBoundary.y );\r
637     pV->z = __min( pV->z, m_vMaxBoundary.z );\r
638 }\r
639 \r
640 \r
641 \r
642 \r
643 //--------------------------------------------------------------------------------------\r
644 // Maps a windows virtual key to an enum\r
645 //--------------------------------------------------------------------------------------\r
646 D3DUtil_CameraKeys CBaseCamera::MapKey( UINT nKey )\r
647 {\r
648     // This could be upgraded to a method that's user-definable but for \r
649     // simplicity, we'll use a hardcoded mapping.\r
650     switch( nKey )\r
651     {\r
652         case VK_CONTROL:\r
653             return CAM_CONTROLDOWN;\r
654         case VK_LEFT:\r
655             return CAM_STRAFE_LEFT;\r
656         case VK_RIGHT:\r
657             return CAM_STRAFE_RIGHT;\r
658         case VK_UP:\r
659             return CAM_MOVE_FORWARD;\r
660         case VK_DOWN:\r
661             return CAM_MOVE_BACKWARD;\r
662         case VK_PRIOR:\r
663             return CAM_MOVE_UP;        // pgup\r
664         case VK_NEXT:\r
665             return CAM_MOVE_DOWN;      // pgdn\r
666 \r
667         case 'A':\r
668             return CAM_STRAFE_LEFT;\r
669         case 'D':\r
670             return CAM_STRAFE_RIGHT;\r
671         case 'W':\r
672             return CAM_MOVE_FORWARD;\r
673         case 'S':\r
674             return CAM_MOVE_BACKWARD;\r
675         case 'Q':\r
676             return CAM_MOVE_DOWN;\r
677         case 'E':\r
678             return CAM_MOVE_UP;\r
679 \r
680         case VK_NUMPAD4:\r
681             return CAM_STRAFE_LEFT;\r
682         case VK_NUMPAD6:\r
683             return CAM_STRAFE_RIGHT;\r
684         case VK_NUMPAD8:\r
685             return CAM_MOVE_FORWARD;\r
686         case VK_NUMPAD2:\r
687             return CAM_MOVE_BACKWARD;\r
688         case VK_NUMPAD9:\r
689             return CAM_MOVE_UP;\r
690         case VK_NUMPAD3:\r
691             return CAM_MOVE_DOWN;\r
692 \r
693         case VK_HOME:\r
694             return CAM_RESET;\r
695     }\r
696 \r
697     return CAM_UNKNOWN;\r
698 }\r
699 \r
700 \r
701 \r
702 \r
703 //--------------------------------------------------------------------------------------\r
704 // Reset the camera's position back to the default\r
705 //--------------------------------------------------------------------------------------\r
706 VOID CBaseCamera::Reset()\r
707 {\r
708     SetViewParams( &m_vDefaultEye, &m_vDefaultLookAt );\r
709 }\r
710 \r
711 \r
712 \r
713 \r
714 //--------------------------------------------------------------------------------------\r
715 // Constructor\r
716 //--------------------------------------------------------------------------------------\r
717 CFirstPersonCamera::CFirstPersonCamera() : m_nActiveButtonMask( 0x07 )\r
718 {\r
719     m_bRotateWithoutButtonDown = false;\r
720 }\r
721 \r
722 \r
723 \r
724 \r
725 //--------------------------------------------------------------------------------------\r
726 // Update the view matrix based on user input & elapsed time\r
727 //--------------------------------------------------------------------------------------\r
728 VOID CFirstPersonCamera::FrameMove( FLOAT fElapsedTime )\r
729 {\r
730     if( DXUTGetGlobalTimer()->IsStopped() ) {\r
731         if (DXUTGetFPS() == 0.0f) fElapsedTime = 0;\r
732         else fElapsedTime = 1.0f / DXUTGetFPS();\r
733     }\r
734 \r
735     if( IsKeyDown( m_aKeys[CAM_RESET] ) )\r
736         Reset();\r
737 \r
738     // Get keyboard/mouse/gamepad input\r
739     GetInput( m_bEnablePositionMovement, ( m_nActiveButtonMask & m_nCurrentButtonMask ) || m_bRotateWithoutButtonDown,\r
740               true, m_bResetCursorAfterMove );\r
741 \r
742     //// Get the mouse movement (if any) if the mouse button are down\r
743     //if( (m_nActiveButtonMask & m_nCurrentButtonMask) || m_bRotateWithoutButtonDown )\r
744     //    UpdateMouseDelta( fElapsedTime );\r
745 \r
746     // Get amount of velocity based on the keyboard input and drag (if any)\r
747     UpdateVelocity( fElapsedTime );\r
748 \r
749     // Simple euler method to calculate position delta\r
750     D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime;\r
751 \r
752     // If rotating the camera \r
753     if( ( m_nActiveButtonMask & m_nCurrentButtonMask ) ||\r
754         m_bRotateWithoutButtonDown ||\r
755         m_vGamePadRightThumb.x != 0 ||\r
756         m_vGamePadRightThumb.z != 0 )\r
757     {\r
758         // Update the pitch & yaw angle based on mouse movement\r
759         float fYawDelta = m_vRotVelocity.x;\r
760         float fPitchDelta = m_vRotVelocity.y;\r
761 \r
762         // Invert pitch if requested\r
763         if( m_bInvertPitch )\r
764             fPitchDelta = -fPitchDelta;\r
765 \r
766         m_fCameraPitchAngle += fPitchDelta;\r
767         m_fCameraYawAngle += fYawDelta;\r
768 \r
769         // Limit pitch to straight up or straight down\r
770         m_fCameraPitchAngle = __max( -D3DX_PI / 2.0f, m_fCameraPitchAngle );\r
771         m_fCameraPitchAngle = __min( +D3DX_PI / 2.0f, m_fCameraPitchAngle );\r
772     }\r
773 \r
774     // Make a rotation matrix based on the camera's yaw & pitch\r
775     D3DXMATRIX mCameraRot;\r
776     D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, m_fCameraPitchAngle, 0 );\r
777 \r
778     // Transform vectors based on camera's rotation matrix\r
779     D3DXVECTOR3 vWorldUp, vWorldAhead;\r
780     D3DXVECTOR3 vLocalUp = D3DXVECTOR3( 0, 1, 0 );\r
781     D3DXVECTOR3 vLocalAhead = D3DXVECTOR3( 0, 0, 1 );\r
782     D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );\r
783     D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );\r
784 \r
785     // Transform the position delta by the camera's rotation \r
786     D3DXVECTOR3 vPosDeltaWorld;\r
787     if( !m_bEnableYAxisMovement )\r
788     {\r
789         // If restricting Y movement, do not include pitch\r
790         // when transforming position delta vector.\r
791         D3DXMatrixRotationYawPitchRoll( &mCameraRot, m_fCameraYawAngle, 0.0f, 0.0f );\r
792     }\r
793     D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );\r
794 \r
795     // Move the eye position \r
796     m_vEye += vPosDeltaWorld;\r
797     if( m_bClipToBoundary )\r
798         ConstrainToBoundary( &m_vEye );\r
799 \r
800     // Update the lookAt position based on the eye position \r
801     m_vLookAt = m_vEye + vWorldAhead;\r
802 \r
803     // Update the view matrix\r
804     D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp );\r
805 \r
806     D3DXMatrixInverse( &m_mCameraWorld, NULL, &m_mView );\r
807 }\r
808 \r
809 \r
810 //--------------------------------------------------------------------------------------\r
811 // Enable or disable each of the mouse buttons for rotation drag.\r
812 //--------------------------------------------------------------------------------------\r
813 void CFirstPersonCamera::SetRotateButtons( bool bLeft, bool bMiddle, bool bRight, bool bRotateWithoutButtonDown )\r
814 {\r
815     m_nActiveButtonMask = ( bLeft ? MOUSE_LEFT_BUTTON : 0 ) |\r
816         ( bMiddle ? MOUSE_MIDDLE_BUTTON : 0 ) |\r
817         ( bRight ? MOUSE_RIGHT_BUTTON : 0 );\r
818     m_bRotateWithoutButtonDown = bRotateWithoutButtonDown;\r
819 }\r
820 \r
821 \r
822 //--------------------------------------------------------------------------------------\r
823 // Constructor \r
824 //--------------------------------------------------------------------------------------\r
825 CModelViewerCamera::CModelViewerCamera()\r
826 {\r
827     D3DXMatrixIdentity( &m_mWorld );\r
828     D3DXMatrixIdentity( &m_mModelRot );\r
829     D3DXMatrixIdentity( &m_mModelLastRot );\r
830     D3DXMatrixIdentity( &m_mCameraRotLast );\r
831     m_vModelCenter = D3DXVECTOR3( 0, 0, 0 );\r
832     m_fRadius = 5.0f;\r
833     m_fDefaultRadius = 5.0f;\r
834     m_fMinRadius = 1.0f;\r
835     m_fMaxRadius = FLT_MAX;\r
836     m_bLimitPitch = false;\r
837     m_bEnablePositionMovement = false;\r
838     m_bAttachCameraToModel = false;\r
839 \r
840     m_nRotateModelButtonMask = MOUSE_LEFT_BUTTON;\r
841     m_nZoomButtonMask = MOUSE_WHEEL;\r
842     m_nRotateCameraButtonMask = MOUSE_RIGHT_BUTTON;\r
843     m_bDragSinceLastUpdate = true;\r
844 }\r
845 \r
846 \r
847 \r
848 \r
849 //--------------------------------------------------------------------------------------\r
850 // Update the view matrix & the model's world matrix based \r
851 //       on user input & elapsed time\r
852 //--------------------------------------------------------------------------------------\r
853 VOID CModelViewerCamera::FrameMove( FLOAT fElapsedTime )\r
854 {\r
855     if( IsKeyDown( m_aKeys[CAM_RESET] ) )\r
856         Reset();\r
857 \r
858     // If no dragged has happend since last time FrameMove is called,\r
859     // and no camera key is held down, then no need to handle again.\r
860     if( !m_bDragSinceLastUpdate && 0 == m_cKeysDown )\r
861         return;\r
862     m_bDragSinceLastUpdate = false;\r
863 \r
864     //// If no mouse button is held down, \r
865     //// Get the mouse movement (if any) if the mouse button are down\r
866     //if( m_nCurrentButtonMask != 0 ) \r
867     //    UpdateMouseDelta( fElapsedTime );\r
868 \r
869     GetInput( m_bEnablePositionMovement, m_nCurrentButtonMask != 0, true, false );\r
870 \r
871     // Get amount of velocity based on the keyboard input and drag (if any)\r
872     UpdateVelocity( fElapsedTime );\r
873 \r
874     // Simple euler method to calculate position delta\r
875     D3DXVECTOR3 vPosDelta = m_vVelocity * fElapsedTime;\r
876 \r
877     // Change the radius from the camera to the model based on wheel scrolling\r
878     if( m_nMouseWheelDelta && m_nZoomButtonMask == MOUSE_WHEEL )\r
879         m_fRadius -= m_nMouseWheelDelta * m_fRadius * 0.1f / 120.0f;\r
880     m_fRadius = __min( m_fMaxRadius, m_fRadius );\r
881     m_fRadius = __max( m_fMinRadius, m_fRadius );\r
882     m_nMouseWheelDelta = 0;\r
883 \r
884     // Get the inverse of the arcball's rotation matrix\r
885     D3DXMATRIX mCameraRot;\r
886     D3DXMatrixInverse( &mCameraRot, NULL, m_ViewArcBall.GetRotationMatrix() );\r
887 \r
888     // Transform vectors based on camera's rotation matrix\r
889     D3DXVECTOR3 vWorldUp, vWorldAhead;\r
890     D3DXVECTOR3 vLocalUp = D3DXVECTOR3( 0, 1, 0 );\r
891     D3DXVECTOR3 vLocalAhead = D3DXVECTOR3( 0, 0, 1 );\r
892     D3DXVec3TransformCoord( &vWorldUp, &vLocalUp, &mCameraRot );\r
893     D3DXVec3TransformCoord( &vWorldAhead, &vLocalAhead, &mCameraRot );\r
894 \r
895     // Transform the position delta by the camera's rotation \r
896     D3DXVECTOR3 vPosDeltaWorld;\r
897     D3DXVec3TransformCoord( &vPosDeltaWorld, &vPosDelta, &mCameraRot );\r
898 \r
899     // Move the lookAt position \r
900     m_vLookAt += vPosDeltaWorld;\r
901     if( m_bClipToBoundary )\r
902         ConstrainToBoundary( &m_vLookAt );\r
903 \r
904     // Update the eye point based on a radius away from the lookAt position\r
905     m_vEye = m_vLookAt - vWorldAhead * m_fRadius;\r
906 \r
907     // Update the view matrix\r
908     D3DXMatrixLookAtLH( &m_mView, &m_vEye, &m_vLookAt, &vWorldUp );\r
909 \r
910     D3DXMATRIX mInvView;\r
911     D3DXMatrixInverse( &mInvView, NULL, &m_mView );\r
912     mInvView._41 = mInvView._42 = mInvView._43 = 0;\r
913 \r
914     D3DXMATRIX mModelLastRotInv;\r
915     D3DXMatrixInverse( &mModelLastRotInv, NULL, &m_mModelLastRot );\r
916 \r
917     // Accumulate the delta of the arcball's rotation in view space.\r
918     // Note that per-frame delta rotations could be problematic over long periods of time.\r
919     D3DXMATRIX mModelRot;\r
920     mModelRot = *m_WorldArcBall.GetRotationMatrix();\r
921     m_mModelRot *= m_mView * mModelLastRotInv * mModelRot * mInvView;\r
922 \r
923     if( m_ViewArcBall.IsBeingDragged() && m_bAttachCameraToModel && !IsKeyDown( m_aKeys[CAM_CONTROLDOWN] ) )\r
924     {\r
925         // Attach camera to model by inverse of the model rotation\r
926         D3DXMATRIX mCameraLastRotInv;\r
927         D3DXMatrixInverse( &mCameraLastRotInv, NULL, &m_mCameraRotLast );\r
928         D3DXMATRIX mCameraRotDelta = mCameraLastRotInv * mCameraRot; // local to world matrix\r
929         m_mModelRot *= mCameraRotDelta;\r
930     }\r
931     m_mCameraRotLast = mCameraRot;\r
932 \r
933     m_mModelLastRot = mModelRot;\r
934 \r
935     // Since we're accumulating delta rotations, we need to orthonormalize \r
936     // the matrix to prevent eventual matrix skew\r
937     D3DXVECTOR3* pXBasis = ( D3DXVECTOR3* )&m_mModelRot._11;\r
938     D3DXVECTOR3* pYBasis = ( D3DXVECTOR3* )&m_mModelRot._21;\r
939     D3DXVECTOR3* pZBasis = ( D3DXVECTOR3* )&m_mModelRot._31;\r
940     D3DXVec3Normalize( pXBasis, pXBasis );\r
941     D3DXVec3Cross( pYBasis, pZBasis, pXBasis );\r
942     D3DXVec3Normalize( pYBasis, pYBasis );\r
943     D3DXVec3Cross( pZBasis, pXBasis, pYBasis );\r
944 \r
945     // Translate the rotation matrix to the same position as the lookAt position\r
946     m_mModelRot._41 = m_vLookAt.x;\r
947     m_mModelRot._42 = m_vLookAt.y;\r
948     m_mModelRot._43 = m_vLookAt.z;\r
949 \r
950     // Translate world matrix so its at the center of the model\r
951     D3DXMATRIX mTrans;\r
952     D3DXMatrixTranslation( &mTrans, -m_vModelCenter.x, -m_vModelCenter.y, -m_vModelCenter.z );\r
953     m_mWorld = mTrans * m_mModelRot;\r
954 }\r
955 \r
956 \r
957 void CModelViewerCamera::SetDragRect( RECT& rc )\r
958 {\r
959     CBaseCamera::SetDragRect( rc );\r
960 \r
961     m_WorldArcBall.SetOffset( rc.left, rc.top );\r
962     m_ViewArcBall.SetOffset( rc.left, rc.top );\r
963     SetWindow( rc.right - rc.left, rc.bottom - rc.top );\r
964 }\r
965 \r
966 \r
967 //--------------------------------------------------------------------------------------\r
968 // Reset the camera's position back to the default\r
969 //--------------------------------------------------------------------------------------\r
970 VOID CModelViewerCamera::Reset()\r
971 {\r
972     CBaseCamera::Reset();\r
973 \r
974     D3DXMatrixIdentity( &m_mWorld );\r
975     D3DXMatrixIdentity( &m_mModelRot );\r
976     D3DXMatrixIdentity( &m_mModelLastRot );\r
977     D3DXMatrixIdentity( &m_mCameraRotLast );\r
978 \r
979     m_fRadius = m_fDefaultRadius;\r
980     m_WorldArcBall.Reset();\r
981     m_ViewArcBall.Reset();\r
982 }\r
983 \r
984 \r
985 //--------------------------------------------------------------------------------------\r
986 // Override for setting the view parameters\r
987 //--------------------------------------------------------------------------------------\r
988 void CModelViewerCamera::SetViewParams( D3DXVECTOR3* pvEyePt, D3DXVECTOR3* pvLookatPt )\r
989 {\r
990     CBaseCamera::SetViewParams( pvEyePt, pvLookatPt );\r
991 \r
992     // Propogate changes to the member arcball\r
993     D3DXQUATERNION quat;\r
994     D3DXMATRIXA16 mRotation;\r
995     D3DXVECTOR3 vUp( 0,1,0 );\r
996     D3DXMatrixLookAtLH( &mRotation, pvEyePt, pvLookatPt, &vUp );\r
997     D3DXQuaternionRotationMatrix( &quat, &mRotation );\r
998     m_ViewArcBall.SetQuatNow( quat );\r
999 \r
1000     // Set the radius according to the distance\r
1001     D3DXVECTOR3 vEyeToPoint;\r
1002     D3DXVec3Subtract( &vEyeToPoint, pvLookatPt, pvEyePt );\r
1003     SetRadius( D3DXVec3Length( &vEyeToPoint ) );\r
1004 \r
1005     // View information changed. FrameMove should be called.\r
1006     m_bDragSinceLastUpdate = true;\r
1007 }\r
1008 \r
1009 \r
1010 \r
1011 //--------------------------------------------------------------------------------------\r
1012 // Call this from your message proc so this class can handle window messages\r
1013 //--------------------------------------------------------------------------------------\r
1014 LRESULT CModelViewerCamera::HandleMessages( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )\r
1015 {\r
1016     CBaseCamera::HandleMessages( hWnd, uMsg, wParam, lParam );\r
1017 \r
1018     if( ( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON ) ||\r
1019         ( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON ) ||\r
1020         ( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON ) )\r
1021     {\r
1022         int iMouseX = ( short )LOWORD( lParam );\r
1023         int iMouseY = ( short )HIWORD( lParam );\r
1024         m_WorldArcBall.OnBegin( iMouseX, iMouseY );\r
1025     }\r
1026 \r
1027     if( ( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON ) ||\r
1028         ( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) &&\r
1029           m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON ) ||\r
1030         ( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON ) )\r
1031     {\r
1032         int iMouseX = ( short )LOWORD( lParam );\r
1033         int iMouseY = ( short )HIWORD( lParam );\r
1034         m_ViewArcBall.OnBegin( iMouseX, iMouseY );\r
1035     }\r
1036 \r
1037     if( uMsg == WM_MOUSEMOVE )\r
1038     {\r
1039         int iMouseX = ( short )LOWORD( lParam );\r
1040         int iMouseY = ( short )HIWORD( lParam );\r
1041         m_WorldArcBall.OnMove( iMouseX, iMouseY );\r
1042         m_ViewArcBall.OnMove( iMouseX, iMouseY );\r
1043     }\r
1044 \r
1045     if( ( uMsg == WM_LBUTTONUP && m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON ) ||\r
1046         ( uMsg == WM_MBUTTONUP && m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON ) ||\r
1047         ( uMsg == WM_RBUTTONUP && m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON ) )\r
1048     {\r
1049         m_WorldArcBall.OnEnd();\r
1050     }\r
1051 \r
1052     if( ( uMsg == WM_LBUTTONUP && m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON ) ||\r
1053         ( uMsg == WM_MBUTTONUP && m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON ) ||\r
1054         ( uMsg == WM_RBUTTONUP && m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON ) )\r
1055     {\r
1056         m_ViewArcBall.OnEnd();\r
1057     }\r
1058 \r
1059     if( uMsg == WM_CAPTURECHANGED )\r
1060     {\r
1061         if( ( HWND )lParam != hWnd )\r
1062         {\r
1063             if( ( m_nRotateModelButtonMask & MOUSE_LEFT_BUTTON ) ||\r
1064                 ( m_nRotateModelButtonMask & MOUSE_MIDDLE_BUTTON ) ||\r
1065                 ( m_nRotateModelButtonMask & MOUSE_RIGHT_BUTTON ) )\r
1066             {\r
1067                 m_WorldArcBall.OnEnd();\r
1068             }\r
1069 \r
1070             if( ( m_nRotateCameraButtonMask & MOUSE_LEFT_BUTTON ) ||\r
1071                 ( m_nRotateCameraButtonMask & MOUSE_MIDDLE_BUTTON ) ||\r
1072                 ( m_nRotateCameraButtonMask & MOUSE_RIGHT_BUTTON ) )\r
1073             {\r
1074                 m_ViewArcBall.OnEnd();\r
1075             }\r
1076         }\r
1077     }\r
1078 \r
1079     if( uMsg == WM_LBUTTONDOWN ||\r
1080         uMsg == WM_LBUTTONDBLCLK ||\r
1081         uMsg == WM_MBUTTONDOWN ||\r
1082         uMsg == WM_MBUTTONDBLCLK ||\r
1083         uMsg == WM_RBUTTONDOWN ||\r
1084         uMsg == WM_RBUTTONDBLCLK ||\r
1085         uMsg == WM_LBUTTONUP ||\r
1086         uMsg == WM_MBUTTONUP ||\r
1087         uMsg == WM_RBUTTONUP ||\r
1088         uMsg == WM_MOUSEWHEEL ||\r
1089         uMsg == WM_MOUSEMOVE )\r
1090     {\r
1091         m_bDragSinceLastUpdate = true;\r
1092     }\r
1093 \r
1094     return FALSE;\r
1095 }\r
1096 \r
1097 \r
1098 \r
1099 //--------------------------------------------------------------------------------------\r
1100 // D3D9\r
1101 IDirect3DDevice9*           CDXUTDirectionWidget::s_pd3d9Device = NULL;\r
1102 ID3DXEffect*                CDXUTDirectionWidget::s_pD3D9Effect = NULL;\r
1103 ID3DXMesh*                  CDXUTDirectionWidget::s_pD3D9Mesh = NULL;\r
1104 D3DXHANDLE                  CDXUTDirectionWidget::s_hRenderWith1LightNoTexture = NULL;\r
1105 D3DXHANDLE                  CDXUTDirectionWidget::s_hMaterialDiffuseColor = NULL;\r
1106 D3DXHANDLE                  CDXUTDirectionWidget::s_hLightDir = NULL;\r
1107 D3DXHANDLE                  CDXUTDirectionWidget::s_hWorldViewProjection = NULL;\r
1108 D3DXHANDLE                  CDXUTDirectionWidget::s_hWorld = NULL;\r
1109 \r
1110 \r
1111 //--------------------------------------------------------------------------------------\r
1112 CDXUTDirectionWidget::CDXUTDirectionWidget()\r
1113 {\r
1114     m_fRadius = 1.0f;\r
1115     m_vDefaultDir = D3DXVECTOR3( 0, 1, 0 );\r
1116     m_vCurrentDir = m_vDefaultDir;\r
1117     m_nRotateMask = MOUSE_RIGHT_BUTTON;\r
1118 \r
1119     D3DXMatrixIdentity( &m_mView );\r
1120     D3DXMatrixIdentity( &m_mRot );\r
1121     D3DXMatrixIdentity( &m_mRotSnapshot );\r
1122 }\r
1123 \r
1124 \r
1125 //--------------------------------------------------------------------------------------\r
1126 HRESULT CDXUTDirectionWidget::StaticOnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice )\r
1127 {\r
1128     HRESULT hr;\r
1129 \r
1130     s_pd3d9Device = pd3dDevice;\r
1131 \r
1132     const char* g_strBuffer =\r
1133         "float4 g_MaterialDiffuseColor;      // Material's diffuse color\r\n"\r
1134         "float3 g_LightDir;                  // Light's direction in world space\r\n"\r
1135         "float4x4 g_mWorld;                  // World matrix for object\r\n"\r
1136         "float4x4 g_mWorldViewProjection;    // World * View * Projection matrix\r\n"\r
1137         "\r\n"\r
1138         "struct VS_OUTPUT\r\n"\r
1139         "{\r\n"\r
1140         "    float4 Position   : POSITION;   // vertex position\r\n"\r
1141         "    float4 Diffuse    : COLOR0;     // vertex diffuse color\r\n"\r
1142         "};\r\n"\r
1143         "\r\n"\r
1144         "VS_OUTPUT RenderWith1LightNoTextureVS( float4 vPos : POSITION,\r\n"\r
1145         "                                       float3 vNormal : NORMAL )\r\n"\r
1146         "{\r\n"\r
1147         "    VS_OUTPUT Output;\r\n"\r
1148         "\r\n"\r
1149         "    // Transform the position from object space to homogeneous projection space\r\n"\r
1150         "    Output.Position = mul(vPos, g_mWorldViewProjection);\r\n"\r
1151         "\r\n"\r
1152         "    // Transform the normal from object space to world space\r\n"\r
1153         "    float3 vNormalWorldSpace;\r\n"\r
1154         "    vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)\r\n"\r
1155         "\r\n"\r
1156         "    // Compute simple directional lighting equation\r\n"\r
1157         "    Output.Diffuse.rgb = g_MaterialDiffuseColor * max(0,dot(vNormalWorldSpace, g_LightDir));\r\n"\r
1158         "    Output.Diffuse.a = 1.0f;\r\n"\r
1159         "\r\n"\r
1160         "    return Output;\r\n"\r
1161         "}\r\n"\r
1162         "\r\n"\r
1163         "float4 RenderWith1LightNoTexturePS( float4 Diffuse : COLOR0 ) : COLOR0\r\n"\r
1164         "{\r\n"\r
1165         "    return Diffuse;\r\n"\r
1166         "}\r\n"\r
1167         "\r\n"\r
1168         "technique RenderWith1LightNoTexture\r\n"\r
1169         "{\r\n"\r
1170         "    pass P0\r\n"\r
1171         "    {\r\n"\r
1172         "        VertexShader = compile vs_2_0 RenderWith1LightNoTextureVS();\r\n"\r
1173         "        PixelShader  = compile ps_2_0 RenderWith1LightNoTexturePS();\r\n"\r
1174         "    }\r\n"\r
1175         "}\r\n"\r
1176         "";\r
1177 \r
1178     UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1;\r
1179 \r
1180     V_RETURN( D3DXCreateEffect( s_pd3d9Device, g_strBuffer, dwBufferSize, NULL, NULL, D3DXFX_NOT_CLONEABLE,\r
1181                                 NULL, &s_pD3D9Effect, NULL ) );\r
1182 \r
1183     // Save technique handles for use when rendering\r
1184     s_hRenderWith1LightNoTexture = s_pD3D9Effect->GetTechniqueByName( "RenderWith1LightNoTexture" );\r
1185     s_hMaterialDiffuseColor = s_pD3D9Effect->GetParameterByName( NULL, "g_MaterialDiffuseColor" );\r
1186     s_hLightDir = s_pD3D9Effect->GetParameterByName( NULL, "g_LightDir" );\r
1187     s_hWorld = s_pD3D9Effect->GetParameterByName( NULL, "g_mWorld" );\r
1188     s_hWorldViewProjection = s_pD3D9Effect->GetParameterByName( NULL, "g_mWorldViewProjection" );\r
1189 \r
1190     // Load the mesh with D3DX and get back a ID3DXMesh*.  For this\r
1191     // sample we'll ignore the X file's embedded materials since we know \r
1192     // exactly the model we're loading.  See the mesh samples such as\r
1193     // "OptimizedMesh" for a more generic mesh loading example.\r
1194     V_RETURN( DXUTCreateArrowMeshFromInternalArray( s_pd3d9Device, &s_pD3D9Mesh ) );\r
1195 \r
1196     // Optimize the mesh for this graphics card's vertex cache \r
1197     // so when rendering the mesh's triangle list the vertices will \r
1198     // cache hit more often so it won't have to re-execute the vertex shader \r
1199     // on those vertices so it will improve perf.\r
1200     DWORD* rgdwAdjacency = new DWORD[s_pD3D9Mesh->GetNumFaces() * 3];\r
1201     if( rgdwAdjacency == NULL )\r
1202         return E_OUTOFMEMORY;\r
1203     V( s_pD3D9Mesh->GenerateAdjacency( 1e-6f, rgdwAdjacency ) );\r
1204     V( s_pD3D9Mesh->OptimizeInplace( D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL ) );\r
1205     delete []rgdwAdjacency;\r
1206 \r
1207     return S_OK;\r
1208 }\r
1209 \r
1210 \r
1211 //--------------------------------------------------------------------------------------\r
1212 HRESULT CDXUTDirectionWidget::OnD3D9ResetDevice( const D3DSURFACE_DESC* pBackBufferSurfaceDesc )\r
1213 {\r
1214     m_ArcBall.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );\r
1215     return S_OK;\r
1216 }\r
1217 \r
1218 \r
1219 //--------------------------------------------------------------------------------------\r
1220 void CDXUTDirectionWidget::StaticOnD3D9LostDevice()\r
1221 {\r
1222     if( s_pD3D9Effect )\r
1223         s_pD3D9Effect->OnLostDevice();\r
1224 }\r
1225 \r
1226 \r
1227 //--------------------------------------------------------------------------------------\r
1228 void CDXUTDirectionWidget::StaticOnD3D9DestroyDevice()\r
1229 {\r
1230     SAFE_RELEASE( s_pD3D9Effect );\r
1231     SAFE_RELEASE( s_pD3D9Mesh );\r
1232 }\r
1233 \r
1234 \r
1235 //--------------------------------------------------------------------------------------\r
1236 LRESULT CDXUTDirectionWidget::HandleMessages( HWND hWnd, UINT uMsg,\r
1237                                               WPARAM wParam, LPARAM lParam )\r
1238 {\r
1239     switch( uMsg )\r
1240     {\r
1241         case WM_LBUTTONDOWN:\r
1242         case WM_MBUTTONDOWN:\r
1243         case WM_RBUTTONDOWN:\r
1244             {\r
1245                 if( ( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) != 0 && uMsg == WM_LBUTTONDOWN ) ||\r
1246                     ( ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) != 0 && uMsg == WM_MBUTTONDOWN ) ||\r
1247                     ( ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) != 0 && uMsg == WM_RBUTTONDOWN ) )\r
1248                 {\r
1249                     int iMouseX = ( int )( short )LOWORD( lParam );\r
1250                     int iMouseY = ( int )( short )HIWORD( lParam );\r
1251                     m_ArcBall.OnBegin( iMouseX, iMouseY );\r
1252                     SetCapture( hWnd );\r
1253                 }\r
1254                 return TRUE;\r
1255             }\r
1256 \r
1257         case WM_MOUSEMOVE:\r
1258         {\r
1259             if( m_ArcBall.IsBeingDragged() )\r
1260             {\r
1261                 int iMouseX = ( int )( short )LOWORD( lParam );\r
1262                 int iMouseY = ( int )( short )HIWORD( lParam );\r
1263                 m_ArcBall.OnMove( iMouseX, iMouseY );\r
1264                 UpdateLightDir();\r
1265             }\r
1266             return TRUE;\r
1267         }\r
1268 \r
1269         case WM_LBUTTONUP:\r
1270         case WM_MBUTTONUP:\r
1271         case WM_RBUTTONUP:\r
1272             {\r
1273                 if( ( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) != 0 && uMsg == WM_LBUTTONUP ) ||\r
1274                     ( ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) != 0 && uMsg == WM_MBUTTONUP ) ||\r
1275                     ( ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) != 0 && uMsg == WM_RBUTTONUP ) )\r
1276                 {\r
1277                     m_ArcBall.OnEnd();\r
1278                     ReleaseCapture();\r
1279                 }\r
1280 \r
1281                 UpdateLightDir();\r
1282                 return TRUE;\r
1283             }\r
1284 \r
1285         case WM_CAPTURECHANGED:\r
1286         {\r
1287             if( ( HWND )lParam != hWnd )\r
1288             {\r
1289                 if( ( m_nRotateMask & MOUSE_LEFT_BUTTON ) ||\r
1290                     ( m_nRotateMask & MOUSE_MIDDLE_BUTTON ) ||\r
1291                     ( m_nRotateMask & MOUSE_RIGHT_BUTTON ) )\r
1292                 {\r
1293                     m_ArcBall.OnEnd();\r
1294                     ReleaseCapture();\r
1295                 }\r
1296             }\r
1297             return TRUE;\r
1298         }\r
1299     }\r
1300 \r
1301     return 0;\r
1302 }\r
1303 \r
1304 \r
1305 //--------------------------------------------------------------------------------------\r
1306 HRESULT CDXUTDirectionWidget::OnRender9( D3DXCOLOR color, const D3DXMATRIX* pmView,\r
1307                                          const D3DXMATRIX* pmProj, const D3DXVECTOR3* pEyePt )\r
1308 {\r
1309     m_mView = *pmView;\r
1310 \r
1311     // Render the light spheres so the user can visually see the light dir\r
1312     UINT iPass, cPasses;\r
1313     D3DXMATRIX mRotate;\r
1314     D3DXMATRIX mScale;\r
1315     D3DXMATRIX mTrans;\r
1316     D3DXMATRIXA16 mWorldViewProj;\r
1317     HRESULT hr;\r
1318 \r
1319     V( s_pD3D9Effect->SetTechnique( s_hRenderWith1LightNoTexture ) );\r
1320     V( s_pD3D9Effect->SetVector( s_hMaterialDiffuseColor, ( D3DXVECTOR4* )&color ) );\r
1321 \r
1322     D3DXVECTOR3 vEyePt;\r
1323     D3DXVec3Normalize( &vEyePt, pEyePt );\r
1324     V( s_pD3D9Effect->SetValue( s_hLightDir, &vEyePt, sizeof( D3DXVECTOR3 ) ) );\r
1325 \r
1326     // Rotate arrow model to point towards origin\r
1327     D3DXMATRIX mRotateA, mRotateB;\r
1328     D3DXVECTOR3 vAt = D3DXVECTOR3( 0, 0, 0 );\r
1329     D3DXVECTOR3 vUp = D3DXVECTOR3( 0, 1, 0 );\r
1330     D3DXMatrixRotationX( &mRotateB, D3DX_PI );\r
1331     D3DXMatrixLookAtLH( &mRotateA, &m_vCurrentDir, &vAt, &vUp );\r
1332     D3DXMatrixInverse( &mRotateA, NULL, &mRotateA );\r
1333     mRotate = mRotateB * mRotateA;\r
1334 \r
1335     D3DXVECTOR3 vL = m_vCurrentDir * m_fRadius * 1.0f;\r
1336     D3DXMatrixTranslation( &mTrans, vL.x, vL.y, vL.z );\r
1337     D3DXMatrixScaling( &mScale, m_fRadius * 0.2f, m_fRadius * 0.2f, m_fRadius * 0.2f );\r
1338 \r
1339     D3DXMATRIX mWorld = mRotate * mScale * mTrans;\r
1340     mWorldViewProj = mWorld * ( m_mView )*( *pmProj );\r
1341 \r
1342     V( s_pD3D9Effect->SetMatrix( s_hWorldViewProjection, &mWorldViewProj ) );\r
1343     V( s_pD3D9Effect->SetMatrix( s_hWorld, &mWorld ) );\r
1344 \r
1345     for( int iSubset = 0; iSubset < 2; iSubset++ )\r
1346     {\r
1347         V( s_pD3D9Effect->Begin( &cPasses, 0 ) );\r
1348         for( iPass = 0; iPass < cPasses; iPass++ )\r
1349         {\r
1350             V( s_pD3D9Effect->BeginPass( iPass ) );\r
1351             V( s_pD3D9Mesh->DrawSubset( iSubset ) );\r
1352             V( s_pD3D9Effect->EndPass() );\r
1353         }\r
1354         V( s_pD3D9Effect->End() );\r
1355     }\r
1356 \r
1357     return S_OK;\r
1358 }\r
1359 \r
1360 //--------------------------------------------------------------------------------------\r
1361 HRESULT CDXUTDirectionWidget::UpdateLightDir()\r
1362 {\r
1363     D3DXMATRIX mInvView;\r
1364     D3DXMatrixInverse( &mInvView, NULL, &m_mView );\r
1365     mInvView._41 = mInvView._42 = mInvView._43 = 0;\r
1366 \r
1367     D3DXMATRIX mLastRotInv;\r
1368     D3DXMatrixInverse( &mLastRotInv, NULL, &m_mRotSnapshot );\r
1369 \r
1370     D3DXMATRIX mRot = *m_ArcBall.GetRotationMatrix();\r
1371     m_mRotSnapshot = mRot;\r
1372 \r
1373     // Accumulate the delta of the arcball's rotation in view space.\r
1374     // Note that per-frame delta rotations could be problematic over long periods of time.\r
1375     m_mRot *= m_mView * mLastRotInv * mRot * mInvView;\r
1376 \r
1377     // Since we're accumulating delta rotations, we need to orthonormalize \r
1378     // the matrix to prevent eventual matrix skew\r
1379     D3DXVECTOR3* pXBasis = ( D3DXVECTOR3* )&m_mRot._11;\r
1380     D3DXVECTOR3* pYBasis = ( D3DXVECTOR3* )&m_mRot._21;\r
1381     D3DXVECTOR3* pZBasis = ( D3DXVECTOR3* )&m_mRot._31;\r
1382     D3DXVec3Normalize( pXBasis, pXBasis );\r
1383     D3DXVec3Cross( pYBasis, pZBasis, pXBasis );\r
1384     D3DXVec3Normalize( pYBasis, pYBasis );\r
1385     D3DXVec3Cross( pZBasis, pXBasis, pYBasis );\r
1386 \r
1387     // Transform the default direction vector by the light's rotation matrix\r
1388     D3DXVec3TransformNormal( &m_vCurrentDir, &m_vDefaultDir, &m_mRot );\r
1389 \r
1390     return S_OK;\r
1391 }\r
1392 \r
1393 //--------------------------------------------------------------------------------------\r
1394 HRESULT CDXUTDirectionWidget::StaticOnD3D11CreateDevice( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext )\r
1395 {\r
1396     \r
1397 \r
1398     //s_pd3d10Device = pd3dDevice;\r
1399 \r
1400     //const char* g_strBuffer =\r
1401     //    "float4 g_MaterialDiffuseColor;      // Material's diffuse color\r\n"\r
1402     //    "float4 g_LightDir;                  // Light's direction in world space\r\n"\r
1403     //    "float4x4 g_mWorld;                  // World matrix for object\r\n"\r
1404     //    "float4x4 g_mWorldViewProjection;    // World * View * Projection matrix\r\n"\r
1405     //    "\r\n"\r
1406     //    "struct VS_OUTPUT\r\n"\r
1407     //    "{\r\n"\r
1408     //    "    float4 Position   : SV_POSITION;   // vertex position\r\n"\r
1409     //    "    float4 Diffuse    : COLOR0;     // vertex diffuse color\r\n"\r
1410     //    "};\r\n"\r
1411     //    "\r\n"\r
1412     //    "VS_OUTPUT RenderWith1LightNoTextureVS( float3 vPos : POSITION,\r\n"\r
1413     //    "                                       float3 vNormal : NORMAL )\r\n"\r
1414     //    "{\r\n"\r
1415     //    "    VS_OUTPUT Output;\r\n"\r
1416     //    "\r\n"\r
1417     //    "    // Transform the position from object space to homogeneous projection space\r\n"\r
1418     //    "    Output.Position = mul( float4(vPos,1), g_mWorldViewProjection);\r\n"\r
1419     //    "\r\n"\r
1420     //    "    // Transform the normal from object space to world space\r\n"\r
1421     //    "    float3 vNormalWorldSpace;\r\n"\r
1422     //    "    vNormalWorldSpace = normalize(mul(vNormal, (float3x3)g_mWorld)); // normal (world space)\r\n"\r
1423     //    "\r\n"\r
1424     //    "    // Compute simple directional lighting equation\r\n"\r
1425     //    "    Output.Diffuse.rgb = g_MaterialDiffuseColor * max(0,dot(vNormalWorldSpace, g_LightDir));\r\n"\r
1426     //    "    Output.Diffuse.a = 1.0f;\r\n"\r
1427     //    "\r\n"\r
1428     //    "    return Output;\r\n"\r
1429     //    "}\r\n"\r
1430     //    "\r\n"\r
1431     //    "float4 RenderWith1LightNoTexturePS( VS_OUTPUT Input ) : SV_TARGET\r\n"\r
1432     //    "{\r\n"\r
1433     //    "    return Input.Diffuse;\r\n"\r
1434     //    "}\r\n"\r
1435     //    "\r\n"\r
1436     //    "technique10 RenderWith1LightNoTexture\r\n"\r
1437     //    "{\r\n"\r
1438     //    "    pass p0\r\n"\r
1439     //    "    {\r\n"\r
1440     //    "       SetVertexShader( CompileShader( vs_4_0, RenderWith1LightNoTextureVS() ) );\r\n"\r
1441     //    "       SetGeometryShader( NULL );\r\n"\r
1442     //    "       SetPixelShader( CompileShader( ps_4_0, RenderWith1LightNoTexturePS() ) );\r\n"\r
1443     //    "    }\r\n"\r
1444     //    "}\r\n"\r
1445     //    "";\r
1446 \r
1447     //UINT dwBufferSize = ( UINT )strlen( g_strBuffer ) + 1;\r
1448 \r
1449     //HRESULT hr = D3DX10CreateEffectFromMemory( g_strBuffer, dwBufferSize, "None", NULL, NULL, "fx_4_0",\r
1450     //                                           D3D10_SHADER_ENABLE_STRICTNESS, 0, pd3dDevice, NULL,\r
1451     //                                           NULL, &s_pD3D10Effect, NULL, NULL );\r
1452     //if( FAILED( hr ) )\r
1453     //    return hr;\r
1454 \r
1455     //s_pRenderTech = s_pD3D10Effect->GetTechniqueByName( "RenderWith1LightNoTexture" );\r
1456     //g_pMaterialDiffuseColor = s_pD3D10Effect->GetVariableByName( "g_MaterialDiffuseColor" )->AsVector();\r
1457     //g_pLightDir = s_pD3D10Effect->GetVariableByName( "g_LightDir" )->AsVector();\r
1458     //g_pmWorld = s_pD3D10Effect->GetVariableByName( "g_mWorld" )->AsMatrix();\r
1459     //g_pmWorldViewProjection = s_pD3D10Effect->GetVariableByName( "g_mWorldViewProjection" )->AsMatrix();\r
1460 \r
1461     //const D3D10_INPUT_ELEMENT_DESC layout[] =\r
1462     //{\r
1463     //    { "POSITION",  0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0,  D3D10_INPUT_PER_VERTEX_DATA, 0 },\r
1464     //    { "NORMAL",    0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },\r
1465     //};\r
1466     //D3D10_PASS_DESC PassDesc;\r
1467     //V_RETURN( s_pRenderTech->GetPassByIndex( 0 )->GetDesc( &PassDesc ) );\r
1468     //V_RETURN( pd3dDevice->CreateInputLayout( layout, 2, PassDesc.pIAInputSignature,\r
1469     //                                         PassDesc.IAInputSignatureSize, &s_pVertexLayout ) );\r
1470     \r
1471     //TODO:  Add loading code here\r
1472 \r
1473     return S_OK;\r
1474 }\r
1475 \r
1476 //--------------------------------------------------------------------------------------\r
1477 HRESULT CDXUTDirectionWidget::OnRender11( D3DXCOLOR color, const D3DXMATRIX* pmView, const D3DXMATRIX* pmProj,\r
1478                                           const D3DXVECTOR3* pEyePt )\r
1479 {\r
1480    // NO D3DX11 YET\r
1481    // m_mView = *pmView;\r
1482 \r
1483    // // Render the light spheres so the user can visually see the light dir\r
1484    // D3DXMATRIX mRotate;\r
1485    // D3DXMATRIX mScale;\r
1486    // D3DXMATRIX mTrans;\r
1487    // D3DXMATRIXA16 mWorldViewProj;\r
1488 \r
1489    // g_pMaterialDiffuseColor->SetFloatVector( ( float* )&color );\r
1490    // D3DXVECTOR3 vEyePt;\r
1491    // D3DXVec3Normalize( &vEyePt, pEyePt );\r
1492    // g_pLightDir->SetFloatVector( ( float* )&vEyePt );\r
1493 \r
1494    // // Rotate arrow model to point towards origin\r
1495    // D3DXMATRIX mRotateA, mRotateB;\r
1496    // D3DXVECTOR3 vAt = D3DXVECTOR3( 0, 0, 0 );\r
1497    // D3DXVECTOR3 vUp = D3DXVECTOR3( 0, 1, 0 );\r
1498    // D3DXMatrixRotationX( &mRotateB, D3DX_PI );\r
1499    // D3DXMatrixLookAtLH( &mRotateA, &m_vCurrentDir, &vAt, &vUp );\r
1500    // D3DXMatrixInverse( &mRotateA, NULL, &mRotateA );\r
1501    // mRotate = mRotateB * mRotateA;\r
1502 \r
1503    // D3DXVECTOR3 vL = m_vCurrentDir * m_fRadius * 1.0f;\r
1504    // D3DXMatrixTranslation( &mTrans, vL.x, vL.y, vL.z );\r
1505    // D3DXMatrixScaling( &mScale, m_fRadius * 0.2f, m_fRadius * 0.2f, m_fRadius * 0.2f );\r
1506 \r
1507    // D3DXMATRIX mWorld = mRotate * mScale * mTrans;\r
1508    // mWorldViewProj = mWorld * ( m_mView )*( *pmProj );\r
1509 \r
1510    // g_pmWorldViewProjection->SetMatrix( ( float* )&mWorldViewProj );\r
1511    // g_pmWorld->SetMatrix( ( float* )&mWorld );\r
1512 \r
1513    // s_pd3d10Device->IASetInputLayout( s_pVertexLayout );\r
1514     \r
1515     //TODO:  Add rendering code here\r
1516 \r
1517     return S_OK;\r
1518 }\r
1519 \r
1520 //--------------------------------------------------------------------------------------\r
1521 void CDXUTDirectionWidget::StaticOnD3D11DestroyDevice()\r
1522 {\r
1523 //    SAFE_RELEASE( s_pVertexLayout );\r
1524 //    SAFE_RELEASE( s_pD3D11Effect );\r
1525 }\r