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.

1500 lines
58 KiB

  1. /*****************************************************************************\
  2. FILE: room.cpp
  3. DESCRIPTION:
  4. BryanSt 12/24/2000
  5. Copyright (C) Microsoft Corp 2000-2001. All rights reserved.
  6. \*****************************************************************************/
  7. #include "stdafx.h"
  8. #include "main.h"
  9. #include "room.h"
  10. #include "util.h"
  11. // Ref-counting on the room tree is involved because it's a doubly linked tree with the root node constantly changing, so
  12. // we need this mechanism to make sure we get the ref-count correct and don't leak.
  13. int g_nLeakCheck = 0;
  14. float g_fRoomWidthX = 100.0f;
  15. float g_fRoomDepthZ = 200.0f;
  16. float g_fRoomHeightY = 40.0f;
  17. float g_fPaintingHeightY = (g_fRoomHeightY * SIZE_MAXPAINTINGSIZE_INWALLPERCENT); // This is how much of the wall we want the painting to take up.
  18. float g_fFudge = 0.1f; // This will cause one object to be above another.
  19. #define MAX_ROOMWALK_PATHS 2
  20. #define NORMAL_NEG_Z D3DXVECTOR3(0, 0, -1)
  21. #define NORMAL_NEG_Y D3DXVECTOR3(0, -1, 0)
  22. #define NORMAL_NEG_X D3DXVECTOR3(-1, 0, 0)
  23. #define NORMAL_Z D3DXVECTOR3(0, 0, 1)
  24. #define NORMAL_Y D3DXVECTOR3(0, 1, 0)
  25. #define NORMAL_X D3DXVECTOR3(1, 0, 0)
  26. #define NORMAL_NEG_Z D3DXVECTOR3(0, 0, -1)
  27. #define NORMAL_NEG_Z D3DXVECTOR3(0, 0, -1)
  28. PAINTING_LAYOUT g_LongRoomPaintings1[6]; // Both doors exist (1 & 2)
  29. PAINTING_LAYOUT g_LongRoomPaintings2[7]; // Doors 0 & 1 exist (Must exit 1)
  30. PAINTING_LAYOUT g_LongRoomPaintings3[7]; // Doors 0 & 1 exist (Must exit 2)
  31. ROOM_FLOORPLANS g_RoomFloorPlans[] =
  32. {
  33. {0, 1, 0, TRUE, TRUE, TRUE, ARRAYSIZE(g_LongRoomPaintings1), g_LongRoomPaintings1},
  34. {0, 1, 0, TRUE, TRUE, TRUE, ARRAYSIZE(g_LongRoomPaintings1), g_LongRoomPaintings1}, // Duplicate to increase odds
  35. {0, 2, 0, TRUE, TRUE, TRUE, ARRAYSIZE(g_LongRoomPaintings1), g_LongRoomPaintings1},
  36. {0, 2, 0, TRUE, TRUE, TRUE, ARRAYSIZE(g_LongRoomPaintings1), g_LongRoomPaintings1}, // Duplicate to increase odds
  37. {0, 1, 0, TRUE, TRUE, FALSE, ARRAYSIZE(g_LongRoomPaintings2), g_LongRoomPaintings2},
  38. {0, 2, 0, TRUE, FALSE, TRUE, ARRAYSIZE(g_LongRoomPaintings3), g_LongRoomPaintings3},
  39. // These require entering door other than 0
  40. // {1, 2, 1, TRUE, TRUE, TRUE, ARRAYSIZE(g_LongRoomPaintings1), g_LongRoomPaintings1},
  41. // {2, 1, 1, TRUE, TRUE, TRUE, ARRAYSIZE(g_LongRoomPaintings1), g_LongRoomPaintings1},
  42. // This requuires supporting leaving the first door
  43. // {2, 0, TRUE, TRUE, FALSE, ARRAYSIZE(g_LongRoomPaintings2), g_LongRoomPaintings2},
  44. };
  45. ROOM_FLOORPLANS g_RoomFloorPlansLobby[] =
  46. {
  47. {0, 1, 0, FALSE, TRUE, TRUE, 0, NULL},
  48. {0, 2, 0, FALSE, TRUE, TRUE, 0, NULL}
  49. };
  50. void InitLayout(void)
  51. {
  52. static BOOL fInited = FALSE;
  53. if (!fInited)
  54. {
  55. int nIndex;
  56. fInited = TRUE;
  57. g_LongRoomPaintings1[0].vLocation = D3DXVECTOR3(g_fFudge, g_fPaintingHeightY, (g_fRoomDepthZ / 4.0f)); g_LongRoomPaintings1[0].vNormal = NORMAL_X; // Left Wall 1
  58. g_LongRoomPaintings1[1].vLocation = D3DXVECTOR3(g_fFudge, g_fPaintingHeightY, (g_fRoomDepthZ * (2.0f / 4.0f))); g_LongRoomPaintings1[1].vNormal = NORMAL_X; // Left Wall 2
  59. g_LongRoomPaintings1[2].vLocation = D3DXVECTOR3((g_fRoomWidthX * (1.0f / 3.0f)), g_fPaintingHeightY, g_fRoomDepthZ-g_fFudge); g_LongRoomPaintings1[2].vNormal = NORMAL_NEG_Z; // Front Wall 1
  60. g_LongRoomPaintings1[3].vLocation = D3DXVECTOR3((g_fRoomWidthX * (2.0f / 3.0f)), g_fPaintingHeightY, g_fRoomDepthZ-g_fFudge); g_LongRoomPaintings1[3].vNormal = NORMAL_NEG_Z; // Front Wall 2
  61. g_LongRoomPaintings1[4].vLocation = D3DXVECTOR3(g_fRoomWidthX-g_fFudge, g_fPaintingHeightY, (g_fRoomDepthZ / 4.0f)); g_LongRoomPaintings1[4].vNormal = NORMAL_NEG_X; // Right Wall 1
  62. g_LongRoomPaintings1[5].vLocation = D3DXVECTOR3(g_fRoomWidthX-g_fFudge, g_fPaintingHeightY, (g_fRoomDepthZ * (2.0f / 4.0f) )); g_LongRoomPaintings1[5].vNormal = NORMAL_NEG_X; // Right Wall 2
  63. // g_LongRoomPaintings2 is a copy of g_LongRoomPaintings1 plus another painting.
  64. for (nIndex = 0; nIndex < ARRAYSIZE(g_LongRoomPaintings1); nIndex++)
  65. {
  66. g_LongRoomPaintings2[nIndex].vLocation = g_LongRoomPaintings1[nIndex].vLocation;
  67. g_LongRoomPaintings2[nIndex].vNormal = g_LongRoomPaintings1[nIndex].vNormal;
  68. }
  69. g_LongRoomPaintings2[6].vLocation = D3DXVECTOR3(g_fRoomWidthX-g_fFudge, g_fPaintingHeightY, (g_fRoomDepthZ * (3.0f / 4.0f) )); g_LongRoomPaintings2[6].vNormal = NORMAL_NEG_X; // Right Wall 3
  70. // g_LongRoomPaintings3 is a copy of g_LongRoomPaintings1 plus another painting.
  71. for (nIndex = 0; nIndex < ARRAYSIZE(g_LongRoomPaintings1); nIndex++)
  72. {
  73. g_LongRoomPaintings3[nIndex].vLocation = g_LongRoomPaintings1[nIndex].vLocation;
  74. g_LongRoomPaintings3[nIndex].vNormal = g_LongRoomPaintings1[nIndex].vNormal;
  75. }
  76. g_LongRoomPaintings3[6].vLocation = D3DXVECTOR3(g_fFudge, g_fPaintingHeightY, (g_fRoomDepthZ * (3.0f / 4.0f))); g_LongRoomPaintings3[6].vNormal = NORMAL_X; // Left Wall 3
  77. }
  78. }
  79. //-----------------------------------------------------------------------------
  80. // Name: CTheRoom()
  81. // Desc: Constructor
  82. //-----------------------------------------------------------------------------
  83. CTheRoom::CTheRoom(BOOL fLobby, CMSLogoDXScreenSaver * pMain, CTheRoom * pEnterRoom, int nBatch)
  84. : m_objWall1(pMain), m_objCeiling(pMain), m_objToeGuard1(pMain), m_objFloor(pMain),
  85. m_theRug(pMain), m_thePowerSocket(pMain), m_nBatch(nBatch), m_cRef(1)
  86. {
  87. InitLayout();
  88. // Initialize member variables
  89. D3DXMatrixIdentity(&m_matIdentity);
  90. m_pEnterRoom = NULL;
  91. m_pFirstRoom = NULL;
  92. m_pLeftRoom = NULL;
  93. m_pRightRoom = NULL;
  94. m_fRoomCreated = FALSE;
  95. m_fVisible = FALSE;
  96. m_fLowPriority = FALSE;
  97. m_fLobby = fLobby;
  98. m_pMain = pMain;
  99. m_fCurrentRoom = FALSE;
  100. IUnknown_Set((IUnknown **) &m_pEnterRoom, pEnterRoom);
  101. if (fLobby)
  102. {
  103. m_pFloorPlan = &g_RoomFloorPlansLobby[GetRandomInt(0, ARRAYSIZE(g_RoomFloorPlansLobby)-1)];
  104. }
  105. else
  106. {
  107. m_pFloorPlan = &g_RoomFloorPlans[GetRandomInt(0, ARRAYSIZE(g_RoomFloorPlans)-1)]; // ARRAYSIZE(g_RoomFloorPlans)-1
  108. }
  109. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pPaintings); nIndex++)
  110. {
  111. m_pPaintings[nIndex] = NULL;
  112. }
  113. g_nLeakCheck++;
  114. }
  115. CTheRoom::~CTheRoom()
  116. {
  117. for (int nIndex = 0; nIndex < ARRAYSIZE(m_pPaintings); nIndex++)
  118. {
  119. SAFE_DELETE(m_pPaintings[nIndex]);
  120. }
  121. FinalCleanup(); // Just in case someone forgot to call FinalCleanup() in an error condition.
  122. g_nLeakCheck--;
  123. }
  124. HRESULT CTheRoom::_InitPaintings(void)
  125. {
  126. HRESULT hr = S_OK;
  127. if (!g_pPictureMgr || !m_pFloorPlan)
  128. {
  129. return E_FAIL;
  130. }
  131. if (m_pPaintings[0])
  132. {
  133. return S_OK;
  134. }
  135. #define FRAMESIZE_X 0.062696f // This is the frame size for frame.bmp
  136. #define FRAMESIZE_Y 0.087336f // This is the frame size for frame.bmp
  137. float fMaxPaintingWH = (g_fRoomHeightY * 0.4f); // The picture can not be more than one half the size of the wall.
  138. float fScale = 1.0f;
  139. for (int nIndex = 0; (nIndex < ARRAYSIZE(m_pPaintings)) && (nIndex < m_pFloorPlan->nPaintings) && SUCCEEDED(hr); nIndex++)
  140. {
  141. m_pPaintings[nIndex] = new CPainting(m_pMain);
  142. if (m_pPaintings[nIndex])
  143. {
  144. DWORD dwMaxPixelSize = ((3 * g_dwHeight) / 4);
  145. CTexture * pPaintingTexture = NULL;
  146. hr = g_pPictureMgr->GetPainting(m_nBatch, nIndex, 0, &pPaintingTexture);
  147. if (SUCCEEDED(hr))
  148. {
  149. D3DXVECTOR3 vPaintingLoc = m_pFloorPlan->pPaintingsLayout[nIndex].vLocation;
  150. D3DXVECTOR3 vPaintingNormal = m_pFloorPlan->pPaintingsLayout[nIndex].vNormal;
  151. m_pPaintings[nIndex]->OneTimeSceneInit();
  152. hr = m_pPaintings[nIndex]->SetPainting(m_pMain->GetGlobalTexture(ITEM_FRAME, &fScale), pPaintingTexture, vPaintingLoc, fMaxPaintingWH, FRAMESIZE_X, FRAMESIZE_Y, vPaintingNormal, dwMaxPixelSize);
  153. pPaintingTexture->Release();
  154. }
  155. else
  156. {
  157. // This will fail if we can't load our pictures. This will cause us to come back later when
  158. // the background thread may have an image.
  159. SAFE_DELETE(m_pPaintings[nIndex]);
  160. }
  161. }
  162. else
  163. {
  164. hr = E_OUTOFMEMORY;
  165. }
  166. }
  167. return hr;
  168. }
  169. HRESULT CTheRoom::_AddWall(BOOL fWithDoor, D3DXVECTOR3 vLocation, D3DXVECTOR3 vWidth, D3DXVECTOR3 vHeight, D3DXVECTOR3 vNormal,
  170. float fTotalHeight, float fDoorHeight, float fTotalWidth, float fDoorWidth, float fDoorStart)
  171. {
  172. HRESULT hr = S_OK;
  173. C3DObject * pobjNextWall = new C3DObject(m_pMain);
  174. C3DObject * pobjNextToeGuard = new C3DObject(m_pMain);
  175. if (pobjNextWall && pobjNextToeGuard && m_pMain)
  176. {
  177. if (fWithDoor)
  178. {
  179. hr = _AddWallWithDoor(pobjNextWall, pobjNextToeGuard, &m_objFloor, vLocation, vWidth, vHeight, vNormal, fTotalHeight, fDoorHeight, fTotalWidth, fDoorWidth, fDoorStart);
  180. }
  181. else
  182. {
  183. // Texture Coords
  184. float fScale = 1.0f;
  185. CTexture * pTexture = m_pMain->GetGlobalTexture(ITEM_WALLPAPER, &fScale);
  186. float fTSWallpaperX = (TEXTURESCALE_WALLPAPER * fScale); // How many repeats per 1 unit.
  187. float fTSWallpaperY = fTSWallpaperX * pTexture->GetSurfaceRatio();
  188. D3DXVECTOR3 vSizeNoDoor = ((vWidth * fTotalWidth) + (vHeight * fTotalHeight));
  189. hr = pobjNextWall->InitPlane(pTexture, m_pMain->GetD3DDevice(), vLocation, vSizeNoDoor, vNormal, 2, 2, fTSWallpaperX, fTSWallpaperY, 0, 10);
  190. if (SUCCEEDED(hr))
  191. {
  192. CTexture * pToeGuardTexture = m_pMain->GetGlobalTexture(ITEM_TOEGUARD, &fScale);
  193. float fTSToeGuardX = (TEXTURESCALE_TOEGUARD * fScale); // How many repeats per 1 unit.
  194. float fTSToeGuardY = fTSToeGuardX * pToeGuardTexture->GetSurfaceRatio();
  195. // Draw ToeGuard
  196. vLocation += (g_fFudge * vNormal);
  197. vSizeNoDoor = D3DXVECTOR3(vSizeNoDoor.x, TOEGUARD_HEIGHT, vSizeNoDoor.z);
  198. hr = pobjNextToeGuard->InitPlane(pToeGuardTexture, m_pMain->GetD3DDevice(), vLocation, vSizeNoDoor, vNormal, 2, 2, fTSToeGuardX, fTSToeGuardY, 0, 0);
  199. }
  200. }
  201. if (SUCCEEDED(hr))
  202. {
  203. hr = m_objWall1.CombineObject(m_pMain->GetD3DDevice(), pobjNextWall);
  204. hr = m_objToeGuard1.CombineObject(m_pMain->GetD3DDevice(), pobjNextToeGuard);
  205. }
  206. }
  207. SAFE_DELETE(pobjNextWall);
  208. SAFE_DELETE(pobjNextToeGuard);
  209. return hr;
  210. }
  211. HRESULT CTheRoom::_AddWallWithDoor(C3DObject * pobjWall, C3DObject * pobjToeGuard, C3DObject * pobjFloor, D3DXVECTOR3 vLocation, D3DXVECTOR3 vWidth, D3DXVECTOR3 vHeight, D3DXVECTOR3 vNormal,
  212. float fTotalHeight, float fDoorHeight, float fTotalWidth, float fDoorWidth, float fDoorStart)
  213. {
  214. HRESULT hr = S_OK;
  215. float fScale = 1.0f;
  216. float fYToeGuard = TOEGUARD_HEIGHT;
  217. CTexture * pToeTexture = m_pMain->GetGlobalTexture(ITEM_TOEGUARD, &fScale);
  218. float fTSToeGuardX = (TEXTURESCALE_TOEGUARD * fScale); // How many repeats per 1 unit.
  219. float fTSToeGuardY = fTSToeGuardX * pToeTexture->GetSurfaceRatio();
  220. CTexture * pTexture = m_pMain->GetGlobalTexture(ITEM_WALLPAPER, &fScale);
  221. float fTSWallpaperX = (TEXTURESCALE_WALLPAPER * fScale); // How many repeats per 1 unit.
  222. float fTSWallpaperY = fTSWallpaperX * pTexture->GetSurfaceRatio();
  223. CTexture * pFloorTexture = m_pMain->GetGlobalTexture(ITEM_FLOOR, &fScale);
  224. float fTSFloorX = (TEXTURESCALE_FLOOR * fScale); // How many repeats per 1 unit.
  225. float fTSFloorY = fTSFloorX * pFloorTexture->GetSurfaceRatio();
  226. // Create Main Wall
  227. D3DXVECTOR3 vSize = ((fDoorStart * vWidth) + (fTotalHeight * vHeight));
  228. hr = pobjWall->InitPlane(pTexture, m_pMain->GetD3DDevice(), vLocation, vSize, vNormal, 2, 2, fTSWallpaperX, fTSWallpaperY, 0, 10);
  229. if (SUCCEEDED(hr))
  230. {
  231. D3DXVECTOR3 vToeLocation = (vLocation + (g_fFudge * vNormal)); // Offset the toeguard so it's above the wall.
  232. vSize = D3DXVECTOR3(D3DXVec3Multiply(vSize, vWidth) + (vHeight * fYToeGuard)); // Replace the height component with the ToeGuard height)
  233. hr = pobjToeGuard->InitPlane(pToeTexture, m_pMain->GetD3DDevice(), vToeLocation, vSize, vNormal, 2, 2, fTSToeGuardX, fTSToeGuardY, 0, 0);
  234. if (SUCCEEDED(hr))
  235. {
  236. int nParts = 9;
  237. D3DXVECTOR3 vNextLocation;
  238. D3DXVECTOR3 vTempNormal;
  239. while (nParts--) // We have 2 more wall parts and 1 more toeguards to add.
  240. {
  241. C3DObject * pNewObject = new C3DObject(m_pMain);
  242. if (pNewObject)
  243. {
  244. switch (nParts)
  245. {
  246. case 8: // Floor at base of door way.
  247. vNextLocation = (vLocation + (fDoorStart * vWidth));
  248. vSize = (((-1.0f * DOORFRAME_DEPTH) * vNormal) + (fDoorWidth * vWidth));
  249. vTempNormal = D3DXVECTOR3(0.0f, 1.0f, 0.0f); // Normal points up
  250. hr = pNewObject->InitPlane(pFloorTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vTempNormal, 2, 2, fTSFloorX, fTSFloorY, 0, 0);
  251. if (SUCCEEDED(hr))
  252. {
  253. hr = pobjFloor->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  254. }
  255. delete pNewObject;
  256. break;
  257. case 7: // Add the wallguard in the door way #2
  258. vNextLocation = (vLocation + ((fDoorStart + g_fFudge) * vWidth) + (g_fFudge * vNormal));
  259. vSize = (((-1.0f * (DOORFRAME_DEPTH + (2.0f * g_fFudge)) * vNormal)) + (fYToeGuard * vHeight));
  260. vTempNormal = vWidth;
  261. hr = pNewObject->InitPlane(pToeTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vTempNormal, 2, 2, fTSToeGuardX, fTSToeGuardY, 0, 0);
  262. if (SUCCEEDED(hr))
  263. {
  264. hr = pobjToeGuard->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  265. }
  266. delete pNewObject;
  267. break;
  268. case 6: // Add the wallguard in the door way #1
  269. vNextLocation = (vLocation + ((fDoorStart + fDoorWidth - g_fFudge) * vWidth) + (g_fFudge * vNormal));
  270. vSize = (((-1.0f * (DOORFRAME_DEPTH + (2.0f * g_fFudge))) * vNormal) + (fYToeGuard * vHeight));
  271. vTempNormal = (-1.0f * vWidth);
  272. hr = pNewObject->InitPlane(pToeTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vTempNormal, 2, 2, fTSToeGuardX, fTSToeGuardY, 0, 0);
  273. if (SUCCEEDED(hr))
  274. {
  275. hr = pobjToeGuard->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  276. }
  277. delete pNewObject;
  278. break;
  279. case 5: // Add door frame top
  280. vNextLocation = (vLocation + (fDoorStart * vWidth) + (fDoorHeight * vHeight));
  281. vSize = (((-1.0f * DOORFRAME_DEPTH) * vNormal) + (fDoorWidth * vWidth));
  282. vTempNormal = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
  283. hr = pNewObject->InitPlane(pTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vTempNormal, 2, 2, fTSWallpaperX, fTSWallpaperY, 0, 10);
  284. if (SUCCEEDED(hr))
  285. {
  286. hr = pobjWall->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  287. }
  288. delete pNewObject;
  289. break;
  290. case 4: // Add door frame #2
  291. vNextLocation = (vLocation + (fDoorStart * vWidth));
  292. vSize = (((-1.0f * DOORFRAME_DEPTH) * vNormal) + (fTotalHeight * vHeight));
  293. vTempNormal = vWidth;
  294. hr = pNewObject->InitPlane(pTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vTempNormal, 2, 2, fTSWallpaperX, fTSWallpaperY, 0, 10);
  295. if (SUCCEEDED(hr))
  296. {
  297. hr = pobjWall->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  298. }
  299. delete pNewObject;
  300. break;
  301. case 3: // Add door frame #1
  302. vNextLocation = (vLocation + ((fDoorStart + fDoorWidth) * vWidth));
  303. vSize = (((-1.0f * DOORFRAME_DEPTH) * vNormal) + (fTotalHeight * vHeight));
  304. vTempNormal = (-1.0f * vWidth);
  305. hr = pNewObject->InitPlane(pToeTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vTempNormal, 2, 2, fTSWallpaperX, fTSWallpaperY, 0, 10);
  306. if (SUCCEEDED(hr))
  307. {
  308. hr = pobjWall->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  309. }
  310. delete pNewObject;
  311. break;
  312. case 2: // Add the second wall part. (Wall over the door)
  313. vNextLocation = (vLocation + (fDoorStart * vWidth) + (fDoorHeight * vHeight));
  314. vSize = ((fDoorWidth * vWidth) + ((fTotalHeight - fDoorHeight) * vHeight));
  315. hr = pNewObject->InitPlane(pTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vNormal, 2, 2, fTSWallpaperX, fTSWallpaperY, 0, 10);
  316. if (SUCCEEDED(hr))
  317. {
  318. hr = pobjWall->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  319. }
  320. delete pNewObject;
  321. break;
  322. case 1: // Add the third wall part
  323. vNextLocation = (vLocation + ((fDoorStart + fDoorWidth) * vWidth));
  324. vSize = (((fTotalWidth - (fDoorStart + fDoorWidth)) * vWidth) + (fTotalHeight * vHeight));
  325. hr = pNewObject->InitPlane(pTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vNormal, 2, 2, fTSWallpaperX, fTSWallpaperY, 0, 10);
  326. if (SUCCEEDED(hr))
  327. {
  328. hr = pobjWall->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  329. }
  330. delete pNewObject;
  331. break;
  332. case 0: // Add the second Toe Guard
  333. vNextLocation = (vLocation + ((fDoorStart + fDoorWidth) * vWidth) + (g_fFudge * vNormal));
  334. vSize = (((fTotalWidth - (fDoorStart + fDoorWidth)) * vWidth) + (fYToeGuard * vHeight));
  335. hr = pNewObject->InitPlane(pToeTexture, m_pMain->GetD3DDevice(), vNextLocation, vSize, vNormal, 2, 2, fTSToeGuardX, fTSToeGuardY, 0, 0);
  336. if (SUCCEEDED(hr))
  337. {
  338. hr = pobjToeGuard->CombineObject(m_pMain->GetD3DDevice(), pNewObject);
  339. }
  340. delete pNewObject;
  341. break;
  342. }
  343. }
  344. else
  345. {
  346. hr = E_OUTOFMEMORY;
  347. }
  348. }
  349. }
  350. }
  351. return hr;
  352. }
  353. HRESULT CTheRoom::_SetRotationMatrix(void)
  354. {
  355. HRESULT hr = S_OK;
  356. D3DXMATRIX matRotate;
  357. D3DXMATRIX matTrans;
  358. // We want to set the matricies to get us to the next room.
  359. // Next Room
  360. if (m_pFirstRoom)
  361. {
  362. D3DXMatrixRotationY(&matRotate, D3DXToRadian(180));
  363. D3DXMatrixTranslation(&matTrans, ((g_fRoomWidthX / 2.0f) + (DOOR_WIDTH / 2.0f) + m_pFirstRoom->GetDoorOffset()), 0.0f, -1.0f);
  364. D3DXMatrixMultiply(&m_matFirstRoom, &matRotate, &matTrans);
  365. }
  366. if (m_pLeftRoom)
  367. {
  368. D3DXMatrixRotationY(&matRotate, D3DXToRadian(270));
  369. D3DXMatrixTranslation(&matTrans, -1.0f, 0.0f, WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f) - m_pLeftRoom->GetDoorOffset());
  370. D3DXMatrixMultiply(&m_matLeftRoom, &matRotate, &matTrans);
  371. }
  372. // Side Room
  373. if (m_pRightRoom)
  374. {
  375. D3DXMatrixRotationY(&matRotate, D3DXToRadian(90));
  376. D3DXMatrixTranslation(&matTrans, (g_fRoomWidthX + 1.0f), 0.0f, (WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f) + m_pRightRoom->GetDoorOffset()));
  377. D3DXMatrixMultiply(&m_matRightRoom, &matRotate, &matTrans);
  378. }
  379. return hr;
  380. }
  381. HRESULT CTheRoom::_CreateLobbySign(void)
  382. {
  383. TCHAR szLine2[MAX_PATH];
  384. TCHAR szUsername[MAX_PATH];
  385. HRESULT hr = GetCurrentUserCustomName(szUsername, ARRAYSIZE(szUsername));
  386. LoadString(HINST_THISDLL, IDS_LOBBY_TITLE2, szLine2, ARRAYSIZE(szLine2));
  387. if (SUCCEEDED(hr))
  388. {
  389. // TODO:
  390. // 1. Create Sign backdrop. (Marble, wood?)
  391. // 2. Render Text. (D3DXCreateTextW, etc.)
  392. }
  393. return hr;
  394. }
  395. HRESULT CTheRoom::_CreateRoom(void)
  396. {
  397. // TODO: For Square room, layout differently
  398. HRESULT hr = S_OK;
  399. D3DXVECTOR3 vNormalWall1(0, 0, -1);
  400. D3DXVECTOR3 vNormalWall2(-1, 0, 0);
  401. D3DXVECTOR3 vNormalWall3(0, 0, 1);
  402. D3DXVECTOR3 vNormalWall4(1, 0, 0);
  403. D3DXVECTOR3 vNormalFloor(0, 1, 0);
  404. D3DXVECTOR3 vNormalCeiling(0, -1, 0);
  405. DWORD dwRugMaxPixelSize = ((3 * g_dwHeight) / 4);
  406. m_fCeiling = m_fToeGuard = m_fPaintings = m_fRug = m_fPower = m_fWalls = m_fFloor = TRUE;
  407. m_fCeiling = !g_fOverheadViewTest;
  408. // Locations
  409. float fYToeGuard = TOEGUARD_HEIGHT;
  410. // Rug
  411. float fScale = 1.0f;
  412. float fRugWidth = 40.0f;
  413. float fRugDepth = (fRugWidth * (m_pMain->GetGlobalTexture(ITEM_RUG, &fScale))->GetSurfaceRatio()); // This will cause one object to be above another.
  414. D3DXVECTOR3 vRugLoc(((g_fRoomWidthX - fRugWidth) / 2.0f), g_fFudge, ((g_fRoomDepthZ - fRugDepth) / 2.0f));
  415. D3DXVECTOR3 vRugSize(fRugWidth, 0, fRugDepth);
  416. // PowerSocket
  417. float fPowerWidth = 2.5f;
  418. float fPowerHeight = (fPowerWidth * (m_pMain->GetGlobalTexture(ITEM_POWEROUTLET, &fScale))->GetSurfaceRatio()); // This will cause one object to be above another.
  419. D3DXVECTOR3 vPowerLoc(((g_fRoomWidthX - fPowerWidth) / 2.0f), 5.00f, (g_fRoomDepthZ - g_fFudge));
  420. D3DXVECTOR3 vPowerSize(fPowerWidth, fPowerHeight, 0.0f);
  421. // Texture Coords
  422. CTexture * pTexture = m_pMain->GetGlobalTexture(ITEM_WALLPAPER, &fScale);
  423. float fTSWallpaperX = (TEXTURESCALE_WALLPAPER * fScale); // How many repeats per 1 unit.
  424. float fTSWallpaperY = fTSWallpaperX * pTexture->GetSurfaceRatio();
  425. CTexture * pFloorTexture = m_pMain->GetGlobalTexture(ITEM_FLOOR, &fScale);
  426. float fTSFloorX = (TEXTURESCALE_FLOOR * fScale); // How many repeats per 1 unit.
  427. float fTSFloorY = fTSFloorX * pFloorTexture->GetSurfaceRatio();
  428. CTexture * pToeGuardTexture = m_pMain->GetGlobalTexture(ITEM_TOEGUARD, &fScale);
  429. float fTSToeGuardX = (TEXTURESCALE_TOEGUARD * fScale); // How many repeats per 1 unit.
  430. float fTSToeGuardY = fTSToeGuardX * pToeGuardTexture->GetSurfaceRatio();
  431. CTexture * pCeilingTexture = m_pMain->GetGlobalTexture(ITEM_CEILING, &fScale);
  432. float fTSCeilingX = (TEXTURESCALE_CEILING * fScale); // How many repeats per 1 unit.
  433. float fTSCeilingY = fTSCeilingX * pCeilingTexture->GetSurfaceRatio();
  434. // Draw Floor
  435. D3DXVECTOR3 vLocation(0.00f, 0.00f, 0.00f);
  436. D3DXVECTOR3 vSize(g_fRoomWidthX, 0.00f, g_fRoomDepthZ);
  437. hr = m_objFloor.InitPlane(pFloorTexture, m_pMain->GetD3DDevice(), vLocation, vSize, vNormalFloor, 2, 2, fTSFloorY, fTSFloorX, 0, 10);
  438. // Draw Wall 1 (Facing Wall)
  439. vLocation = D3DXVECTOR3(0.00f, 0.00f, g_fRoomDepthZ);
  440. vSize = D3DXVECTOR3(g_fRoomWidthX, g_fRoomHeightY, 0.00f);
  441. hr = m_objWall1.InitPlane(pTexture, m_pMain->GetD3DDevice(), vLocation, vSize, vNormalWall1, 2, 2, fTSWallpaperX, fTSWallpaperY, 0, 10);
  442. // Draw ToeGuard 1
  443. vLocation = D3DXVECTOR3(0.00f, 0.00f, g_fRoomDepthZ-g_fFudge);
  444. vSize = D3DXVECTOR3(g_fRoomWidthX, fYToeGuard, 0.00f);
  445. hr = m_objToeGuard1.InitPlane(pToeGuardTexture, m_pMain->GetD3DDevice(), vLocation, vSize, vNormalWall1, 2, 2, fTSToeGuardY, fTSToeGuardX, 0, 0);
  446. // Draw Wall 2 (Right wall)
  447. vLocation = D3DXVECTOR3(g_fRoomWidthX, 0.00f, 0.00f);
  448. hr = _AddWall((NULL != m_pRightRoom), vLocation, D3DXVECTOR3(0.0f, 0.0f, 1.0f), D3DXVECTOR3(0.0f, 1.0f, 0.0f), vNormalWall2, g_fRoomHeightY,
  449. DOOR_HEIGHT, g_fRoomDepthZ, DOOR_WIDTH, WALL_WIDTHBEFOREDOOR);
  450. // Draw Wall 3 (Back Wall)
  451. vLocation = D3DXVECTOR3(0.00f, 0.00f, 0.00f);
  452. hr = _AddWall(FALSE, vLocation, D3DXVECTOR3(1.0f, 0.0f, 0.0f), D3DXVECTOR3(0.0f, 1.0f, 0.0f), vNormalWall3, g_fRoomHeightY,
  453. DOOR_HEIGHT, g_fRoomWidthX, DOOR_WIDTH, ((g_fRoomWidthX - DOOR_WIDTH) / 2.0f));
  454. // Draw Wall 4 (Left Wall)
  455. vLocation = D3DXVECTOR3(0.00f, 0.00f, 0.00f);
  456. hr = _AddWall((NULL != m_pLeftRoom), vLocation, D3DXVECTOR3(0.0f, 0.0f, 1.0f), D3DXVECTOR3(0.0f, 1.0f, 0.0f), vNormalWall4, g_fRoomHeightY,
  457. DOOR_HEIGHT, g_fRoomDepthZ, DOOR_WIDTH, WALL_WIDTHBEFOREDOOR);
  458. // Draw Ceiling
  459. vLocation = D3DXVECTOR3(0.00f, g_fRoomHeightY, 0.00f);
  460. vSize = D3DXVECTOR3(g_fRoomWidthX, 0.00f, g_fRoomDepthZ);
  461. hr = m_objCeiling.InitPlane(pCeilingTexture, m_pMain->GetD3DDevice(), vLocation, vSize, vNormalCeiling, 2, 2, fTSCeilingY, fTSCeilingX, 0, 10);
  462. // Room Items (Rug, Power Sockets, Benches)
  463. hr = m_theRug.InitPlaneStretch(m_pMain->GetGlobalTexture(ITEM_RUG, &fScale), m_pMain->GetD3DDevice(), vRugLoc, vRugSize, vNormalFloor, 2, 2, dwRugMaxPixelSize);
  464. if (m_fLobby)
  465. {
  466. hr = _CreateLobbySign();
  467. }
  468. else
  469. {
  470. // We don't want a powerplug in the lobby.
  471. hr = m_thePowerSocket.InitPlaneStretch(m_pMain->GetGlobalTexture(ITEM_POWEROUTLET, &fScale), m_pMain->GetD3DDevice(), vPowerLoc, vPowerSize, vNormalWall1, 2, 2, 0);
  472. }
  473. hr = _SetRotationMatrix();
  474. m_fWalls = TRUE;
  475. return hr;
  476. }
  477. //-----------------------------------------------------------------------------
  478. // Name: OneTimeSceneInit()
  479. // Desc: Called during initial app startup, this function performs all the
  480. // permanent initialization.
  481. //-----------------------------------------------------------------------------
  482. HRESULT CTheRoom::OneTimeSceneInit(int nFutureRooms, BOOL fLowPriority)
  483. {
  484. HRESULT hr = S_OK;
  485. m_fLowPriority = fLowPriority;
  486. if (!m_fRoomCreated)
  487. {
  488. // assert(!m_pFirstRoom); // This will cause a leak
  489. // ASSERT(!m_pLeftRoom); //, TEXT("This will cause a leak"));
  490. // ASSERT(!m_pRightRoom); // , TEXT("This will cause a leak"));
  491. if (m_pFloorPlan->nEnterDoor == 0)
  492. {
  493. IUnknown_Set((IUnknown **) &m_pFirstRoom, m_pEnterRoom);
  494. }
  495. else
  496. {
  497. if (m_pFloorPlan->fDoor0)
  498. {
  499. m_pFirstRoom = new CTheRoom(FALSE, m_pMain, this, m_nBatch+1);
  500. if (!m_pFirstRoom)
  501. {
  502. hr = E_OUTOFMEMORY;
  503. }
  504. }
  505. }
  506. if (m_pFloorPlan->nEnterDoor == 1)
  507. {
  508. IUnknown_Set((IUnknown **) &m_pLeftRoom, m_pEnterRoom);
  509. }
  510. else
  511. {
  512. if (m_pFloorPlan->fDoor1)
  513. {
  514. m_pLeftRoom = new CTheRoom(FALSE, m_pMain, this, m_nBatch+1);
  515. if (!m_pLeftRoom)
  516. {
  517. hr = E_OUTOFMEMORY;
  518. }
  519. }
  520. }
  521. if (m_pFloorPlan->nEnterDoor == 2)
  522. {
  523. IUnknown_Set((IUnknown **) &m_pRightRoom, m_pEnterRoom);
  524. }
  525. else
  526. {
  527. if (m_pFloorPlan->fDoor2)
  528. {
  529. m_pRightRoom = new CTheRoom(FALSE, m_pMain, this, m_nBatch+1);
  530. if (!m_pRightRoom)
  531. {
  532. hr = E_OUTOFMEMORY;
  533. }
  534. }
  535. }
  536. if (SUCCEEDED(hr) &&
  537. (m_pFirstRoom || m_pLeftRoom || m_pRightRoom))
  538. {
  539. hr = _CreateRoom();
  540. if (!m_fLobby && !g_fFirstFrame)
  541. {
  542. _InitPaintings();
  543. }
  544. if (SUCCEEDED(hr))
  545. {
  546. m_fVisible = TRUE; // We have children to render.
  547. m_fRoomCreated = TRUE;
  548. }
  549. }
  550. else
  551. {
  552. hr = E_OUTOFMEMORY;
  553. }
  554. }
  555. if (SUCCEEDED(hr) && (nFutureRooms > 0))
  556. {
  557. if (m_pLeftRoom)
  558. {
  559. hr = m_pLeftRoom->OneTimeSceneInit(nFutureRooms-1, FALSE);
  560. }
  561. if (SUCCEEDED(hr) && m_pRightRoom)
  562. {
  563. hr = m_pRightRoom->OneTimeSceneInit(nFutureRooms-1, FALSE);
  564. } // TODO: Need first room?
  565. }
  566. return hr;
  567. }
  568. HRESULT CTheRoom::FreePictures(int nMaxBatch)
  569. {
  570. HRESULT hr = S_OK;
  571. if (-1 == nMaxBatch)
  572. {
  573. nMaxBatch = m_nBatch;
  574. }
  575. if (nMaxBatch >= m_nBatch)
  576. {
  577. if (g_pPictureMgr)
  578. {
  579. g_pPictureMgr->ReleaseBatch(m_nBatch);
  580. m_nBatch = 0;
  581. }
  582. // Free our paintings
  583. for (int nIndex = 0; (nIndex < ARRAYSIZE(m_pPaintings)); nIndex++)
  584. {
  585. SAFE_DELETE(m_pPaintings[nIndex]);
  586. }
  587. if (m_pFloorPlan)
  588. {
  589. if (m_pFirstRoom && (m_pFirstRoom != m_pEnterRoom) &&
  590. (!m_fCurrentRoom || (0 != m_pFloorPlan->nExitDoor)))
  591. {
  592. hr = m_pFirstRoom->FreePictures(nMaxBatch);
  593. }
  594. if (m_pLeftRoom && (m_pLeftRoom != m_pEnterRoom) &&
  595. (!m_fCurrentRoom || (1 != m_pFloorPlan->nExitDoor)))
  596. {
  597. hr = m_pLeftRoom->FreePictures(nMaxBatch);
  598. }
  599. if (m_pRightRoom && (m_pRightRoom != m_pEnterRoom) &&
  600. (!m_fCurrentRoom || (2 != m_pFloorPlan->nExitDoor)))
  601. {
  602. hr = m_pRightRoom->FreePictures(nMaxBatch);
  603. }
  604. }
  605. }
  606. return hr;
  607. }
  608. HRESULT CTheRoom::SetCurrent(BOOL fCurrent)
  609. {
  610. HRESULT hr = S_OK;
  611. m_fCurrentRoom = fCurrent;
  612. if (fCurrent)
  613. {
  614. if (m_pFirstRoom)
  615. {
  616. hr = m_pFirstRoom->OneTimeSceneInit(1, TRUE);
  617. }
  618. if (m_pLeftRoom)
  619. {
  620. hr = m_pLeftRoom->OneTimeSceneInit(1, TRUE);
  621. }
  622. if (m_pRightRoom)
  623. {
  624. hr = m_pRightRoom->OneTimeSceneInit(1, TRUE);
  625. }
  626. m_fVisible = TRUE;
  627. }
  628. else
  629. {
  630. }
  631. return hr;
  632. }
  633. HRESULT CTheRoom::GetNextRoom(CTheRoom ** ppNextRoom)
  634. {
  635. // This function does two things:
  636. // 1. Gives the caller a pointer to our next room, and
  637. // 2. Changes the order so we free rooms we will no longer need.
  638. // We want to take this opportunity to free our other rooms in case we come back into this room.
  639. // TODO: Regen other rooms. Use Ref-counting with SetSite(NULL) in order to track memory correctly.
  640. // We would need to re-generate m_pFloorPlan that has the same enter door as our exit door
  641. // with the same floor plan if we want to walk into previous rooms.
  642. switch (m_pFloorPlan->nExitDoor)
  643. {
  644. case 0: // Enter door
  645. IUnknown_Set((IUnknown **) ppNextRoom, m_pFirstRoom);
  646. IUnknown_Set((IUnknown **) &m_pEnterRoom, m_pFirstRoom);
  647. break;
  648. case 1: // Left door
  649. IUnknown_Set((IUnknown **) ppNextRoom, m_pLeftRoom);
  650. IUnknown_Set((IUnknown **) &m_pEnterRoom, m_pLeftRoom);
  651. break;
  652. case 2: // Right door
  653. IUnknown_Set((IUnknown **) ppNextRoom, m_pRightRoom);
  654. IUnknown_Set((IUnknown **) &m_pEnterRoom, m_pRightRoom);
  655. break;
  656. };
  657. BOOL fReEnter = ((ppNextRoom && *ppNextRoom) ? ((*ppNextRoom)->GetEnterDoor() == (*ppNextRoom)->GetExitDoor()) : FALSE);
  658. if (m_pFirstRoom != m_pEnterRoom)
  659. {
  660. if (m_pFirstRoom) m_pFirstRoom->FinalCleanup();
  661. SAFE_RELEASE(m_pFirstRoom);
  662. if (fReEnter)
  663. {
  664. m_pFirstRoom = new CTheRoom(FALSE, m_pMain, this, m_nBatch+1);
  665. }
  666. }
  667. if (m_pLeftRoom != m_pEnterRoom)
  668. {
  669. if (m_pLeftRoom) m_pLeftRoom->FinalCleanup();
  670. SAFE_RELEASE(m_pLeftRoom);
  671. if (fReEnter)
  672. {
  673. m_pLeftRoom = new CTheRoom(FALSE, m_pMain, this, m_nBatch+1);
  674. }
  675. }
  676. if (m_pRightRoom != m_pEnterRoom)
  677. {
  678. if (m_pRightRoom) m_pRightRoom->FinalCleanup();
  679. SAFE_RELEASE(m_pRightRoom);
  680. if (fReEnter)
  681. {
  682. m_pRightRoom = new CTheRoom(FALSE, m_pMain, this, m_nBatch+1);
  683. }
  684. }
  685. return (*ppNextRoom ? S_OK : E_FAIL);
  686. }
  687. //-----------------------------------------------------------------------------
  688. // Name: FinalCleanup()
  689. // Desc: Called before the app exits, this function gives the app the chance
  690. // to cleanup after itself.
  691. //-----------------------------------------------------------------------------
  692. HRESULT CTheRoom::FinalCleanup(void)
  693. {
  694. // This is where we break all the circular ref-counts
  695. if (m_pFirstRoom && (m_pEnterRoom != m_pFirstRoom)) m_pFirstRoom->FinalCleanup();
  696. if (m_pLeftRoom && (m_pEnterRoom != m_pLeftRoom)) m_pLeftRoom->FinalCleanup();
  697. if (m_pRightRoom && (m_pEnterRoom != m_pRightRoom)) m_pRightRoom->FinalCleanup();
  698. SAFE_RELEASE(m_pEnterRoom);
  699. SAFE_RELEASE(m_pFirstRoom);
  700. SAFE_RELEASE(m_pLeftRoom);
  701. SAFE_RELEASE(m_pRightRoom);
  702. m_theRug.FinalCleanup();
  703. m_thePowerSocket.FinalCleanup();
  704. return S_OK;
  705. }
  706. //-----------------------------------------------------------------------------
  707. // Name: DeleteDeviceObjects()
  708. // Desc: Called when the app is exitting, or the device is being changed,
  709. // this function deletes any device dependant objects.
  710. //-----------------------------------------------------------------------------
  711. HRESULT CTheRoom::DeleteDeviceObjects(void)
  712. {
  713. m_theRug.DeleteDeviceObjects();
  714. m_thePowerSocket.DeleteDeviceObjects();
  715. return S_OK;
  716. }
  717. #define ABS(i) (((i) < 0) ? -(i) : (i))
  718. HRESULT CTheRoom::_RenderThisRoom(IDirect3DDevice8 * pD3DDevice, int nRenderPhase, BOOL fFrontToBack)
  719. {
  720. HRESULT hr = S_OK;
  721. DWORD dwTesting = 0;
  722. switch (nRenderPhase)
  723. {
  724. case 0: // Wallpaper
  725. if (m_fWalls)
  726. {
  727. hr = m_objWall1.Render(pD3DDevice);
  728. }
  729. break;
  730. case 1:
  731. if (m_fFloor)
  732. {
  733. hr = m_objFloor.Render(pD3DDevice);
  734. }
  735. break;
  736. case 2:
  737. if (m_fToeGuard)
  738. {
  739. // pD3DDevice->SetRenderState(D3DRS_ZBIAS, 12); // Force the ToeGuard to appear above the wallpaper.
  740. hr = m_objToeGuard1.Render(pD3DDevice);
  741. }
  742. break;
  743. case 3: // Frames
  744. case 4: // Pictures. (Here's where we blow the cache)
  745. if (m_fPaintings)
  746. {
  747. if (m_fLobby)
  748. {
  749. // TODO: Paint lobby sign. (user name) Anything created in _CreateLobbySign().
  750. }
  751. else
  752. {
  753. // pD3DDevice->SetRenderState(D3DRS_ZBIAS, 13);
  754. if (!m_pPaintings[0] && m_fVisible && !g_fFirstFrame) // Did the background thread not yet have any pictures for us?
  755. {
  756. hr = _InitPaintings(); // If so, see if they have anything yet?
  757. }
  758. for (int nIndex = ARRAYSIZE(m_pPaintings)-1; m_fVisible && (nIndex >= 0); nIndex--)
  759. {
  760. if (m_pPaintings[nIndex]) // May be NULL if out of memory or in lobby.
  761. {
  762. // We use fFrontToBack because we always want to render the frame first. This way
  763. // the painting is always painted on top. We don't worry about blowing the texture
  764. // cache on the video card because since we will render so many paintings and change
  765. // the paintings we render so often, the cache will almost be certainly blown anyway.
  766. // We always want 0 rendered first.
  767. if (fFrontToBack)
  768. {
  769. m_pPaintings[nIndex]->Render(pD3DDevice, nRenderPhase-3);
  770. }
  771. else
  772. {
  773. m_pPaintings[nIndex]->Render(pD3DDevice, ((4 == nRenderPhase) ? 0 : 1));
  774. }
  775. }
  776. }
  777. }
  778. }
  779. break;
  780. case 5:
  781. if (m_fPower)
  782. {
  783. // pD3DDevice->SetRenderState(D3DRS_ZBIAS, 11);
  784. m_thePowerSocket.Render(pD3DDevice);
  785. }
  786. break;
  787. case 6:
  788. if (m_fRug)
  789. {
  790. // pD3DDevice->SetRenderState(D3DRS_ZBIAS, 10);
  791. m_theRug.Render(pD3DDevice);
  792. }
  793. break;
  794. case 7:
  795. if (m_fCeiling)
  796. {
  797. hr = m_objCeiling.Render(pD3DDevice);
  798. }
  799. break;
  800. }
  801. return hr;
  802. }
  803. //#define COLOR_DOORFRAME_GRAY D3DXCOLOR(0.78f, 0.78f, 0.78f, 1.0f)
  804. #define COLOR_DOORFRAME_GRAY D3DXCOLOR(0.28f, 0.28f, 0.28f, 1.0f)
  805. BOOL CTheRoom::_IsRoomVisible(IDirect3DDevice8 * pD3DDevice, int nRoomNumber)
  806. {
  807. D3DXVECTOR3 vMin;
  808. D3DXVECTOR3 vMax;
  809. D3DXMATRIX matWorld;
  810. pD3DDevice->GetTransform(D3DTS_WORLD, &matWorld);
  811. switch (nRoomNumber)
  812. {
  813. case 0: // First Door.
  814. return FALSE; // we never look back at the first door
  815. case 1: // Left Door.
  816. vMin = D3DXVECTOR3( 0, 0, WALL_WIDTHBEFOREDOOR );
  817. vMax = D3DXVECTOR3( 0, DOOR_HEIGHT, WALL_WIDTHBEFOREDOOR + DOOR_WIDTH );
  818. return Is3DRectViewable( m_pMain->PCullInfo(), &matWorld, vMin, vMax );
  819. case 2: // Right Door
  820. vMin = D3DXVECTOR3( g_fRoomWidthX, 0, WALL_WIDTHBEFOREDOOR );
  821. vMax = D3DXVECTOR3( g_fRoomWidthX, DOOR_HEIGHT, WALL_WIDTHBEFOREDOOR + DOOR_WIDTH );
  822. return Is3DRectViewable( m_pMain->PCullInfo(), &matWorld, vMin, vMax );
  823. default:
  824. return FALSE;
  825. }
  826. }
  827. //-----------------------------------------------------------------------------
  828. // Name: Render()
  829. // Desc: Called once per frame, the call is the entry point for 3d
  830. // rendering. This function sets up render states, clears the
  831. // viewport, and renders the scene.
  832. //-----------------------------------------------------------------------------
  833. HRESULT CTheRoom::Render(IDirect3DDevice8 * pD3DDevice, int nRenderPhase, BOOL fFrontToBack)
  834. {
  835. HRESULT hr;
  836. DWORD dwTesting = 0;
  837. // Draw the obstacles
  838. D3DMATERIAL8 mtrl = {0};
  839. mtrl.Ambient.r = mtrl.Specular.r = mtrl.Diffuse.r = 1.0f;
  840. mtrl.Ambient.g = mtrl.Specular.g = mtrl.Diffuse.g = 1.0f;
  841. mtrl.Ambient.b = mtrl.Specular.b = mtrl.Diffuse.b = 1.0f;
  842. mtrl.Ambient.a = mtrl.Specular.a = mtrl.Diffuse.a = 1.0f;
  843. if (m_fCurrentRoom)
  844. {
  845. // DXUtil_Trace(TEXT("ROOM: m_nExitDoor=%d, m_pLeftRoom=%d, m_pRightRoom=%d\n"), m_pFloorPlan->nExitDoor, m_pLeftRoom, m_pRightRoom);
  846. }
  847. hr = pD3DDevice->SetMaterial(&mtrl);
  848. if (SUCCEEDED(hr) && m_fVisible && (m_pEnterRoom || m_pLeftRoom || m_pRightRoom))
  849. {
  850. // We really want to do hit testing here otherwise we are really wasting our time.
  851. D3DXMATRIX matPrevious;
  852. D3DXMATRIX matNext;
  853. hr = pD3DDevice->GetTransform(D3DTS_WORLD, &matPrevious);
  854. if (m_pEnterRoom && _IsRoomVisible(pD3DDevice, 0) &&
  855. (m_pEnterRoom != m_pFirstRoom))
  856. {
  857. D3DXMatrixMultiply(&matNext, &m_matFirstRoom, &matPrevious);
  858. hr = pD3DDevice->SetTransform(D3DTS_WORLD, &matNext);
  859. hr = m_pFirstRoom->Render(pD3DDevice, nRenderPhase, fFrontToBack);
  860. hr = pD3DDevice->SetTransform(D3DTS_WORLD, &matPrevious);
  861. }
  862. if (m_pLeftRoom && _IsRoomVisible(pD3DDevice, 1) &&
  863. (m_pEnterRoom != m_pLeftRoom))
  864. {
  865. D3DXMatrixMultiply(&matNext, &m_matLeftRoom, &matPrevious);
  866. hr = pD3DDevice->SetTransform(D3DTS_WORLD, &matNext);
  867. hr = m_pLeftRoom->Render(pD3DDevice, nRenderPhase, fFrontToBack);
  868. hr = pD3DDevice->SetTransform(D3DTS_WORLD, &matPrevious);
  869. }
  870. if (m_pRightRoom && _IsRoomVisible(pD3DDevice, 2) &&
  871. (m_pEnterRoom != m_pRightRoom))
  872. {
  873. D3DXMatrixMultiply(&matNext, &m_matRightRoom, &matPrevious);
  874. hr = pD3DDevice->SetTransform(D3DTS_WORLD, &matNext);
  875. hr = m_pRightRoom->Render(pD3DDevice, nRenderPhase, fFrontToBack);
  876. hr = pD3DDevice->SetTransform(D3DTS_WORLD, &matPrevious);
  877. }
  878. }
  879. hr = _RenderThisRoom(pD3DDevice, nRenderPhase, fFrontToBack);
  880. return hr;
  881. }
  882. #define DIST_TO_WALL_ON_ZOOM 10.0f
  883. HRESULT CTheRoom::_AddPaintingToPaintingMovements(CCameraMove * ptheCamera, D3DXVECTOR3 vSourceLocIn, D3DXVECTOR3 vSourceTangentIn,
  884. D3DXVECTOR3 vPainting, D3DXVECTOR3 * pvDestDir, float fDest, D3DXVECTOR3 * pvDestTangent,
  885. int nBatch)
  886. {
  887. HRESULT hr = S_OK;
  888. float fDistToWall = 30.0f;
  889. float fZoomDistToWall = DIST_TO_WALL_ON_ZOOM;
  890. float fZoomDelta = (fDistToWall - fZoomDistToWall);
  891. BOOL fExitLeft = ((1 == m_pFloorPlan->nExitDoor) ? TRUE : FALSE);
  892. D3DXVECTOR3 vSourceLoc = vSourceLocIn;
  893. D3DXVECTOR3 vSourceTangent = vSourceTangentIn;
  894. D3DXVECTOR3 vDestLoc;
  895. D3DXVECTOR3 vDestTangent;
  896. // Move closer to the first painting so it's full screen
  897. vDestLoc = (vSourceLoc + (vPainting * fZoomDelta));
  898. vDestTangent = vSourceTangent;
  899. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  900. // Look at painting #1
  901. hr = ptheCamera->CreateNextWait(m_nBatch+3, nBatch);
  902. // Back up some and start moving to the next painting.
  903. vSourceLoc = vDestLoc;
  904. vSourceTangent = vDestTangent;
  905. vDestLoc = (vSourceLocIn + (*pvDestDir * (fDest * 0.5f)));
  906. vDestTangent = (*pvDestDir * fDest);
  907. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  908. // Now walk much closer to the next painting
  909. vSourceLoc = vDestLoc;
  910. vSourceTangent = vDestTangent;
  911. vDestLoc = (vSourceLocIn + (*pvDestDir * (fDest * 0.90f)));
  912. vDestTangent = vSourceTangent;
  913. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  914. // Now move close to the painting
  915. vSourceLoc = vDestLoc;
  916. vSourceTangent = vDestTangent;
  917. vDestLoc = (vSourceLocIn + (vPainting * fZoomDelta) + (*pvDestDir * fDest));
  918. vDestTangent = (vPainting * 5.0f) * 1000.0f;
  919. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  920. // Look at painting #2
  921. hr = ptheCamera->CreateNextWait(m_nBatch+3, nBatch);
  922. vSourceLoc = vDestLoc;
  923. vSourceTangent = vDestTangent = vPainting;
  924. vDestLoc = (vSourceLocIn + (*pvDestDir * fDest));
  925. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  926. *pvDestDir = vDestLoc;
  927. *pvDestTangent = vDestTangent;
  928. return hr;
  929. }
  930. HRESULT CTheRoom::_LongRoomEnterDoorMovements(CCameraMove * ptheCamera)
  931. {
  932. HRESULT hr = S_OK;
  933. float fDistant = 5.0f;
  934. float fDistToWall = 30.0f;
  935. float fWalkHeight = 20.0f;
  936. D3DXVECTOR3 vSourceLoc((g_fRoomWidthX / 2.0f), fWalkHeight, 1.0f);
  937. D3DXVECTOR3 vSourceTangent(0.0f, 0.0f, fDistant);
  938. hr = ptheCamera->Init(vSourceLoc, vSourceTangent, D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  939. if (SUCCEEDED(hr))
  940. {
  941. BOOL fExitLeft = ((1 == m_pFloorPlan->nExitDoor) ? TRUE : FALSE);
  942. // fExitLeft 1=Left
  943. D3DXVECTOR3 vDestLoc((fExitLeft ? fDistToWall : g_fRoomWidthX-fDistToWall), fWalkHeight, (g_fRoomDepthZ * (1.0f / 4.0f)));
  944. D3DXVECTOR3 vDestTangent((fExitLeft ? -fDistant : fDistant), 0.0f, 0.0f);
  945. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  946. vSourceLoc = vDestLoc;
  947. vSourceTangent = vDestTangent;
  948. vDestLoc = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
  949. hr = _AddPaintingToPaintingMovements(ptheCamera, vSourceLoc, vSourceTangent, D3DXVECTOR3((fExitLeft ? -1.0f : 1.0f), 0.0f, 0.0f),
  950. &vDestLoc, (g_fRoomDepthZ * (1.0f / 4.0f)), &vDestTangent, 2);
  951. vSourceLoc = vDestLoc;
  952. vSourceTangent = vDestTangent;
  953. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, fDistant);
  954. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  955. vSourceTangent = vDestTangent;
  956. vDestTangent = D3DXVECTOR3((fExitLeft ? fDistant : -fDistant), 0.0f, 0.0f);
  957. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  958. vSourceTangent = vDestTangent;
  959. vDestLoc = D3DXVECTOR3((fExitLeft ? g_fRoomWidthX-fDistToWall : fDistToWall), fWalkHeight, (g_fRoomDepthZ * (2.0f / 4.0f)));
  960. vDestTangent = vSourceTangent;
  961. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  962. // If we removed this door, then let us look at the painting that took it's place.
  963. if (!m_pLeftRoom || !m_pRightRoom)
  964. {
  965. vSourceLoc = vDestLoc;
  966. vSourceTangent = vDestTangent;
  967. vDestLoc = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
  968. hr = _AddPaintingToPaintingMovements(ptheCamera, vSourceLoc, vSourceTangent, D3DXVECTOR3((fExitLeft ? 1.0f : -1.0f), 0.0f, 0.0f),
  969. &vDestLoc, (g_fRoomDepthZ * (1.0f / 4.0f)), &vDestTangent, 1);
  970. }
  971. else
  972. {
  973. vSourceLoc = vDestLoc;
  974. vSourceTangent = vDestTangent;
  975. vDestLoc = D3DXVECTOR3((fExitLeft ? g_fRoomWidthX-DIST_TO_WALL_ON_ZOOM : DIST_TO_WALL_ON_ZOOM), fWalkHeight, (g_fRoomDepthZ * (2.0f / 4.0f)));
  976. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  977. // Look at painting #3
  978. hr = ptheCamera->CreateNextWait(m_nBatch+3, 1);
  979. vSourceLoc = vDestLoc;
  980. vSourceTangent = vDestTangent;
  981. vDestTangent = D3DXVECTOR3((fExitLeft ? fDistant : -fDistant), 0.0f, fDistant);
  982. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  983. }
  984. // Now, walk from this painting close up to the location of the next painting
  985. vSourceLoc = vDestLoc;
  986. vSourceTangent = vDestTangent;
  987. vDestLoc = D3DXVECTOR3((fExitLeft ? 2.0f : 1.0f) * (g_fRoomWidthX/3.0f), fWalkHeight, (g_fRoomDepthZ - fDistToWall));
  988. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, fDistant);
  989. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  990. vSourceLoc = vDestLoc;
  991. vSourceTangent = vDestTangent;
  992. vDestLoc = D3DXVECTOR3((fExitLeft ? -1.0f : 1.0f), 0.0f, 0.0f);
  993. hr = _AddPaintingToPaintingMovements(ptheCamera, vSourceLoc, vSourceTangent, D3DXVECTOR3(0.0f, 0.0f, 1.0f),
  994. &vDestLoc, (g_fRoomWidthX * (1.0f / 3.0f)), &vDestTangent, 1);
  995. // Turn toward the door while walking.
  996. vSourceLoc = vDestLoc;
  997. vSourceTangent = D3DXVECTOR3(0.0f, 0.0f, fDistant);
  998. vDestLoc = D3DXVECTOR3((fExitLeft ? 0.0f : g_fRoomWidthX), fWalkHeight, (WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f)));
  999. vDestTangent = D3DXVECTOR3((fExitLeft ? -fDistant : fDistant), 0.0f, 0.0f);
  1000. #define TURN_RATE 0.30f
  1001. D3DXVECTOR3 vTemp;
  1002. D3DXVec3Lerp(&vTemp, &vSourceLoc, &vDestLoc, TURN_RATE); // We want to do our turn towards the door while walking. We do it while walking 10% towards the door.
  1003. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vTemp, vDestTangent);
  1004. vSourceLoc = vTemp;
  1005. // Finish walking to and thru the exit door.
  1006. vSourceTangent = vDestTangent;
  1007. vDestLoc = D3DXVECTOR3((fExitLeft ? 0.0f : g_fRoomWidthX), fWalkHeight, (WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f)));
  1008. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1009. }
  1010. return hr;
  1011. }
  1012. HRESULT CTheRoom::_LongRoomSideEnterLeaveMovements(CCameraMove * ptheCamera)
  1013. {
  1014. HRESULT hr = S_OK;
  1015. BOOL fExitLeft = ((1 == m_pFloorPlan->nExitDoor) ? TRUE : FALSE);
  1016. float fDistant = 5.0f;
  1017. float fDistToWall = 30.0f;
  1018. float fWalkHeight = 20.0f;
  1019. D3DXVECTOR3 vSourceLoc((fExitLeft ? g_fRoomWidthX : 0.0f), fWalkHeight, (WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f)));
  1020. D3DXVECTOR3 vSourceTangent((fExitLeft ? -fDistant : fDistant), 0.0f, 0.0f);
  1021. hr = ptheCamera->Init(vSourceLoc, vSourceTangent, D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  1022. if (SUCCEEDED(hr))
  1023. {
  1024. BOOL fExitLeft = ((1 == m_pFloorPlan->nExitDoor) ? TRUE : FALSE);
  1025. // fExitLeft 1=Left
  1026. D3DXVECTOR3 vDestLoc((fExitLeft ? g_fRoomWidthX-fDistToWall : fDistToWall), fWalkHeight, (WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f)));
  1027. D3DXVECTOR3 vDestTangent((fExitLeft ? -fDistant : fDistant), 0.0f, 0.0f);
  1028. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1029. vSourceLoc = vDestLoc;
  1030. vSourceTangent = vDestTangent;
  1031. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, -fDistant);
  1032. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1033. vSourceTangent = vDestTangent;
  1034. vDestLoc = D3DXVECTOR3((fExitLeft ? g_fRoomWidthX-fDistToWall : fDistToWall), fWalkHeight, (g_fRoomDepthZ * (3.0f / 4.0f)));
  1035. vDestTangent = vSourceTangent;
  1036. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1037. vSourceLoc = vDestLoc;
  1038. vSourceTangent = vDestTangent;
  1039. vDestTangent = D3DXVECTOR3((fExitLeft ? fDistant : -fDistant), 0.0f, 0.0f);
  1040. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1041. // Look at painting #1
  1042. hr = ptheCamera->CreateNextWait(m_nBatch+3, 2);
  1043. vSourceLoc = vDestLoc;
  1044. vSourceTangent = vDestTangent;
  1045. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, -fDistant);
  1046. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1047. vSourceTangent = vDestTangent;
  1048. vDestLoc = D3DXVECTOR3((fExitLeft ? g_fRoomWidthX-fDistToWall : fDistToWall), fWalkHeight, (g_fRoomDepthZ * (2.0f / 4.0f)));
  1049. vDestTangent = vSourceTangent;
  1050. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1051. vSourceLoc = vDestLoc;
  1052. vSourceTangent = vDestTangent;
  1053. vDestTangent = D3DXVECTOR3((fExitLeft ? fDistant : -fDistant), 0.0f, 0.0f);
  1054. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1055. // Look at painting #2
  1056. hr = ptheCamera->CreateNextWait(m_nBatch+3, 2);
  1057. vSourceLoc = vDestLoc;
  1058. vSourceTangent = vDestTangent;
  1059. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, -fDistant);
  1060. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1061. vSourceTangent = vDestTangent;
  1062. vDestLoc = D3DXVECTOR3((fExitLeft ? g_fRoomWidthX-fDistToWall : fDistToWall), fWalkHeight, (g_fRoomDepthZ * (1.0f / 4.0f)));
  1063. vDestTangent = vSourceTangent;
  1064. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1065. vSourceLoc = vDestLoc;
  1066. vSourceTangent = vDestTangent;
  1067. vDestTangent = D3DXVECTOR3((fExitLeft ? fDistant : -fDistant), 0.0f, 0.0f);
  1068. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1069. // Look at painting #3
  1070. hr = ptheCamera->CreateNextWait(m_nBatch+3, 1);
  1071. // Now do the 180 degree turn around
  1072. vSourceLoc = vDestLoc;
  1073. vSourceTangent = vDestTangent;
  1074. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, (GetRandomInt(0, 1) ? -fDistant : fDistant));
  1075. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1076. vSourceTangent = vDestTangent;
  1077. vDestTangent = D3DXVECTOR3((fExitLeft ? -fDistant : fDistant), 0.0f, 0.0f);
  1078. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1079. vSourceLoc = vDestLoc;
  1080. vSourceTangent = vDestTangent;
  1081. vDestLoc = D3DXVECTOR3((fExitLeft ? fDistToWall : g_fRoomWidthX-fDistToWall), fWalkHeight, (g_fRoomDepthZ * (1.0f / 4.0f)));
  1082. vDestTangent = vSourceTangent;
  1083. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1084. // Look at painting #4 (Front Wall #1)
  1085. hr = ptheCamera->CreateNextWait(m_nBatch+3, 1);
  1086. vSourceLoc = vDestLoc;
  1087. vSourceTangent = vDestTangent;
  1088. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, fDistant);
  1089. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1090. vSourceTangent = vDestTangent;
  1091. vDestLoc = D3DXVECTOR3((fExitLeft ? fDistToWall : g_fRoomWidthX-fDistToWall), fWalkHeight, (g_fRoomDepthZ * (2.0f / 4.0f)));
  1092. vDestTangent = vSourceTangent;
  1093. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1094. vSourceLoc = vDestLoc;
  1095. vSourceTangent = vDestTangent;
  1096. vDestTangent = D3DXVECTOR3((fExitLeft ? -fDistant : fDistant), 0.0f, 0.0f);
  1097. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1098. // Look at painting #5 (Front Wall #2)
  1099. hr = ptheCamera->CreateNextWait(m_nBatch+3, 1);
  1100. vSourceLoc = vDestLoc;
  1101. vSourceTangent = vDestTangent;
  1102. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, fDistant);
  1103. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1104. vSourceTangent = vDestTangent;
  1105. vDestLoc = D3DXVECTOR3((fExitLeft ? fDistToWall : g_fRoomWidthX-fDistToWall), fWalkHeight, (g_fRoomDepthZ * (3.0f / 4.0f)));
  1106. vDestTangent = vSourceTangent;
  1107. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1108. vSourceLoc = vDestLoc;
  1109. vSourceTangent = vDestTangent;
  1110. vDestTangent = D3DXVECTOR3((fExitLeft ? -fDistant : fDistant), 0.0f, 0.0f);
  1111. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1112. // Look at painting #6 (Front Wall #2)
  1113. hr = ptheCamera->CreateNextWait(m_nBatch+3, 1);
  1114. // Walk towards the door
  1115. vSourceLoc = vDestLoc;
  1116. vSourceTangent = vDestTangent;
  1117. vDestTangent = D3DXVECTOR3(0.0f, 0.0f, fDistant);
  1118. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1119. vSourceTangent = vDestTangent;
  1120. vDestLoc = D3DXVECTOR3((fExitLeft ? fDistToWall : g_fRoomWidthX-fDistToWall), fWalkHeight, (WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f)));
  1121. vDestTangent = vSourceTangent;
  1122. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1123. // Now leave the room.
  1124. vSourceLoc = vDestLoc;
  1125. vSourceTangent = vDestTangent;
  1126. vDestTangent = D3DXVECTOR3((fExitLeft ? -fDistant : fDistant), 0.0f, 0.0f);
  1127. hr = ptheCamera->CreateNextRotate(vSourceLoc, vSourceTangent, vDestTangent);
  1128. vSourceTangent = vDestTangent;
  1129. vDestLoc = D3DXVECTOR3((fExitLeft ? 0.0f : g_fRoomWidthX), fWalkHeight, (WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f)));
  1130. vDestTangent = vSourceTangent;
  1131. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1132. }
  1133. return hr;
  1134. }
  1135. HRESULT CTheRoom::LoadCameraMoves(CCameraMove * ptheCamera)
  1136. { // TODO: We need to change this based on the room shape and the door entered.
  1137. HRESULT hr = S_OK;
  1138. if (m_fLobby)
  1139. {
  1140. hr = _LoadLobbyPath(ptheCamera);
  1141. }
  1142. else
  1143. {
  1144. switch (m_pFloorPlan->nMovementPattern)
  1145. {
  1146. case 0:
  1147. hr = _LongRoomEnterDoorMovements(ptheCamera);
  1148. break;
  1149. case 1:
  1150. hr = _LongRoomSideEnterLeaveMovements(ptheCamera);
  1151. break;
  1152. }
  1153. }
  1154. return hr;
  1155. }
  1156. HRESULT CTheRoom::_LoadLobbyPath(CCameraMove * ptheCamera)
  1157. {
  1158. HRESULT hr = S_OK;
  1159. float fDistant = 5.0f;
  1160. float fDistToWall = 30.0f;
  1161. float fWalkHeight = 20.0f;
  1162. D3DXVECTOR3 vSourceLoc((g_fRoomWidthX / 2.0f), fWalkHeight, 1.0f);
  1163. D3DXVECTOR3 vSourceTangent(0.0f, 0.0f, fDistant);
  1164. hr = ptheCamera->Init(vSourceLoc, vSourceTangent, D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  1165. if (SUCCEEDED(hr))
  1166. {
  1167. // Walk down the middle of the room.
  1168. D3DXVECTOR3 vDestLoc((g_fRoomWidthX / 2.0f), fWalkHeight, (g_fRoomDepthZ * (2.0f / 4.0f)));
  1169. D3DXVECTOR3 vDestTangent(0.0f, 0.0f, 1.0f);
  1170. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1171. // Now start walking toward the door.
  1172. vSourceLoc = vDestLoc;
  1173. vSourceTangent = vDestTangent;
  1174. // 1=Left
  1175. vDestTangent = D3DXVECTOR3(((1 == m_pFloorPlan->nExitDoor) ? -1.0f : 1.0f), 0.0f, 0.0f);
  1176. vDestLoc = D3DXVECTOR3(((1 == m_pFloorPlan->nExitDoor) ? 0.0f : g_fRoomWidthX), fWalkHeight, (WALL_WIDTHBEFOREDOOR + (DOOR_WIDTH / 2.0f)));
  1177. hr = ptheCamera->CreateNextMove(vSourceLoc, vSourceTangent, vDestLoc, vDestTangent);
  1178. }
  1179. return hr;
  1180. }
  1181. //===========================
  1182. // *** IUnknown Interface ***
  1183. //===========================
  1184. ULONG CTheRoom::AddRef()
  1185. {
  1186. return InterlockedIncrement(&m_cRef);
  1187. }
  1188. ULONG CTheRoom::Release()
  1189. {
  1190. if (InterlockedDecrement(&m_cRef))
  1191. return m_cRef;
  1192. delete this;
  1193. return 0;
  1194. }
  1195. HRESULT CTheRoom::QueryInterface(REFIID riid, void **ppvObj)
  1196. {
  1197. static const QITAB qit[] = {
  1198. QITABENT(CTheRoom, IUnknown),
  1199. { 0 },
  1200. };
  1201. return QISearch(this, qit, riid, ppvObj);
  1202. }
  1203. int CTheRoom::GetEnterDoor(void)
  1204. {
  1205. int nDoor = 0;
  1206. if (m_pFloorPlan)
  1207. {
  1208. nDoor = m_pFloorPlan->nEnterDoor;
  1209. }
  1210. return nDoor;
  1211. }
  1212. int CTheRoom::GetExitDoor(void)
  1213. {
  1214. int nDoor = 0;
  1215. if (m_pFloorPlan)
  1216. {
  1217. nDoor = m_pFloorPlan->nExitDoor;
  1218. }
  1219. return nDoor;
  1220. }