Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

421 lines
13 KiB

  1. /*****************************************************************************\
  2. FILE: CameraMove.cpp
  3. DESCRIPTION:
  4. The caller can create this object to tell it to move from point a to
  5. point b from time t1 to time t2.
  6. BryanSt 12/24/2000
  7. Copyright (C) Microsoft Corp 2000-2001. All rights reserved.
  8. \*****************************************************************************/
  9. #include "stdafx.h"
  10. #include <d3d8.h>
  11. #include <d3dx8.h>
  12. #include <d3dsaver.h>
  13. #include <d3d8rgbrast.h>
  14. #include <dxutil.h>
  15. #include <shlobj.h>
  16. #include "CameraMove.h"
  17. enum eCameraMoveType
  18. {
  19. cameraMoveLocation = 0,
  20. cameraRotate,
  21. cameraWait,
  22. };
  23. typedef struct
  24. {
  25. eCameraMoveType type;
  26. D3DXVECTOR3 vSourceLoc; // For cameraMoveLocation and cameraRotate
  27. D3DXVECTOR3 vSourceTangent; // For cameraMoveLocation and cameraRotate
  28. D3DXVECTOR3 vDestLoc; // For cameraMoveLocation
  29. D3DXVECTOR3 vDestTangent; // For cameraMoveLocation and cameraRotate
  30. float fTime; // For cameraMoveLocation cameraRotate, and cameraWait
  31. int nMinFrames;
  32. int nMaxFrames;
  33. int nBatch;
  34. int nPreFetch;
  35. } CAMERA_MOVEMENT;
  36. CCameraMove::CCameraMove()
  37. {
  38. m_hdpaMovements = DPA_Create(4);
  39. m_fTimeInPreviousMovements = NULL;
  40. m_vLookAtLast = m_vUpVec = m_vLocLast = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  41. m_nCurrent = 0;
  42. m_fTimeInPreviousMovements = 0.0f;
  43. m_nFramesFromCurrent = 1;
  44. m_fTimeToLookAtPainting = 1.0f;
  45. DWORD dwSpeedSlider = DEFAULT_SPEEDSLIDER;
  46. if (g_pConfig)
  47. {
  48. m_fTimeToLookAtPainting = (float) g_pConfig->GetDWORDSetting(CONFIG_DWORD_VIEWPAINTINGTIME);
  49. dwSpeedSlider = g_pConfig->GetDWORDSetting(CONFIG_DWORD_SPEED_SLIDER);
  50. }
  51. m_fTimeToRotate = s_SpeedSettings[dwSpeedSlider].fTimeToRotate;
  52. m_nMinTurnFrames = s_SpeedSettings[dwSpeedSlider].nMinTurnFrames;
  53. m_nMaxTurnFrames = s_SpeedSettings[dwSpeedSlider].nMaxTurnFrames;
  54. m_fTimeToWalk = s_SpeedSettings[dwSpeedSlider].fTimeToWalk;
  55. m_nMinWalkFrames = s_SpeedSettings[dwSpeedSlider].nMinWalkFrames;
  56. m_nMaxWalkFrames = s_SpeedSettings[dwSpeedSlider].nMaxWalkFrames;
  57. }
  58. CCameraMove::~CCameraMove()
  59. {
  60. DeleteAllMovements(0.0f);
  61. }
  62. HRESULT CCameraMove::Init(D3DXVECTOR3 vStartLoc, D3DXVECTOR3 vStartTangent, D3DXVECTOR3 vUpVec)
  63. {
  64. HRESULT hr = S_OK;
  65. // Initialize member variables
  66. m_vUpVec = vUpVec;
  67. m_vLocLast = vStartLoc;
  68. m_vLookAtLast = vStartTangent;
  69. m_nFramesFromCurrent = 0;
  70. return hr;
  71. }
  72. HRESULT CCameraMove::CreateNextMove(D3DXVECTOR3 vSourceLoc, D3DXVECTOR3 vSourceTangent, D3DXVECTOR3 vDestLoc, D3DXVECTOR3 vDestTangent)
  73. {
  74. HRESULT hr = E_OUTOFMEMORY;
  75. if (m_hdpaMovements)
  76. {
  77. CAMERA_MOVEMENT * pNew = (CAMERA_MOVEMENT *) LocalAlloc(LPTR, sizeof(*pNew));
  78. if (pNew)
  79. {
  80. D3DXVECTOR3 vDelta = (vSourceLoc - vDestLoc);
  81. float fLen = D3DXVec3Length(&vDelta); // How far are we traveling
  82. float fRatio = (fLen / 50.0f); // The speed values are stored per 50.0f distance
  83. pNew->type = cameraMoveLocation;
  84. pNew->vSourceLoc = vSourceLoc;
  85. pNew->vSourceTangent = vSourceTangent;
  86. pNew->vDestLoc = vDestLoc;
  87. pNew->vDestTangent = vDestTangent;
  88. pNew->fTime = (m_fTimeToWalk * fRatio);
  89. pNew->nMinFrames = (int) max((m_nMinWalkFrames * fRatio), 1);
  90. pNew->nMaxFrames = (int) max((m_nMaxWalkFrames * fRatio), 1);
  91. pNew->nBatch = 0;
  92. pNew->nPreFetch = 0;
  93. if (-1 != DPA_AppendPtr(m_hdpaMovements, pNew))
  94. {
  95. hr = S_OK;
  96. }
  97. else
  98. {
  99. LocalFree(pNew);
  100. }
  101. }
  102. }
  103. return hr;
  104. }
  105. HRESULT CCameraMove::CreateNextRotate(D3DXVECTOR3 vSourceLoc, D3DXVECTOR3 vSourceTangent, D3DXVECTOR3 vDestTangent)
  106. {
  107. HRESULT hr = E_OUTOFMEMORY;
  108. if (m_hdpaMovements)
  109. {
  110. CAMERA_MOVEMENT * pNew = (CAMERA_MOVEMENT *) LocalAlloc(LPTR, sizeof(*pNew));
  111. if (pNew)
  112. {
  113. float fDotProduct = D3DXVec3Dot(&vSourceTangent, &vDestTangent);
  114. float fRatio;
  115. if (fDotProduct)
  116. {
  117. float fRads = (float)acos(fDotProduct / max(1, (D3DXVec3Length(&vSourceTangent) * D3DXVec3Length(&vDestTangent)))); // How far are we traveling
  118. fRatio = (D3DXToDegree(fRads) / 90.0f); // The speed values are stored per 90.0f distance
  119. }
  120. else
  121. {
  122. // Assume a dot product of 0 means 90 degrees.
  123. fRatio = 1.0f; // The speed values are stored per 90.0f distance
  124. }
  125. pNew->type = cameraRotate;
  126. pNew->vSourceLoc = vSourceLoc;
  127. pNew->vSourceTangent = vSourceTangent;
  128. pNew->vDestLoc = vSourceLoc;
  129. pNew->vDestTangent = vDestTangent;
  130. pNew->fTime = (m_fTimeToRotate * fRatio);
  131. pNew->nMinFrames = (int) max((m_nMinTurnFrames * fRatio), 1);
  132. pNew->nMaxFrames = (int) max((m_nMaxTurnFrames * fRatio), 1);
  133. pNew->nBatch = 0;
  134. pNew->nPreFetch = 0;
  135. if (-1 != DPA_AppendPtr(m_hdpaMovements, pNew))
  136. {
  137. hr = S_OK;
  138. }
  139. else
  140. {
  141. LocalFree(pNew);
  142. }
  143. }
  144. }
  145. return hr;
  146. }
  147. HRESULT CCameraMove::CreateNextWait(int nBatch, int nPreFetch, float fTime)
  148. {
  149. HRESULT hr = E_OUTOFMEMORY;
  150. if (-1.0f == fTime)
  151. {
  152. fTime = m_fTimeToLookAtPainting;
  153. }
  154. if (m_hdpaMovements)
  155. {
  156. CAMERA_MOVEMENT * pNew = (CAMERA_MOVEMENT *) LocalAlloc(LPTR, sizeof(*pNew));
  157. if (pNew)
  158. {
  159. pNew->type = cameraWait;
  160. pNew->vSourceLoc = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  161. pNew->vSourceTangent = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  162. pNew->vDestLoc = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  163. pNew->vDestTangent = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  164. pNew->fTime = fTime;
  165. pNew->nMinFrames = 1;
  166. pNew->nMaxFrames = 1000000;
  167. pNew->nBatch = nBatch;
  168. pNew->nPreFetch = nPreFetch;
  169. if (-1 != DPA_AppendPtr(m_hdpaMovements, pNew))
  170. {
  171. hr = S_OK;
  172. }
  173. else
  174. {
  175. LocalFree(pNew);
  176. }
  177. }
  178. }
  179. return hr;
  180. }
  181. HRESULT CCameraMove::SetCamera(IDirect3DDevice8 * pD3DDevice, FLOAT fTimeKeyIn)
  182. {
  183. HRESULT hr = E_INVALIDARG;
  184. if (pD3DDevice && m_hdpaMovements)
  185. {
  186. float fTimeInSegment = 0.0f;
  187. CAMERA_MOVEMENT * pCurrent = NULL;
  188. if (0 > m_nCurrent)
  189. {
  190. m_nCurrent = 0;
  191. }
  192. if (m_nCurrent >= DPA_GetPtrCount(m_hdpaMovements))
  193. {
  194. hr = S_FALSE; // This means we left the room.
  195. }
  196. else
  197. {
  198. do
  199. {
  200. pCurrent = (CAMERA_MOVEMENT *) DPA_GetPtr(m_hdpaMovements, m_nCurrent);
  201. if (!pCurrent)
  202. {
  203. // ASSERT(FAILED(hr));
  204. break;
  205. }
  206. else
  207. {
  208. float fTimePerFrameMin = (pCurrent->fTime / pCurrent->nMinFrames);
  209. fTimeInSegment = (fTimeKeyIn - m_fTimeInPreviousMovements);
  210. if (fTimeInSegment < 0)
  211. {
  212. fTimeInSegment = 0;
  213. }
  214. // Do we need to warp time in order to have enough frames for the motion so we don't
  215. // jump?
  216. if ((fTimeInSegment > (fTimePerFrameMin * m_nFramesFromCurrent)) &&
  217. (m_nFramesFromCurrent <= pCurrent->nMinFrames))
  218. {
  219. // Yes.
  220. float fTimeWarp = (fTimeInSegment - (fTimePerFrameMin * m_nFramesFromCurrent));
  221. m_fTimeInPreviousMovements += fTimeWarp;
  222. fTimeInSegment = (fTimeKeyIn - m_fTimeInPreviousMovements);
  223. }
  224. if (fTimeInSegment > pCurrent->fTime)
  225. {
  226. m_fTimeInPreviousMovements += pCurrent->fTime;
  227. if (cameraRotate == pCurrent->type)
  228. {
  229. m_vLocLast = pCurrent->vSourceLoc;
  230. m_vLookAtLast = pCurrent->vDestTangent;
  231. }
  232. else if (cameraMoveLocation == pCurrent->type)
  233. {
  234. m_vLocLast = pCurrent->vDestLoc;
  235. m_vLookAtLast = pCurrent->vDestTangent;
  236. }
  237. m_nFramesFromCurrent = 0;
  238. m_nCurrent++;
  239. }
  240. else
  241. {
  242. m_nFramesFromCurrent++;
  243. hr = S_OK;
  244. break;
  245. }
  246. }
  247. }
  248. while (1);
  249. }
  250. if (S_OK == hr) // S_FALSE means we left the room, so do nothing.
  251. {
  252. D3DXVECTOR3 vEye = m_vLocLast;
  253. D3DXVECTOR3 vLookAt = (m_vLocLast + m_vLookAtLast);
  254. float fTimeRatio = (fTimeInSegment / pCurrent->fTime);
  255. float fTimeRemainingInSeg = 0.0f;
  256. switch (pCurrent->type)
  257. {
  258. case cameraMoveLocation:
  259. D3DXVec3Lerp(&vEye, &pCurrent->vSourceLoc, &pCurrent->vDestLoc, fTimeRatio);
  260. D3DXVec3Lerp(&vLookAt, &pCurrent->vSourceTangent, &pCurrent->vDestTangent, fTimeRatio);
  261. vLookAt += vEye;
  262. break;
  263. case cameraRotate:
  264. // TODO: Use D3DXVec3Lerp() instead.
  265. D3DXVec3Lerp(&vLookAt, &pCurrent->vSourceTangent, &pCurrent->vDestTangent, fTimeRatio);
  266. vLookAt += vEye;
  267. // vLookAt = (vEye + (pCurrent->vSourceTangent + (fTimeRatio * (pCurrent->vDestTangent - pCurrent->vSourceTangent))));
  268. // How do we rotate? Quaternion.
  269. break;
  270. case cameraWait:
  271. if (m_nFramesFromCurrent > 1)
  272. {
  273. if ((2 == m_nFramesFromCurrent) && g_pPictureMgr)
  274. {
  275. DWORD dwMaxPixelSize = ((3 * g_dwHeight) / 4);
  276. // Let's take the hit now of converting an image into a texture object since we don't have
  277. // any work to do while looking at this painting. This can normally take 1.5 seconds, so
  278. // it's big perf hit to do it any other time.
  279. hr = g_pPictureMgr->PreFetch(pCurrent->nBatch, pCurrent->nPreFetch);
  280. }
  281. else
  282. {
  283. // We don't have any work remaining to do, so sleep so the computer can get some work
  284. // done. (Like in background services or let it do any paging that we may have caused)
  285. fTimeRemainingInSeg = (pCurrent->fTime - fTimeInSegment);
  286. int nSleepTime = 1000 * (int) fTimeRemainingInSeg;
  287. Sleep(nSleepTime);
  288. }
  289. }
  290. break;
  291. default:
  292. // Do nothing.
  293. break;
  294. };
  295. D3DXMATRIX matView;
  296. D3DXMATRIX matIdentity;
  297. D3DXMatrixIdentity(&matIdentity);
  298. if (g_fOverheadViewTest)
  299. {
  300. static float s_fHeight = 600.0f;
  301. D3DXVECTOR3 vDelta = (vEye - vLookAt);
  302. vEye += D3DXVECTOR3(0.0f, s_fHeight, 0.0f);
  303. vEye += (4 * vDelta);
  304. D3DXMatrixLookAtLH(&matView, &vEye, &vLookAt, &m_vUpVec);
  305. }
  306. else
  307. {
  308. D3DXMatrixLookAtLH(&matView, &vEye, &vLookAt, &m_vUpVec);
  309. }
  310. // PrintLocation(TEXT("Camera angle at: %s and looking at: %s"), vEye, vLookAt);
  311. hr = pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
  312. m_vEyePrev = vEye;
  313. m_vLookAtPrev = vLookAt;
  314. }
  315. else
  316. {
  317. D3DXMATRIX matView;
  318. D3DXMatrixLookAtLH(&matView, &m_vEyePrev, &m_vLookAtPrev, &m_vUpVec);
  319. // PrintLocation(TEXT("xxxxxx Camera angle at: %s and looking at: %s"), m_vEyePrev, m_vLookAtPrev);
  320. pD3DDevice->SetTransform(D3DTS_VIEW, &matView);
  321. }
  322. }
  323. else
  324. {
  325. DXUtil_Trace(TEXT("ERROR: pD3DDevice or m_hdpaMovements is NULL"));
  326. }
  327. return hr;
  328. }
  329. HRESULT CCameraMove::DeleteAllMovements(float fCurrentTime)
  330. {
  331. HRESULT hr = S_OK;
  332. if (m_hdpaMovements)
  333. {
  334. DPA_DestroyCallback(m_hdpaMovements, DPALocalFree_Callback, NULL);
  335. m_hdpaMovements = DPA_Create(4);
  336. }
  337. m_fTimeInPreviousMovements = fCurrentTime;
  338. m_nCurrent = 0;
  339. return hr;
  340. }