camera.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WW3D *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/camera.cpp $*
  25. * *
  26. * Org Author:: Greg_h *
  27. * *
  28. * $Author:: Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 4:04p $*
  31. * *
  32. * $Revision:: 24 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. *---------------------------------------------------------------------------------------------*
  36. * Functions: *
  37. * CameraClass::CameraClass -- constructor *
  38. * CameraClass::CameraClass -- copy constructor *
  39. * CameraClass::operator == -- assignment operator *
  40. * CameraClass::~CameraClass -- destructor *
  41. * CameraClass::Clone -- virtual copy constructor *
  42. * CameraClass::Add -- add the camera to the world? *
  43. * CameraClass::Remove -- Remove the camera from the world? *
  44. * CameraClass::Get_Obj_Space_Bounding_Sphere -- returns the object space bounding sphere *
  45. * CameraClass::Get_Object_Space_Bounding_Box -- returns the object space bounding box *
  46. * CameraClass::Set_Transform -- set the transform of the camera *
  47. * CameraClass::Set_Position -- Set the position of the camera *
  48. * CameraClass::Set_Animation -- set the animation state of the camera *
  49. * CameraClass::Set_Animation -- Set the animation state of the camera *
  50. * CameraClass::Set_Animation -- set the animation state of the camera *
  51. * CameraClass::Set_Animation -- set the animation state of the camera *
  52. * CameraClass::Set_View_Plane -- control over the view plane *
  53. * CameraClass::Set_View_Plane -- set the viewplane using fov angles *
  54. * CameraClass::Set_Focal_Length -- set the view plane using focal length and aspect ratio *
  55. * CameraClass::Get_View_Plane -- get the corners of the current view plane *
  56. * CameraClass::Project -- project a point from ws to the view plane *
  57. * CameraClass::Project_Camera_Space_Point -- Project a point that is already in camera spac *
  58. * CameraClass::Un_Project -- "unproject" a point from the view plane to world space *
  59. * CameraClass::Transform_To_View_Space -- transforms the given world space point to camera *
  60. * CameraClass::Rotate_To_View_Space -- rotates the given world space vector to camera space *
  61. * CameraClass::Get_Near_Clip_Bounding_Box -- returns an obb that contains near clip plane *
  62. * CameraCLass::Update_Frustum -- updates the frustum parameters *
  63. * CameraClass::Cull_Box -- tests whether the given box can be culled *
  64. * CameraClass::Device_To_View_Space -- converts the given device coordinate to view space *
  65. * CameraClass::Device_To_World_Space -- converts given device coord to world space *
  66. * CameraClass::Camera_Push -- pushes the camera's parameters into the given GERD *
  67. * CameraClass::Camera_Pop -- pops the camera's parameters from the given GERD *
  68. * CameraClass::Set_Aspect_Ratio -- sets the aspect ratio of the camera *
  69. * CameraClass::Apply_D3D_State -- sets the D3D states controlled by the camera *
  70. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  71. #include "camera.h"
  72. #include "ww3d.h"
  73. #include "matrix4.h"
  74. #include "dx8wrapper.h"
  75. /***********************************************************************************************
  76. * CameraClass::CameraClass -- constructor *
  77. * *
  78. * INPUT: *
  79. * *
  80. * OUTPUT: *
  81. * *
  82. * WARNINGS: *
  83. * *
  84. * HISTORY: *
  85. * 3/21/98 GTH : Created. *
  86. *=============================================================================================*/
  87. CameraClass::CameraClass(void) :
  88. Projection(PERSPECTIVE),
  89. Viewport(Vector2(0,0),Vector2(1,1)), // pixel viewport to render into
  90. AspectRatio(4.0f/3.0f),
  91. ZNear(1.0f), // near clip plane distance
  92. ZFar(1000.0f), // far clip plane distance
  93. ZBufferMin(0.0f), // smallest value we'll write into the z-buffer
  94. ZBufferMax(1.0f), // largest value we'll write into the z-buffer
  95. FrustumValid(false)
  96. {
  97. Set_Transform(Matrix3D(1));
  98. Set_View_Plane(DEG_TO_RADF(50.0f));
  99. }
  100. /***********************************************************************************************
  101. * CameraClass::CameraClass -- copy constructor *
  102. * *
  103. * INPUT: *
  104. * *
  105. * OUTPUT: *
  106. * *
  107. * WARNINGS: *
  108. * *
  109. * HISTORY: *
  110. * 3/21/98 GTH : Created. *
  111. * 4/13/2001 hy : added in copy code for new member functions *
  112. *=============================================================================================*/
  113. CameraClass::CameraClass(const CameraClass & src) :
  114. RenderObjClass(src),
  115. Projection(src.Projection),
  116. Viewport(src.Viewport),
  117. ViewPlane(src.ViewPlane),
  118. ZNear(src.ZNear),
  119. ZFar(src.ZFar),
  120. FrustumValid(src.FrustumValid),
  121. Frustum(src.Frustum),
  122. NearClipBBox(src.NearClipBBox),
  123. ProjectionTransform(src.ProjectionTransform),
  124. CameraInvTransform(src.CameraInvTransform),
  125. AspectRatio(src.AspectRatio),
  126. ZBufferMin(src.ZBufferMin),
  127. ZBufferMax(src.ZBufferMax)
  128. {
  129. // just being paraniod in case any parent class doesn't completely copy the entire state...
  130. FrustumValid = false;
  131. }
  132. /***********************************************************************************************
  133. * CameraClass::operator == -- assignment operator *
  134. * *
  135. * INPUT: *
  136. * *
  137. * OUTPUT: *
  138. * *
  139. * WARNINGS: *
  140. * *
  141. * HISTORY: *
  142. * 3/21/98 GTH : Created. *
  143. *=============================================================================================*/
  144. CameraClass & CameraClass::operator = (const CameraClass & that)
  145. {
  146. if (this != &that) {
  147. RenderObjClass::operator = (that);
  148. Projection = that.Projection;
  149. Viewport = that.Viewport;
  150. ViewPlane = that.ViewPlane;
  151. ZNear = that.ZNear;
  152. ZFar = that.ZFar;
  153. FrustumValid = that.FrustumValid;
  154. Frustum = that.Frustum;
  155. NearClipBBox = that.NearClipBBox;
  156. ProjectionTransform = that.ProjectionTransform;
  157. CameraInvTransform = that.CameraInvTransform;
  158. // just being paraniod in case any parent class doesn't completely copy the entire state...
  159. FrustumValid = false;
  160. }
  161. return * this;
  162. }
  163. /***********************************************************************************************
  164. * CameraClass::~CameraClass -- destructor *
  165. * *
  166. * INPUT: *
  167. * *
  168. * OUTPUT: *
  169. * *
  170. * WARNINGS: *
  171. * *
  172. * HISTORY: *
  173. * 3/21/98 GTH : Created. *
  174. *=============================================================================================*/
  175. CameraClass::~CameraClass(void)
  176. {
  177. }
  178. /***********************************************************************************************
  179. * CameraClass::Clone -- virtual copy constructor *
  180. * *
  181. * INPUT: *
  182. * *
  183. * OUTPUT: *
  184. * *
  185. * WARNINGS: *
  186. * *
  187. * HISTORY: *
  188. * 3/21/98 GTH : Created. *
  189. *=============================================================================================*/
  190. RenderObjClass * CameraClass::Clone(void) const
  191. {
  192. return NEW_REF( CameraClass, (*this) );
  193. }
  194. /***********************************************************************************************
  195. * CameraClass::Get_Obj_Space_Bounding_Sphere -- returns the object space bounding sphere *
  196. * *
  197. * INPUT: *
  198. * *
  199. * OUTPUT: *
  200. * *
  201. * WARNINGS: *
  202. * *
  203. * HISTORY: *
  204. * 9/29/98 GTH : Created. *
  205. *=============================================================================================*/
  206. void CameraClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
  207. {
  208. sphere.Center.Set(0,0,0);
  209. sphere.Radius = ZFar; // could optimize this but its not really used.
  210. }
  211. /***********************************************************************************************
  212. * CameraClass::Get_Object_Space_Bounding_Box -- returns the object space bounding box *
  213. * *
  214. * INPUT: *
  215. * *
  216. * OUTPUT: *
  217. * *
  218. * WARNINGS: *
  219. * *
  220. * HISTORY: *
  221. * 9/29/98 GTH : Created. *
  222. *=============================================================================================*/
  223. void CameraClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
  224. {
  225. box.Center.Set(0,0,0);
  226. box.Extent.Set(ZFar,ZFar,ZFar); // could optimize this but its not really used.
  227. }
  228. /***********************************************************************************************
  229. * CameraClass::Set_Transform -- set the transform of the camera *
  230. * *
  231. * This is over-ridden to invalidate the cached frustum parameters *
  232. * *
  233. * INPUT: *
  234. * *
  235. * OUTPUT: *
  236. * *
  237. * WARNINGS: *
  238. * *
  239. * HISTORY: *
  240. * 5/29/98 GTH : Created. *
  241. *=============================================================================================*/
  242. void CameraClass::Set_Transform(const Matrix3D &m)
  243. {
  244. RenderObjClass::Set_Transform(m);
  245. FrustumValid = false;
  246. }
  247. /***********************************************************************************************
  248. * CameraClass::Set_Position -- Set the position of the camera *
  249. * *
  250. * This is overriden to invalidate the cached frustum parameters *
  251. * *
  252. * INPUT: *
  253. * *
  254. * OUTPUT: *
  255. * *
  256. * WARNINGS: *
  257. * *
  258. * HISTORY: *
  259. * 5/29/98 GTH : Created. *
  260. *=============================================================================================*/
  261. void CameraClass::Set_Position(const Vector3 &v)
  262. {
  263. RenderObjClass::Set_Position(v);
  264. FrustumValid = false;
  265. }
  266. /***********************************************************************************************
  267. * CameraClass::Set_View_Plane -- control over the view plane *
  268. * *
  269. * INPUT: *
  270. * min - x,y of the upper left corner of the view rectangle (dist is assumed to be 1.0) *
  271. * max - x,y of the lower right corner of the view rectangle *
  272. * *
  273. * OUTPUT: *
  274. * *
  275. * WARNINGS: *
  276. * *
  277. * HISTORY: *
  278. * 3/21/98 GTH : Created. *
  279. *=============================================================================================*/
  280. void CameraClass::Set_View_Plane(const Vector2 & vmin,const Vector2 & vmax)
  281. {
  282. ViewPlane.Min = vmin;
  283. ViewPlane.Max = vmax;
  284. AspectRatio = (vmax.X - vmin.X) / (vmax.Y - vmin.Y);
  285. FrustumValid = false;
  286. }
  287. /***********************************************************************************************
  288. * CameraClass::Set_View_Plane -- set the viewplane using fov angles *
  289. * *
  290. * INPUT: *
  291. * *
  292. * OUTPUT: *
  293. * *
  294. * WARNINGS: *
  295. * *
  296. * HISTORY: *
  297. * 3/21/98 GTH : Created. *
  298. *=============================================================================================*/
  299. void CameraClass::Set_View_Plane(float hfov,float vfov)
  300. {
  301. float width_half = tan(hfov/2.0);
  302. float height_half = 0.0f;
  303. if (vfov == -1) {
  304. height_half = (1.0f / AspectRatio) * width_half; // use the aspect ratio
  305. } else {
  306. height_half = tan(vfov/2.0);
  307. AspectRatio = width_half / height_half; // or, initialize the aspect ratio
  308. }
  309. ViewPlane.Min.Set(-width_half,-height_half);
  310. ViewPlane.Max.Set(width_half,height_half);
  311. FrustumValid = false;
  312. }
  313. /***********************************************************************************************
  314. * CameraClass::Set_Aspect_Ratio -- sets the aspect ratio of the camera *
  315. * *
  316. * INPUT: *
  317. * *
  318. * OUTPUT: *
  319. * *
  320. * WARNINGS: *
  321. * *
  322. * HISTORY: *
  323. * 1/29/2001 gth : Created. *
  324. *=============================================================================================*/
  325. void CameraClass::Set_Aspect_Ratio(float width_to_height)
  326. {
  327. AspectRatio = width_to_height;
  328. ViewPlane.Min.Y = ViewPlane.Min.X / AspectRatio;
  329. ViewPlane.Max.Y = ViewPlane.Max.X / AspectRatio;
  330. FrustumValid = false;
  331. }
  332. /***********************************************************************************************
  333. * CameraClass::Get_View_Plane -- get the corners of the current view plane *
  334. * *
  335. * INPUT: *
  336. * *
  337. * OUTPUT: *
  338. * *
  339. * WARNINGS: *
  340. * *
  341. * HISTORY: *
  342. * 3/21/98 GTH : Created. *
  343. *=============================================================================================*/
  344. void CameraClass::Get_View_Plane(Vector2 & set_min,Vector2 & set_max) const
  345. {
  346. set_min = ViewPlane.Min;
  347. set_max = ViewPlane.Max;
  348. }
  349. /***********************************************************************************************
  350. * CameraClass::Project -- project a point from ws to the view plane *
  351. * *
  352. * INPUT: *
  353. * dest - will be set to a point on the normalized view plane. x,y, and z range from -1 to 1 *
  354. * ws_point - input point in world space *
  355. * *
  356. * OUTPUT: *
  357. * ProjectionResType indicating whether the point was in the frustum *
  358. * *
  359. * WARNINGS: *
  360. * When the input is behind the near clip plane, 0,0,0 is returned. *
  361. * *
  362. * HISTORY: *
  363. * 3/21/98 GTH : Created. *
  364. *=============================================================================================*/
  365. CameraClass::ProjectionResType CameraClass::Project(Vector3 & dest,const Vector3 & ws_point) const
  366. {
  367. Update_Frustum();
  368. Vector3 cam_point;
  369. Matrix3D::Transform_Vector(CameraInvTransform,ws_point,&cam_point);
  370. if (cam_point.Z > -ZNear) {
  371. dest.Set(0,0,0);
  372. return OUTSIDE_NEAR_CLIP;
  373. }
  374. Vector4 view_point = ProjectionTransform * cam_point;
  375. float oow = 1.0f / view_point.W;
  376. dest.X = view_point.X * oow;
  377. dest.Y = view_point.Y * oow;
  378. dest.Z = view_point.Z * oow;
  379. if (dest.Z > 1.0f) {
  380. return OUTSIDE_FAR_CLIP;
  381. }
  382. if ((dest.X < -1.0f) || (dest.X > 1.0f) || (dest.Y < -1.0f) || (dest.Y > 1.0f)) {
  383. return OUTSIDE_FRUSTUM;
  384. }
  385. return INSIDE_FRUSTUM;
  386. }
  387. /***********************************************************************************************
  388. * CameraClass::Project_Camera_Space_Point -- Project a point that is already in camera space *
  389. * *
  390. * INPUT: *
  391. * dest - will be set to a point on the normalized view plane. x,y, and z range from -1 to 1 *
  392. * cam_point - input point in camera space *
  393. * *
  394. * OUTPUT: *
  395. * ProjectionResType indicating whether the point was in the frustum *
  396. * *
  397. * WARNINGS: *
  398. * When the input is behind the near clip plane, 0,0,0 is returned. *
  399. * *
  400. * HISTORY: *
  401. * 11/17/2000 gth : Created. *
  402. *=============================================================================================*/
  403. CameraClass::ProjectionResType
  404. CameraClass::Project_Camera_Space_Point(Vector3 & dest,const Vector3 & cam_point) const
  405. {
  406. Update_Frustum();
  407. if ( cam_point.Z > -ZNear + WWMATH_EPSILON) {
  408. dest.Set(0,0,0);
  409. return OUTSIDE_NEAR_CLIP;
  410. }
  411. Vector4 view_point = ProjectionTransform * cam_point;
  412. float oow = 1.0f / view_point.W;
  413. dest.X = view_point.X * oow;
  414. dest.Y = view_point.Y * oow;
  415. dest.Z = view_point.Z * oow;
  416. if (dest.Z > 1.0f) {
  417. return OUTSIDE_FAR_CLIP;
  418. }
  419. if ((dest.X < -1.0f) || (dest.X > 1.0f) || (dest.Y < -1.0f) || (dest.Y > 1.0f)) {
  420. return OUTSIDE_FRUSTUM;
  421. }
  422. return INSIDE_FRUSTUM;
  423. }
  424. /***********************************************************************************************
  425. * CameraClass::Un_Project -- "unproject" a point from the view plane to world space *
  426. * *
  427. * The given point is assumed to be on the view_plane at z=-1. The 3D world space point that *
  428. * this represents will be returned in dest. *
  429. * *
  430. * INPUT: *
  431. * dest - will be filled in with the 3D world space point that the given point represents *
  432. * view_point - point on the view_plane to be un-projected *
  433. * *
  434. * OUTPUT: *
  435. * *
  436. * WARNINGS: *
  437. * *
  438. * HISTORY: *
  439. * 3/21/98 GTH : Created. *
  440. *=============================================================================================*/
  441. void CameraClass::Un_Project(Vector3 & dest,const Vector2 & view_point) const
  442. {
  443. /*
  444. ** map view_point.X from -1..1 to ViewPlaneMin.X..ViewPlaneMax.X
  445. ** map view_point.Y from -1..1 to ViewPlaneMin.X..ViewPlaneMax.X
  446. */
  447. float vpdx = ViewPlane.Max.X - ViewPlane.Min.X;
  448. float vpdy = ViewPlane.Max.Y - ViewPlane.Min.Y;
  449. Vector3 point;
  450. point.X = ViewPlane.Min.X + vpdx * (view_point.X + 1.0f) * 0.5f;
  451. point.Y = ViewPlane.Min.Y + vpdy * (view_point.Y + 1.0f) * 0.5f;
  452. point.Z = -1.0f;
  453. Matrix3D::Transform_Vector(Transform,point,&dest);
  454. }
  455. /***********************************************************************************************
  456. * CameraClass::Transform_To_View_Space -- transforms the given world space point to camera sp *
  457. * *
  458. * INPUT: *
  459. * *
  460. * OUTPUT: *
  461. * *
  462. * WARNINGS: *
  463. * *
  464. * HISTORY: *
  465. * 2/22/2001 gth : Created. *
  466. *=============================================================================================*/
  467. void CameraClass::Transform_To_View_Space(Vector3 & dest,const Vector3 & ws_point) const
  468. {
  469. Update_Frustum();
  470. Matrix3D::Transform_Vector(CameraInvTransform,ws_point,&dest);
  471. }
  472. /***********************************************************************************************
  473. * CameraClass::Rotate_To_View_Space -- rotates the given world space vector to camera space *
  474. * *
  475. * INPUT: *
  476. * *
  477. * OUTPUT: *
  478. * *
  479. * WARNINGS: *
  480. * *
  481. * HISTORY: *
  482. * 2/22/2001 gth : Created. *
  483. *=============================================================================================*/
  484. void CameraClass::Rotate_To_View_Space(Vector3 & dest,const Vector3 & ws_vector) const
  485. {
  486. Update_Frustum();
  487. Matrix3D::Rotate_Vector(CameraInvTransform,ws_vector,&dest);
  488. }
  489. /***********************************************************************************************
  490. * CameraClass::Get_Near_Clip_Bounding_Box -- returns an obb that contains near clip plane *
  491. * *
  492. * INPUT: *
  493. * *
  494. * OUTPUT: *
  495. * *
  496. * WARNINGS: *
  497. * *
  498. * HISTORY: *
  499. * 8/25/99 GTH : Created. *
  500. *=============================================================================================*/
  501. const OBBoxClass & CameraClass::Get_Near_Clip_Bounding_Box(void) const
  502. {
  503. Update_Frustum();
  504. return NearClipBBox;
  505. }
  506. /***********************************************************************************************
  507. * CameraClass::Cull_Box -- tests whether the given box can be culled *
  508. * *
  509. * INPUT: *
  510. * *
  511. * OUTPUT: *
  512. * *
  513. * WARNINGS: *
  514. * *
  515. * HISTORY: *
  516. * 12/8/98 GTH : Created. *
  517. *=============================================================================================*/
  518. bool CameraClass::Cull_Box(const AABoxClass & box) const
  519. {
  520. const FrustumClass & frustum = Get_Frustum();
  521. return CollisionMath::Overlap_Test(frustum,box) == CollisionMath::OUTSIDE;
  522. }
  523. /***********************************************************************************************
  524. * CameraClass::Update_Frustum -- updates the frustum parameters *
  525. * *
  526. * INPUT: *
  527. * *
  528. * OUTPUT: *
  529. * *
  530. * WARNINGS: *
  531. * *
  532. * HISTORY: *
  533. * 5/29/98 GTH : Created. *
  534. *=============================================================================================*/
  535. void CameraClass::Update_Frustum(void) const
  536. {
  537. if (FrustumValid) return;
  538. Vector2 vpmin,vpmax;
  539. float znear,zfar;
  540. float znear_dist,zfar_dist;
  541. Matrix3D cam_mat = Get_Transform();
  542. Get_View_Plane(vpmin, vpmax); // Normalized view plane at a depth of 1.0
  543. Get_Clip_Planes(znear_dist, zfar_dist);
  544. // Forward is negative Z in our viewspace coordinate system.
  545. znear = -znear_dist;
  546. zfar = -zfar_dist;
  547. // Update the frustum
  548. FrustumValid = true;
  549. Frustum.Init(cam_mat,vpmin,vpmax,znear,zfar);
  550. ViewSpaceFrustum.Init(Matrix3D(1),vpmin,vpmax,znear,zfar);
  551. // Update the OBB around the near clip rectangle
  552. #ifdef ALLOW_TEMPORARIES
  553. NearClipBBox.Center = cam_mat * Vector3(0,0,znear);
  554. #else
  555. cam_mat.mulVector3(Vector3(0,0,znear), NearClipBBox.Center);
  556. #endif
  557. NearClipBBox.Extent.X = (vpmax.X - vpmin.X) * (-znear) * 0.5f; // (near_clip_x / |znear|) == (vpmin.X / 1.0f)...
  558. NearClipBBox.Extent.Y = (vpmax.Y - vpmin.Y) * (-znear) * 0.5f;
  559. NearClipBBox.Extent.Z = 0.01f;
  560. NearClipBBox.Basis.Set(cam_mat);
  561. // Update the inverse camera matrix
  562. Transform.Get_Inverse(CameraInvTransform);
  563. // Update the projection matrix
  564. if (Projection == PERSPECTIVE) {
  565. ProjectionTransform.Init_Perspective( vpmin.X*znear_dist, vpmax.X*znear_dist,
  566. vpmin.Y*znear_dist, vpmax.Y*znear_dist,
  567. znear_dist, zfar_dist );
  568. } else {
  569. ProjectionTransform.Init_Ortho( vpmin.X,vpmax.X,vpmin.Y,vpmax.Y,znear_dist,zfar_dist);
  570. }
  571. }
  572. /***********************************************************************************************
  573. * CameraClass::Device_To_View_Space -- converts the given device coordinate to view space *
  574. * *
  575. * INPUT: *
  576. * *
  577. * OUTPUT: *
  578. * *
  579. * WARNINGS: *
  580. * *
  581. * HISTORY: *
  582. * 12/8/98 GTH : Created. *
  583. *=============================================================================================*/
  584. void CameraClass::Device_To_View_Space(const Vector2 & device_coord,Vector3 * set_view)
  585. {
  586. int res_width;
  587. int res_height;
  588. int res_bits;
  589. bool windowed;
  590. WW3D::Get_Render_Target_Resolution(res_width,res_height,res_bits,windowed);
  591. // convert the device coordinates into normalized device coordinates:
  592. Vector2 ndev;
  593. ndev.X = device_coord.X / (float)res_width;
  594. ndev.Y = device_coord.Y / (float)res_height;
  595. // view space rectangle which corresponds to the viewport
  596. Vector2 vs_min;
  597. Vector2 vs_max;
  598. Get_View_Plane(vs_min,vs_max);
  599. // mapping from the viewport coordinates to view space coordinates
  600. set_view->X = vs_min.X + (ndev.X - Viewport.Min.X) * (vs_max.X - vs_min.X) / (Viewport.Width());
  601. set_view->Y = vs_max.Y - (ndev.Y - Viewport.Min.Y) * (vs_max.Y - vs_min.Y) / (Viewport.Height());
  602. set_view->Z = -1.0f;
  603. }
  604. /***********************************************************************************************
  605. * CameraClass::Device_To_World_Space -- converts given device coord to world space *
  606. * *
  607. * INPUT: *
  608. * *
  609. * OUTPUT: *
  610. * *
  611. * WARNINGS: *
  612. * *
  613. * HISTORY: *
  614. * 12/8/98 GTH : Created. *
  615. *=============================================================================================*/
  616. void CameraClass::Device_To_World_Space(const Vector2 & device_coord,Vector3 * world_coord)
  617. {
  618. Vector3 vs;
  619. Device_To_View_Space(device_coord,&vs);
  620. Matrix3D::Transform_Vector(Transform,vs,world_coord);
  621. }
  622. /***********************************************************************************************
  623. * CameraClass::Apply -- sets the D3D states controlled by the camera *
  624. * *
  625. * INPUT: *
  626. * *
  627. * OUTPUT: *
  628. * *
  629. * WARNINGS: *
  630. * *
  631. * HISTORY: *
  632. * 1/29/2001 gth : Created. *
  633. *=============================================================================================*/
  634. void CameraClass::Apply(void)
  635. {
  636. Update_Frustum();
  637. int width,height,bits;
  638. bool windowed;
  639. WW3D::Get_Render_Target_Resolution(width,height,bits,windowed);
  640. D3DVIEWPORT8 vp;
  641. vp.X = (DWORD)(Viewport.Min.X * (float)width);
  642. vp.Y = (DWORD)(Viewport.Min.Y * (float)height);
  643. vp.Width = (DWORD)((Viewport.Max.X - Viewport.Min.X) * (float)width);
  644. vp.Height = (DWORD)((Viewport.Max.Y - Viewport.Min.Y) * (float)height);
  645. vp.MinZ = ZBufferMin;
  646. vp.MaxZ = ZBufferMax;
  647. DX8Wrapper::Set_Viewport(&vp);
  648. Matrix4x4 d3dprojection;
  649. Get_D3D_Projection_Matrix(&d3dprojection);
  650. DX8Wrapper::Set_Projection_Transform_With_Z_Bias(d3dprojection,ZNear,ZFar);
  651. DX8Wrapper::Set_Transform(D3DTS_VIEW,CameraInvTransform);
  652. }
  653. void CameraClass::Set_Clip_Planes(float znear,float zfar)
  654. {
  655. FrustumValid = false;
  656. ZNear = znear;
  657. ZFar = zfar;
  658. }
  659. void CameraClass::Get_Clip_Planes(float & znear,float & zfar) const
  660. {
  661. znear = ZNear;
  662. zfar = ZFar;
  663. }
  664. float CameraClass::Get_Horizontal_FOV(void) const
  665. {
  666. float width = ViewPlane.Max.X - ViewPlane.Min.X;
  667. return 2*WWMath::Atan2(width,2.0);
  668. }
  669. float CameraClass::Get_Vertical_FOV(void) const
  670. {
  671. float height = ViewPlane.Max.Y - ViewPlane.Min.Y;
  672. return 2*WWMath::Atan2(height,2.0);
  673. }
  674. float CameraClass::Get_Aspect_Ratio(void) const
  675. {
  676. return AspectRatio;
  677. }
  678. void CameraClass::Get_Projection_Matrix(Matrix4x4 * set_tm)
  679. {
  680. WWASSERT(set_tm != NULL);
  681. Update_Frustum();
  682. *set_tm = ProjectionTransform;
  683. }
  684. void CameraClass::Get_D3D_Projection_Matrix(Matrix4x4 * set_tm)
  685. {
  686. WWASSERT(set_tm != NULL);
  687. Update_Frustum();
  688. *set_tm = ProjectionTransform;
  689. /*
  690. ** We need to flip the handed-ness of the projection matrix and
  691. ** move the z-range to 0<z<1 rather than -1<z<1
  692. */
  693. float oozdiff = 1.0 / (ZFar - ZNear);
  694. if (Projection == PERSPECTIVE) {
  695. (*set_tm)[2][2] = -(ZFar) * oozdiff;
  696. (*set_tm)[2][3] = -(ZFar*ZNear) * oozdiff;
  697. } else {
  698. (*set_tm)[2][2] = -oozdiff;
  699. (*set_tm)[2][3] = -ZNear * oozdiff;
  700. }
  701. }
  702. void CameraClass::Get_View_Matrix(Matrix3D * set_tm)
  703. {
  704. WWASSERT(set_tm != NULL);
  705. Update_Frustum();
  706. *set_tm = CameraInvTransform;
  707. }
  708. const Matrix4x4 & CameraClass::Get_Projection_Matrix(void)
  709. {
  710. Update_Frustum();
  711. return ProjectionTransform;
  712. }
  713. const Matrix3D & CameraClass::Get_View_Matrix(void)
  714. {
  715. Update_Frustum();
  716. return CameraInvTransform;
  717. }
  718. void CameraClass::Convert_Old(Vector3 &pos)
  719. {
  720. pos.X=(pos.X+1)/2;
  721. pos.Y=(pos.Y+1)/2;
  722. }
  723. float CameraClass::Compute_Projected_Sphere_Radius(float dist,float radius)
  724. {
  725. Vector4 result = ProjectionTransform * Vector4(radius,0.0f,dist,1.0f);
  726. return result.X / result.W;
  727. }