camera.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  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.h $*
  25. * *
  26. * Org Author:: Greg_h *
  27. * *
  28. * $Author:: Kenny Mitchell *
  29. * *
  30. * $Modtime:: 06/26/02 4:04p $*
  31. * *
  32. * $Revision:: 14 $*
  33. * *
  34. * 06/26/02 KM Matrix name change to avoid MAX conflicts *
  35. *---------------------------------------------------------------------------------------------*
  36. * Functions: *
  37. * CameraClass::Get_Frustum -- returns the frustum of the camera *
  38. * CameraClass::Get_Frustum_Planes -- returns pointer to the array of frustum planes *
  39. * CameraClass::Get_Frustum_Corners -- returns pointer to the array of frustum corners *
  40. * CameraClass::Get_View_Space_Frustum -- returns the view-space frustum for this camera *
  41. * CameraClass::Get_View_Space_Frustum_Planes -- returns the view space clip planes for this *
  42. * CameraClass::Get_View_Space_Frustum_Corners -- returns the corners of the view space frus *
  43. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  44. #if defined(_MSC_VER)
  45. #pragma once
  46. #endif
  47. #ifndef CAMERA_H
  48. #define CAMERA_H
  49. #include "always.h"
  50. #include "rendobj.h"
  51. #include "plane.h"
  52. #include "frustum.h"
  53. #include "obbox.h"
  54. #include "vector2.h"
  55. #include "matrix4.h"
  56. #include "colmath.h"
  57. class RenderInfoClass;
  58. /**
  59. ** ViewportClass
  60. ** This class is used to define a "normalized" screen space rectangle for the
  61. ** camera to render into. A viewport which filled the entire screen would be
  62. ** (0,0) - (1,1) with 0,0 being the upper left and 1,1 being the lower right.
  63. */
  64. class ViewportClass
  65. {
  66. public:
  67. ViewportClass(void) : Min(0,0), Max(1,1) { }
  68. ViewportClass(const Vector2 & min,const Vector2 & max) : Min(min), Max(max) { }
  69. ViewportClass(const ViewportClass & vp) : Min(vp.Min), Max(vp.Max) { }
  70. float Width(void) const { return Max.X - Min.X; }
  71. float Height(void) const { return Max.Y - Min.Y; }
  72. Vector2 Min;
  73. Vector2 Max;
  74. };
  75. /**
  76. ** CameraClass
  77. ** This object controls how vertices are transformed from world-space to view
  78. ** space, the parameters of the perspective projection, and the viewport
  79. ** on screen that the result is mapped into.
  80. **
  81. ** Cameras are not "rendered" and do not need to be "added" to a scene. A
  82. ** CameraClass is passed into the WW3D::Render(...) function. The reason
  83. ** they are render objects is so that they can be inserted onto the bone of
  84. ** some animation and move with the animation...
  85. **
  86. ** For all of the projection functions (Matrix4x4, ProjectorClass (used by
  87. ** decals and texture projections), and CameraClass) I followed the OpenGL
  88. ** convention of passing positive distances for your clip planes even though
  89. ** in a right-handed coordinate system your z values are negative after
  90. ** transformation to camera space. So Set_Clip_Planes expects positive distances
  91. ** to your near and far clip planes.
  92. **
  93. ** (gth) We should probably separate CameraClass from RenderObjClass... In the
  94. ** case where a camera is using a transform from an animation; the programmer
  95. ** is usually requesting the transform and plugging it into the camera anyway.
  96. */
  97. class CameraClass : public RenderObjClass
  98. {
  99. public:
  100. enum ProjectionType
  101. {
  102. PERSPECTIVE = 0,
  103. ORTHO
  104. };
  105. enum ProjectionResType
  106. {
  107. INSIDE_FRUSTUM,
  108. OUTSIDE_FRUSTUM,
  109. OUTSIDE_NEAR_CLIP,
  110. OUTSIDE_FAR_CLIP,
  111. };
  112. CameraClass(void);
  113. CameraClass(const CameraClass & src);
  114. CameraClass & operator = (const CameraClass &);
  115. virtual ~CameraClass(void);
  116. virtual RenderObjClass * Clone(void) const;
  117. virtual int Class_ID(void) const { return CLASSID_CAMERA; }
  118. /////////////////////////////////////////////////////////////////////////////
  119. // Render Object Interface - Rendering, cameras don't "render"
  120. /////////////////////////////////////////////////////////////////////////////
  121. virtual void Render(RenderInfoClass & rinfo) { }
  122. /////////////////////////////////////////////////////////////////////////////
  123. // Render Object Interface - "Scene Graph"
  124. // Cameras cache their frustum description, this is invalidated whenever
  125. // the transform/position is changed
  126. /////////////////////////////////////////////////////////////////////////////
  127. virtual void Set_Transform(const Matrix3D &m);
  128. virtual void Set_Position(const Vector3 &v);
  129. /////////////////////////////////////////////////////////////////////////////
  130. // Render Object Interface - Bounding Volumes
  131. /////////////////////////////////////////////////////////////////////////////
  132. virtual void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const;
  133. virtual void Get_Obj_Space_Bounding_Box(AABoxClass & box) const;
  134. ///////////////////////////////////////////////////////////////////////////
  135. // Camera parameter control
  136. ///////////////////////////////////////////////////////////////////////////
  137. // Depth of the scene.
  138. float Get_Depth(void) const;
  139. // Setting the projection type
  140. void Set_Projection_Type(ProjectionType ptype);
  141. ProjectionType Get_Projection_Type(void);
  142. // Setting the clipping ranges in world space distances
  143. void Set_Clip_Planes(float znear,float zfar);
  144. void Get_Clip_Planes(float & znear,float & zfar) const;
  145. // Setting the zbuffer range used during rendering. (Added to allow subdividing the z-buffer. -MW).
  146. void Set_Zbuffer_Range(float znear,float zfar) {ZBufferMin = znear;ZBufferMax=zfar;}
  147. void Get_Zbuffer_Range(float & znear,float & zfar) const {znear=ZBufferMin;zfar=ZBufferMax;}
  148. // Methods for setting the View Plane.
  149. // NOTE: View plane is always at a distance of 1.0 from the eye.
  150. void Set_View_Plane(const Vector2 & min,const Vector2 & max);
  151. void Set_View_Plane(float hfov,float vfov = -1);
  152. void Set_Aspect_Ratio(float width_to_height);
  153. // Methods for querying the View Plane settings.
  154. void Get_View_Plane(Vector2 & set_min,Vector2 & set_max) const;
  155. float Get_Horizontal_FOV(void) const;
  156. float Get_Vertical_FOV(void) const;
  157. float Get_Aspect_Ratio(void) const;
  158. // Access to the projection matrices for this camera
  159. void Get_Projection_Matrix(Matrix4x4 * set_tm);
  160. void Get_D3D_Projection_Matrix(Matrix4x4 * set_tm);
  161. void Get_View_Matrix(Matrix3D * set_tm);
  162. const Matrix4x4 & Get_Projection_Matrix(void);
  163. const Matrix3D & Get_View_Matrix(void);
  164. // Projecting and Un-Projecting a point
  165. ProjectionResType Project(Vector3 & dest,const Vector3 & ws_point) const;
  166. ProjectionResType Project_Camera_Space_Point(Vector3 & dest,const Vector3 & cam_point) const;
  167. void Un_Project(Vector3 & dest,const Vector2 & view_point) const;
  168. void Transform_To_View_Space(Vector3 & dest,const Vector3 & ws_point) const;
  169. void Rotate_To_View_Space(Vector3 & dest,const Vector3 & ws_vector) const;
  170. // Viewport control
  171. void Set_Viewport(const Vector2 & min,const Vector2 & max);
  172. void Get_Viewport(Vector2 & set_min,Vector2 & set_max) const;
  173. const ViewportClass & Get_Viewport(void) const;
  174. void Set_Depth_Range(float zstart = 0.0f,float zend = 1.0f);
  175. void Get_Depth_Range(float * set_zstart,float * set_zend) const;
  176. // Culling for various bounding volumes. These functions will return true if the
  177. // given primitive is culled (i.e. it is *outside* the view frustum)
  178. bool Cull_Sphere(const SphereClass & sphere) const;
  179. bool Cull_Sphere_On_Frustum_Sides(const SphereClass & sphere) const;
  180. bool Cull_Box(const AABoxClass & box) const;
  181. // Various properties of the camera's frustum: These funcitons return a
  182. // pointer to the internal storage of the descriptions. there will be
  183. // 6 frustum planes, 8 corner points, see the implementations of these
  184. // functions for definitions on which points/planes are associated with
  185. // each index. Better yet, just use the Frustum object.
  186. const FrustumClass & Get_Frustum(void) const;
  187. const PlaneClass * Get_Frustum_Planes(void) const;
  188. const Vector3 * Get_Frustum_Corners(void) const;
  189. const FrustumClass & Get_View_Space_Frustum(void) const;
  190. const PlaneClass * Get_View_Space_Frustum_Planes(void) const;
  191. const Vector3 * Get_View_Space_Frustum_Corners(void) const;
  192. const OBBoxClass & Get_Near_Clip_Bounding_Box(void) const;
  193. // Methods for transforming/projecting points between various coordinate systems
  194. // associated with this camera.
  195. // "Device Space" - pixel coordinate
  196. // "View Space" - 3D space where the view point is at 0,0,0 and the view plane is at z=-1.0
  197. // "World Space" - 3D world coordinate system.
  198. void Device_To_View_Space(const Vector2 & device_coord,Vector3 * view_coord);
  199. void Device_To_World_Space(const Vector2 & device_coord,Vector3 * world_coord);
  200. float Compute_Projected_Sphere_Radius(float dist,float radius);
  201. // apply this camera's settings into d3d.
  202. void Apply(void);
  203. // utility class to convert to old space of 0..1
  204. static void Convert_Old(Vector3 &pos);
  205. protected:
  206. void Update_Frustum(void) const;
  207. ProjectionType Projection; // projection type, orthographic or perspective
  208. ViewportClass Viewport; // pixel viewport to render into
  209. ViewportClass ViewPlane; // corners of a slice through the frustum at z=-1.0
  210. float AspectRatio; // aspect ratio of the camera, width / height
  211. float ZNear; // near clip plane distance
  212. float ZFar; // far clip plane distance
  213. float ZBufferMin; // smallest value we'll write into the z-buffer (usually 0.0)
  214. float ZBufferMax; // largest value we'll write into the z-buffer (usually 1.0)
  215. mutable bool FrustumValid;
  216. mutable FrustumClass Frustum; // world-space frustum and clip planes
  217. mutable FrustumClass ViewSpaceFrustum; // view-space frustum and clip planes
  218. mutable OBBoxClass NearClipBBox; // obbox which bounds the near clip plane
  219. mutable Matrix4x4 ProjectionTransform;
  220. mutable Matrix3D CameraInvTransform;
  221. };
  222. inline float CameraClass::Get_Depth(void) const
  223. {
  224. return ZFar;
  225. }
  226. inline void CameraClass::Set_Projection_Type(ProjectionType ptype)
  227. {
  228. FrustumValid = false;
  229. Projection = ptype;
  230. }
  231. inline CameraClass::ProjectionType CameraClass::Get_Projection_Type(void)
  232. {
  233. return Projection;
  234. }
  235. inline void CameraClass::Set_Viewport(const Vector2 & min,const Vector2 & max)
  236. {
  237. Viewport.Min = min; Viewport.Max = max;
  238. FrustumValid = false;
  239. }
  240. inline void CameraClass::Get_Viewport(Vector2 & set_min,Vector2 & set_max) const
  241. {
  242. set_min = Viewport.Min;
  243. set_max = Viewport.Max;
  244. }
  245. inline void CameraClass::Set_Depth_Range(float zmin,float zmax)
  246. {
  247. ZBufferMin = zmin;
  248. ZBufferMax = zmax;
  249. }
  250. inline void CameraClass::Get_Depth_Range(float * set_zmin,float * set_zmax) const
  251. {
  252. if (set_zmin != NULL) {
  253. *set_zmin = ZBufferMin;
  254. }
  255. if (set_zmax != NULL) {
  256. *set_zmax = ZBufferMax;
  257. }
  258. }
  259. inline const ViewportClass & CameraClass::Get_Viewport(void) const
  260. {
  261. return Viewport;
  262. }
  263. inline bool CameraClass::Cull_Sphere(const SphereClass & sphere) const
  264. {
  265. const FrustumClass & frustum = Get_Frustum();
  266. return CollisionMath::Overlap_Test(frustum,sphere) == CollisionMath::OUTSIDE;
  267. }
  268. inline bool CameraClass::Cull_Sphere_On_Frustum_Sides(const SphereClass & sphere) const
  269. {
  270. const FrustumClass & frustum = Get_Frustum();
  271. const PlaneClass * planes = frustum.Planes;
  272. bool is_visible = true;
  273. for (int i = 1; i < 5; i++) {
  274. is_visible = is_visible && (CollisionMath::Overlap_Test(planes[i],sphere) & (CollisionMath::INSIDE|CollisionMath::BOTH));
  275. }
  276. return !is_visible;
  277. }
  278. /***********************************************************************************************
  279. * CameraClass::Get_Frustum -- returns the frustum of the camera *
  280. * *
  281. * INPUT: *
  282. * *
  283. * OUTPUT: *
  284. * *
  285. * WARNINGS: *
  286. * *
  287. * HISTORY: *
  288. * 3/24/99 GTH : Created. *
  289. *=============================================================================================*/
  290. inline const FrustumClass &
  291. CameraClass::Get_Frustum(void) const
  292. {
  293. Update_Frustum();
  294. return Frustum;
  295. }
  296. /***********************************************************************************************
  297. * CameraClass::Get_Frustum_Planes -- returns pointer to the array of frustum planes *
  298. * *
  299. * INPUT: *
  300. * *
  301. * OUTPUT: *
  302. * *
  303. * WARNINGS: *
  304. * *
  305. * HISTORY: *
  306. * 5/29/98 GTH : Created. *
  307. *=============================================================================================*/
  308. inline const PlaneClass *
  309. CameraClass::Get_Frustum_Planes(void) const
  310. {
  311. const FrustumClass & frustum = Get_Frustum();
  312. return frustum.Planes;
  313. }
  314. /***********************************************************************************************
  315. * CameraClass::Get_Frustum_Corners -- returns pointer to the array of frustum corners *
  316. * *
  317. * The camera frustum corner FrustumCorners are defined in the following order *
  318. * The first four points lie on the near clipping plane: *
  319. * upper left 0, upper right 1, lower left 2, lower right 3. *
  320. * The last four points lie on the far clipping plane, numbered analogous fashion. *
  321. * upper left 4, upper right 5, lower left 6, lower right 7. *
  322. * (remember: the camera space has x going to the right, y up and z backwards). *
  323. * *
  324. * INPUT: *
  325. * *
  326. * OUTPUT: *
  327. * *
  328. * WARNINGS: *
  329. * *
  330. * HISTORY: *
  331. * 5/29/98 GTH : Created. *
  332. *=============================================================================================*/
  333. inline const Vector3 *
  334. CameraClass::Get_Frustum_Corners(void) const
  335. {
  336. const FrustumClass & frustum = Get_Frustum();
  337. return frustum.Corners;
  338. }
  339. /***********************************************************************************************
  340. * CameraClass::Get_View_Space_Frustum -- returns the view-space frustum for this camera *
  341. * *
  342. * INPUT: *
  343. * *
  344. * OUTPUT: *
  345. * *
  346. * WARNINGS: *
  347. * *
  348. * HISTORY: *
  349. * 5/16/2001 gth : Created. *
  350. *=============================================================================================*/
  351. inline const FrustumClass & CameraClass::Get_View_Space_Frustum(void) const
  352. {
  353. Update_Frustum();
  354. return ViewSpaceFrustum;
  355. }
  356. /***********************************************************************************************
  357. * CameraClass::Get_View_Space_Frustum_Planes -- returns the view space clip planes for this c *
  358. * *
  359. * INPUT: *
  360. * *
  361. * OUTPUT: *
  362. * *
  363. * WARNINGS: *
  364. * *
  365. * HISTORY: *
  366. * 5/16/2001 gth : Created. *
  367. *=============================================================================================*/
  368. inline const PlaneClass * CameraClass::Get_View_Space_Frustum_Planes(void) const
  369. {
  370. const FrustumClass & frustum = Get_View_Space_Frustum();
  371. return frustum.Planes;
  372. }
  373. /***********************************************************************************************
  374. * CameraClass::Get_View_Space_Frustum_Corners -- returns the corners of the view space frustu *
  375. * *
  376. * The camera frustum corner FrustumCorners are defined in the following order *
  377. * The first four points lie on the near clipping plane: *
  378. * upper left 0, upper right 1, lower left 2, lower right 3. *
  379. * The last four points lie on the far clipping plane, numbered analogous fashion. *
  380. * upper left 4, upper right 5, lower left 6, lower right 7. *
  381. * (remember: camera space has x going to the right, y up and z backwards). *
  382. * *
  383. * INPUT: *
  384. * *
  385. * OUTPUT: *
  386. * *
  387. * WARNINGS: *
  388. * *
  389. * HISTORY: *
  390. * 5/16/2001 gth : Created. *
  391. *=============================================================================================*/
  392. inline const Vector3 * CameraClass::Get_View_Space_Frustum_Corners(void) const
  393. {
  394. const FrustumClass & frustum = Get_View_Space_Frustum();
  395. return frustum.Corners;
  396. }
  397. #endif