449 lines
22 KiB
C++
449 lines
22 KiB
C++
/*
|
|
** Command & Conquer Renegade(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/***********************************************************************************************
|
|
*** 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 ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : WW3D *
|
|
* *
|
|
* $Archive:: /Commando/Code/ww3d2/camera.h $*
|
|
* *
|
|
* Author:: Greg_h *
|
|
* *
|
|
* $Modtime:: 7/31/01 10:52a $*
|
|
* *
|
|
* $Revision:: 13 $*
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* CameraClass::Get_Frustum -- returns the frustum of the camera *
|
|
* CameraClass::Get_Frustum_Planes -- returns pointer to the array of frustum planes *
|
|
* CameraClass::Get_Frustum_Corners -- returns pointer to the array of frustum corners *
|
|
* CameraClass::Get_View_Space_Frustum -- returns the view-space frustum for this camera *
|
|
* CameraClass::Get_View_Space_Frustum_Planes -- returns the view space clip planes for this *
|
|
* CameraClass::Get_View_Space_Frustum_Corners -- returns the corners of the view space frus *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma once
|
|
#endif
|
|
|
|
#ifndef CAMERA_H
|
|
#define CAMERA_H
|
|
|
|
#include "always.h"
|
|
#include "rendobj.h"
|
|
#include "plane.h"
|
|
#include "frustum.h"
|
|
#include "obbox.h"
|
|
#include "vector2.h"
|
|
#include "matrix4.h"
|
|
#include "colmath.h"
|
|
|
|
class RenderInfoClass;
|
|
|
|
/**
|
|
** ViewportClass
|
|
** This class is used to define a "normalized" screen space rectangle for the
|
|
** camera to render into. A viewport which filled the entire screen would be
|
|
** (0,0) - (1,1) with 0,0 being the upper left and 1,1 being the lower right.
|
|
*/
|
|
class ViewportClass
|
|
{
|
|
public:
|
|
ViewportClass(void) : Min(0,0), Max(1,1) { }
|
|
ViewportClass(const Vector2 & min,const Vector2 & max) : Min(min), Max(max) { }
|
|
ViewportClass(const ViewportClass & vp) : Min(vp.Min), Max(vp.Max) { }
|
|
|
|
float Width(void) const { return Max.X - Min.X; }
|
|
float Height(void) const { return Max.Y - Min.Y; }
|
|
|
|
Vector2 Min;
|
|
Vector2 Max;
|
|
};
|
|
|
|
|
|
/**
|
|
** CameraClass
|
|
** This object controls how vertices are transformed from world-space to view
|
|
** space, the parameters of the perspective projection, and the viewport
|
|
** on screen that the result is mapped into.
|
|
**
|
|
** Cameras are not "rendered" and do not need to be "added" to a scene. A
|
|
** CameraClass is passed into the WW3D::Render(...) function. The reason
|
|
** they are render objects is so that they can be inserted onto the bone of
|
|
** some animation and move with the animation...
|
|
**
|
|
** For all of the projection functions (Matrix4, ProjectorClass (used by
|
|
** decals and texture projections), and CameraClass) I followed the OpenGL
|
|
** convention of passing positive distances for your clip planes even though
|
|
** in a right-handed coordinate system your z values are negative after
|
|
** transformation to camera space. So Set_Clip_Planes expects positive distances
|
|
** to your near and far clip planes.
|
|
**
|
|
** (gth) We should probably separate CameraClass from RenderObjClass... In the
|
|
** case where a camera is using a transform from an animation; the programmer
|
|
** is usually requesting the transform and plugging it into the camera anyway.
|
|
*/
|
|
class CameraClass : public RenderObjClass
|
|
{
|
|
public:
|
|
|
|
enum ProjectionType
|
|
{
|
|
PERSPECTIVE = 0,
|
|
ORTHO
|
|
};
|
|
|
|
enum ProjectionResType
|
|
{
|
|
INSIDE_FRUSTUM,
|
|
OUTSIDE_FRUSTUM,
|
|
OUTSIDE_NEAR_CLIP,
|
|
OUTSIDE_FAR_CLIP,
|
|
};
|
|
|
|
CameraClass(void);
|
|
CameraClass(const CameraClass & src);
|
|
CameraClass & operator = (const CameraClass &);
|
|
virtual ~CameraClass(void);
|
|
virtual RenderObjClass * Clone(void) const;
|
|
virtual int Class_ID(void) const { return CLASSID_CAMERA; }
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Render Object Interface - Rendering, cameras don't "render"
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
virtual void Render(RenderInfoClass & rinfo) { }
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Render Object Interface - "Scene Graph"
|
|
// Cameras cache their frustum description, this is invalidated whenever
|
|
// the transform/position is changed
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
virtual void Set_Transform(const Matrix3D &m);
|
|
virtual void Set_Position(const Vector3 &v);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Render Object Interface - Bounding Volumes
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
virtual void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const;
|
|
virtual void Get_Obj_Space_Bounding_Box(AABoxClass & box) const;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Camera parameter control
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Depth of the scene.
|
|
float Get_Depth(void) const;
|
|
|
|
// Setting the projection type
|
|
void Set_Projection_Type(ProjectionType ptype);
|
|
ProjectionType Get_Projection_Type(void);
|
|
|
|
// Setting the clipping ranges in world space distances
|
|
void Set_Clip_Planes(float znear,float zfar);
|
|
void Get_Clip_Planes(float & znear,float & zfar) const;
|
|
|
|
// Methods for setting the View Plane.
|
|
// NOTE: View plane is always at a distance of 1.0 from the eye.
|
|
void Set_View_Plane(const Vector2 & min,const Vector2 & max);
|
|
void Set_View_Plane(float hfov,float vfov = -1);
|
|
void Set_Aspect_Ratio(float width_to_height);
|
|
|
|
// Methods for querying the View Plane settings.
|
|
void Get_View_Plane(Vector2 & set_min,Vector2 & set_max) const;
|
|
float Get_Horizontal_FOV(void) const;
|
|
float Get_Vertical_FOV(void) const;
|
|
float Get_Aspect_Ratio(void) const;
|
|
|
|
// Access to the projection matrices for this camera
|
|
void Get_Projection_Matrix(Matrix4 * set_tm);
|
|
void Get_D3D_Projection_Matrix(Matrix4 * set_tm);
|
|
void Get_View_Matrix(Matrix3D * set_tm);
|
|
const Matrix4 & Get_Projection_Matrix(void);
|
|
const Matrix3D & Get_View_Matrix(void);
|
|
|
|
// Projecting and Un-Projecting a point
|
|
ProjectionResType Project(Vector3 & dest,const Vector3 & ws_point) const;
|
|
ProjectionResType Project_Camera_Space_Point(Vector3 & dest,const Vector3 & cam_point) const;
|
|
void Un_Project(Vector3 & dest,const Vector2 & view_point) const;
|
|
void Transform_To_View_Space(Vector3 & dest,const Vector3 & ws_point) const;
|
|
void Rotate_To_View_Space(Vector3 & dest,const Vector3 & ws_vector) const;
|
|
|
|
// Viewport control
|
|
void Set_Viewport(const Vector2 & min,const Vector2 & max);
|
|
void Get_Viewport(Vector2 & set_min,Vector2 & set_max) const;
|
|
const ViewportClass & Get_Viewport(void) const;
|
|
|
|
void Set_Depth_Range(float zstart = 0.0f,float zend = 1.0f);
|
|
void Get_Depth_Range(float * set_zstart,float * set_zend) const;
|
|
|
|
// Culling for various bounding volumes. These functions will return true if the
|
|
// given primitive is culled (i.e. it is *outside* the view frustum)
|
|
bool Cull_Sphere(const SphereClass & sphere) const;
|
|
bool Cull_Sphere_On_Frustum_Sides(const SphereClass & sphere) const;
|
|
bool Cull_Box(const AABoxClass & box) const;
|
|
|
|
// Various properties of the camera's frustum: These funcitons return a
|
|
// pointer to the internal storage of the descriptions. there will be
|
|
// 6 frustum planes, 8 corner points, see the implementations of these
|
|
// functions for definitions on which points/planes are associated with
|
|
// each index. Better yet, just use the Frustum object.
|
|
const FrustumClass & Get_Frustum(void) const;
|
|
const PlaneClass * Get_Frustum_Planes(void) const;
|
|
const Vector3 * Get_Frustum_Corners(void) const;
|
|
const FrustumClass & Get_View_Space_Frustum(void) const;
|
|
const PlaneClass * Get_View_Space_Frustum_Planes(void) const;
|
|
const Vector3 * Get_View_Space_Frustum_Corners(void) const;
|
|
const OBBoxClass & Get_Near_Clip_Bounding_Box(void) const;
|
|
|
|
// Methods for transforming/projecting points between various coordinate systems
|
|
// associated with this camera.
|
|
// "Device Space" - pixel coordinate
|
|
// "View Space" - 3D space where the view point is at 0,0,0 and the view plane is at z=-1.0
|
|
// "World Space" - 3D world coordinate system.
|
|
void Device_To_View_Space(const Vector2 & device_coord,Vector3 * view_coord);
|
|
void Device_To_World_Space(const Vector2 & device_coord,Vector3 * world_coord);
|
|
float Compute_Projected_Sphere_Radius(float dist,float radius);
|
|
|
|
// apply this camera's settings into d3d.
|
|
void Apply(void);
|
|
|
|
// utility class to convert to old space of 0..1
|
|
static void Convert_Old(Vector3 &pos);
|
|
|
|
protected:
|
|
|
|
void Update_Frustum(void) const;
|
|
|
|
ProjectionType Projection; // projection type, orthographic or perspective
|
|
ViewportClass Viewport; // pixel viewport to render into
|
|
ViewportClass ViewPlane; // corners of a slice through the frustum at z=-1.0
|
|
float AspectRatio; // aspect ratio of the camera, width / height
|
|
float ZNear; // near clip plane distance
|
|
float ZFar; // far clip plane distance
|
|
float ZBufferMin; // smallest value we'll write into the z-buffer (usually 0.0)
|
|
float ZBufferMax; // largest value we'll write into the z-buffer (usually 1.0)
|
|
|
|
mutable bool FrustumValid;
|
|
mutable FrustumClass Frustum; // world-space frustum and clip planes
|
|
mutable FrustumClass ViewSpaceFrustum; // view-space frustum and clip planes
|
|
mutable OBBoxClass NearClipBBox; // obbox which bounds the near clip plane
|
|
mutable Matrix4 ProjectionTransform;
|
|
mutable Matrix3D CameraInvTransform;
|
|
};
|
|
|
|
|
|
inline float CameraClass::Get_Depth(void) const
|
|
{
|
|
return ZFar;
|
|
}
|
|
|
|
inline void CameraClass::Set_Projection_Type(ProjectionType ptype)
|
|
{
|
|
FrustumValid = false;
|
|
Projection = ptype;
|
|
}
|
|
|
|
inline CameraClass::ProjectionType CameraClass::Get_Projection_Type(void)
|
|
{
|
|
return Projection;
|
|
}
|
|
|
|
inline void CameraClass::Set_Viewport(const Vector2 & min,const Vector2 & max)
|
|
{
|
|
Viewport.Min = min; Viewport.Max = max;
|
|
FrustumValid = false;
|
|
}
|
|
|
|
inline void CameraClass::Get_Viewport(Vector2 & set_min,Vector2 & set_max) const
|
|
{
|
|
set_min = Viewport.Min;
|
|
set_max = Viewport.Max;
|
|
}
|
|
|
|
inline void CameraClass::Set_Depth_Range(float zmin,float zmax)
|
|
{
|
|
ZBufferMin = zmin;
|
|
ZBufferMax = zmax;
|
|
}
|
|
|
|
inline void CameraClass::Get_Depth_Range(float * set_zmin,float * set_zmax) const
|
|
{
|
|
if (set_zmin != NULL) {
|
|
*set_zmin = ZBufferMin;
|
|
}
|
|
if (set_zmax != NULL) {
|
|
*set_zmax = ZBufferMax;
|
|
}
|
|
}
|
|
|
|
inline const ViewportClass & CameraClass::Get_Viewport(void) const
|
|
{
|
|
return Viewport;
|
|
}
|
|
|
|
inline bool CameraClass::Cull_Sphere(const SphereClass & sphere) const
|
|
{
|
|
const FrustumClass & frustum = Get_Frustum();
|
|
return CollisionMath::Overlap_Test(frustum,sphere) == CollisionMath::OUTSIDE;
|
|
}
|
|
|
|
inline bool CameraClass::Cull_Sphere_On_Frustum_Sides(const SphereClass & sphere) const
|
|
{
|
|
const FrustumClass & frustum = Get_Frustum();
|
|
const PlaneClass * planes = frustum.Planes;
|
|
bool is_visible = true;
|
|
for (int i = 1; i < 5; i++) {
|
|
is_visible = is_visible && (CollisionMath::Overlap_Test(planes[i],sphere) & (CollisionMath::INSIDE|CollisionMath::BOTH));
|
|
}
|
|
return !is_visible;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CameraClass::Get_Frustum -- returns the frustum of the camera *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 3/24/99 GTH : Created. *
|
|
*=============================================================================================*/
|
|
inline const FrustumClass &
|
|
CameraClass::Get_Frustum(void) const
|
|
{
|
|
Update_Frustum();
|
|
return Frustum;
|
|
}
|
|
|
|
/***********************************************************************************************
|
|
* CameraClass::Get_Frustum_Planes -- returns pointer to the array of frustum planes *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 5/29/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
inline const PlaneClass *
|
|
CameraClass::Get_Frustum_Planes(void) const
|
|
{
|
|
const FrustumClass & frustum = Get_Frustum();
|
|
return frustum.Planes;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CameraClass::Get_Frustum_Corners -- returns pointer to the array of frustum corners *
|
|
* *
|
|
* The camera frustum corner FrustumCorners are defined in the following order *
|
|
* The first four points lie on the near clipping plane: *
|
|
* upper left 0, upper right 1, lower left 2, lower right 3. *
|
|
* The last four points lie on the far clipping plane, numbered analogous fashion. *
|
|
* upper left 4, upper right 5, lower left 6, lower right 7. *
|
|
* (remember: the camera space has x going to the right, y up and z backwards). *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 5/29/98 GTH : Created. *
|
|
*=============================================================================================*/
|
|
inline const Vector3 *
|
|
CameraClass::Get_Frustum_Corners(void) const
|
|
{
|
|
const FrustumClass & frustum = Get_Frustum();
|
|
return frustum.Corners;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CameraClass::Get_View_Space_Frustum -- returns the view-space frustum for this camera *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 5/16/2001 gth : Created. *
|
|
*=============================================================================================*/
|
|
inline const FrustumClass & CameraClass::Get_View_Space_Frustum(void) const
|
|
{
|
|
Update_Frustum();
|
|
return ViewSpaceFrustum;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CameraClass::Get_View_Space_Frustum_Planes -- returns the view space clip planes for this c *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 5/16/2001 gth : Created. *
|
|
*=============================================================================================*/
|
|
inline const PlaneClass * CameraClass::Get_View_Space_Frustum_Planes(void) const
|
|
{
|
|
const FrustumClass & frustum = Get_View_Space_Frustum();
|
|
return frustum.Planes;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* CameraClass::Get_View_Space_Frustum_Corners -- returns the corners of the view space frustu *
|
|
* *
|
|
* The camera frustum corner FrustumCorners are defined in the following order *
|
|
* The first four points lie on the near clipping plane: *
|
|
* upper left 0, upper right 1, lower left 2, lower right 3. *
|
|
* The last four points lie on the far clipping plane, numbered analogous fashion. *
|
|
* upper left 4, upper right 5, lower left 6, lower right 7. *
|
|
* (remember: camera space has x going to the right, y up and z backwards). *
|
|
* *
|
|
* INPUT: *
|
|
* *
|
|
* OUTPUT: *
|
|
* *
|
|
* WARNINGS: *
|
|
* *
|
|
* HISTORY: *
|
|
* 5/16/2001 gth : Created. *
|
|
*=============================================================================================*/
|
|
inline const Vector3 * CameraClass::Get_View_Space_Frustum_Corners(void) const
|
|
{
|
|
const FrustumClass & frustum = Get_View_Space_Frustum();
|
|
return frustum.Corners;
|
|
}
|
|
|
|
|
|
#endif
|