661 lines
22 KiB
C++
661 lines
22 KiB
C++
//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//=============================================================================//
|
|
|
|
#ifndef CAMERA_H
|
|
#define CAMERA_H
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
// For vec_t, put this somewhere else?
|
|
#include "tier0/basetypes.h"
|
|
#include "mathlib/vector.h"
|
|
|
|
#include "tier0/dbg.h"
|
|
#include "mathlib/vector2d.h"
|
|
#include "mathlib/math_pfns.h"
|
|
#include "mathlib/vmatrix.h"
|
|
#include "mathlib/ssemath.h"
|
|
#include "datamap.h"
|
|
#include "mathlib/aabb.h"
|
|
|
|
#include "tier0/memalloc.h"
|
|
// declarations for camera and frustum
|
|
|
|
extern VMatrix g_matViewToCameraMatrix, g_matCameraToViewMatrix;
|
|
|
|
struct ALIGN16 Camera_t
|
|
{
|
|
void Init( const Vector &origin, const QAngle &angles, float flNear, float flFar, float flFOV, float flAspect );
|
|
void InitOrtho( const Vector &origin, const QAngle &angles, float flNear, float flFar, float flWidth, float flHeight );
|
|
|
|
void InitViewParameters( const Vector &vOrigin, const QAngle &vAngles );
|
|
|
|
void InitOrthoProjection( float flZNear, float flZFar, float flWidth, float flHeight );
|
|
bool IsOrthographic() const;
|
|
void InitPerspectiveProjection( float flZNear, float flZFar, float flFOVX, float flAspect );
|
|
// generates 8 vertices of the frustum
|
|
// vertex order is near plane (UL, UR, LL, LR), far plane (UL, UR, LL, LR)
|
|
void ComputeGeometry( Vector *pVertsOut8 ) const;
|
|
void ComputeGeometry( Vector *pVertsOut8, const Vector &vForward, const Vector &vLeft, const Vector &vUp ) const;
|
|
|
|
inline bool operator ==( const Camera_t &other ) const;
|
|
inline bool operator !=( const Camera_t &other ) const;
|
|
|
|
Vector m_origin;
|
|
QAngle m_angles;
|
|
|
|
// FOV for X/width.
|
|
// This should be set to -1 to get an ortho projection,
|
|
// in which case it'll use m_flWidth and m_flHeight.
|
|
float m_flFOVX;
|
|
float m_flAspect; // For Perspective
|
|
|
|
float m_flZNear;
|
|
float m_flZFar;
|
|
|
|
float m_flWidth; // For ortho.
|
|
float m_flHeight;
|
|
} ALIGN16_POST;
|
|
|
|
inline void Camera_t::Init( const Vector &origin, const QAngle &angles, float flNear, float flFar, float flFOV, float flAspect )
|
|
{
|
|
InitViewParameters( origin, angles );
|
|
InitPerspectiveProjection( flNear, flFar, flFOV, flAspect );
|
|
m_flWidth = -1;
|
|
m_flHeight = -1;
|
|
}
|
|
|
|
inline void Camera_t::InitOrtho( const Vector &origin, const QAngle &angles, float flNear, float flFar, float flWidth, float flHeight )
|
|
{
|
|
InitViewParameters( origin, angles );
|
|
InitOrthoProjection( flNear, flFar, flWidth, flHeight );
|
|
}
|
|
|
|
|
|
inline void Camera_t::InitViewParameters( const Vector &vOrigin, const QAngle &vAngles )
|
|
{
|
|
m_origin = vOrigin;
|
|
m_angles = vAngles;
|
|
}
|
|
|
|
inline void Camera_t::InitOrthoProjection( float flZNear, float flZFar, float flWidth, float flHeight )
|
|
{
|
|
m_flFOVX = -1;
|
|
m_flZNear = flZNear;
|
|
m_flZFar = flZFar;
|
|
m_flWidth = flWidth;
|
|
m_flHeight = flHeight;
|
|
}
|
|
|
|
inline bool Camera_t::IsOrthographic() const
|
|
{
|
|
return m_flFOVX == -1;
|
|
}
|
|
|
|
inline void Camera_t::InitPerspectiveProjection( float flZNear, float flZFar, float flFOVX, float flAspect )
|
|
{
|
|
m_flFOVX = flFOVX;
|
|
m_flAspect = flAspect;
|
|
m_flZNear = flZNear;
|
|
m_flZFar = flZFar;
|
|
}
|
|
|
|
inline bool Camera_t::operator ==( const Camera_t &other ) const
|
|
{
|
|
return ( m_origin == other.m_origin ) &&
|
|
( m_angles == other.m_angles ) &&
|
|
( m_flFOVX == other.m_flFOVX ) &&
|
|
( m_flAspect == other.m_flAspect ) &&
|
|
( m_flZNear == other.m_flZNear ) &&
|
|
( m_flZFar == other.m_flZFar ) &&
|
|
( m_flWidth == other.m_flWidth ) &&
|
|
( m_flHeight == other.m_flHeight );
|
|
}
|
|
|
|
|
|
inline bool Camera_t::operator !=( const Camera_t &other ) const
|
|
{
|
|
return !( *this == other );
|
|
}
|
|
|
|
|
|
///\name Functions to set up a VMatrix from various input view specifications
|
|
//@{
|
|
/// This maps the X/Y bounds into [-1,1] and flNear/flFar into [0,1]
|
|
inline VMatrix OrthoMatrixRH( float x1, float y1, float x2, float y2, float flNear, float flFar )
|
|
{
|
|
float flDelta = flNear - flFar;
|
|
|
|
float ix = 2.0f / ( x2 - x1 );
|
|
float iy = 2.0f / ( y2 - y1 );
|
|
|
|
VMatrix mRet(
|
|
ix, 0, 0, 0,
|
|
0, iy, 0, 0,
|
|
0, 0, 1.0f / flDelta, flNear / flDelta,
|
|
0, 0, 0, 1 );
|
|
|
|
return mRet;
|
|
}
|
|
|
|
inline VMatrix OrthoMatrixOffCenterRH( float x1, float y1, float x2, float y2, float flNear, float flFar )
|
|
{
|
|
float flDelta = flNear - flFar;
|
|
|
|
float ix = 2.0f / ( x2 - x1 );
|
|
float iy = 2.0f / ( y2 - y1 );
|
|
|
|
VMatrix mRet(
|
|
ix, 0, 0, -(ix * x1) - 1,
|
|
0, iy, 0, -(iy * y1) - 1,
|
|
0, 0, 1.0f / flDelta, flNear / flDelta,
|
|
0, 0, 0, 1 );
|
|
|
|
return mRet;
|
|
}
|
|
|
|
/// This maps the X/Y bounds into [-1,1] and flNear/flFar into [0,1]
|
|
/// This is left-handed for concatenation onto the viewproj matrix for app-tiling in source2
|
|
inline VMatrix OrthoMatrixOffCenterLH( float x1, float y1, float x2, float y2, float flNear, float flFar )
|
|
{
|
|
float flDelta = flFar - flNear;
|
|
|
|
float ix = 2.0f / ( x2 - x1 );
|
|
float iy = 2.0f / ( y2 - y1 );
|
|
|
|
VMatrix mRet(
|
|
ix, 0, 0, 0,
|
|
0, iy, 0, 0,
|
|
0, 0, 1.0f / flDelta, 0,
|
|
( x1 + x2 )/( x1 - x2 ), ( y1 + y2 ) / ( y1 - y2 ), -flNear / flDelta, 1 );
|
|
|
|
return mRet;
|
|
}
|
|
|
|
/// This is the hammer wireframe widget version that inverts depth and shifts the xy coordinates
|
|
inline VMatrix OrthoMatrixHammerRH( float x1, float y1, float x2, float y2, float flNear, float flFar )
|
|
{
|
|
float flDelta = flNear - flFar;
|
|
|
|
float ix = 2.0f / ( x2 - x1 );
|
|
float iy = 2.0f / ( y2 - y1 );
|
|
|
|
VMatrix mRet(
|
|
ix, 0, 0, -(ix * x1) - 1,
|
|
0, iy, 0, -(iy * y1) - 1,
|
|
0, 0, 1.0f / flDelta, -flNear / flDelta,
|
|
0, 0, 0, 1 );
|
|
|
|
return mRet;
|
|
}
|
|
|
|
|
|
|
|
/// helper to calculate an ortho matrix for a view region centered at 0 of specified width and height
|
|
inline VMatrix OrthoMatrixRH( float flWidth, float flHeight, float flNear, float flFar )
|
|
{
|
|
return OrthoMatrixRH( -flWidth/2, -flHeight/2, flWidth/2, flHeight/2, flNear, flFar );
|
|
}
|
|
|
|
/// calculate a view matrix given an origin, forward vector, and up vector
|
|
VMatrix ViewMatrixRH( Vector &vEye, Vector &vAt, Vector &vUp );
|
|
|
|
/// calculate a VMatrix from a camera_t
|
|
void ComputeViewMatrix( VMatrix *pWorldToView, const Camera_t& camera );
|
|
/// calculate a matrix3x4_t corresponding to a camera_t
|
|
void ComputeViewMatrix( matrix3x4_t *pWorldToView, const Camera_t& camera );
|
|
void ComputeViewMatrix( matrix3x4_t *pWorldToView, matrix3x4_t *pWorldToCamera, const Camera_t &camera );
|
|
void ComputeViewMatrix( matrix3x4_t *pWorldToView, matrix3x4_t *pCameraToWorld,
|
|
Vector const &vecOrigin,
|
|
Vector const &vecForward, Vector const &vecLeft, Vector const &vecUp );
|
|
|
|
void ComputeViewMatrix( VMatrix *pViewMatrix, const Vector &origin, const QAngle &angles );
|
|
void ComputeViewMatrix( VMatrix *pViewMatrix, const matrix3x4_t &matGameCustom );
|
|
|
|
void ComputeProjectionMatrix( VMatrix *pCameraToProjection, const Camera_t& camera, int width, int height );
|
|
void ComputeProjectionMatrix( VMatrix *pCameraToProjection, float flZNear, float flZFar, float flFOVX, float flAspectRatio );
|
|
void ComputeProjectionMatrix( VMatrix *pCameraToProjection, float flZNear, float flZFar, float flFOVX, float flAspectRatio,
|
|
float flClipSpaceBottomLeftX, float flClipSpaceBottomLeftY,
|
|
float flClipSpaceTopRightX, float flClipSpaceTopRightY );
|
|
|
|
//@}
|
|
|
|
|
|
void CalcFarPlaneCameraRelativePoints( Vector *p4PointsOut, Vector &vForward, Vector &vUp, Vector &vLeft, float flFarPlane,
|
|
float flFovX, float flFovY,
|
|
float flClipSpaceBottomLeftX = -1.0f, float flClipSpaceBottomLeftY = -1.0f,
|
|
float flClipSpaceTopRightX = 1.0f, float flClipSpaceTopRightY = 1.0f );
|
|
|
|
/// transform a point from 3d to 2d, given screen width + height
|
|
void ComputeScreenSpacePosition( Vector2D *pScreenPosition, const Vector &vecWorldPosition,
|
|
const Camera_t &camera, int width, int height );
|
|
|
|
|
|
|
|
// Functions to build frustum information given params
|
|
void MatricesFromCamera( VMatrix &mWorldToView, VMatrix &mProjection, const Camera_t &camera,
|
|
float flClipSpaceBottomLeftX = -1.0f, float flClipSpaceBottomLeftY = -1.0f,
|
|
float flClipSpaceTopRightX = 1.0f, float flClipSpaceTopRightY = 1.0f );
|
|
void FrustumFromViewProj( Frustum_t *pFrustum, const VMatrix &mViewProj, const Vector &origin, bool bD3DClippingRange = true );
|
|
void FrustumFromMatrices( Frustum_t *pFrustum, const VMatrix &mWorldToView, const VMatrix &mProjection, const Vector &origin, bool bD3DClippingRange = true );
|
|
// TODO: desired api.
|
|
//void MatrixFromFrustum( VMatrix *pViewProj, const Frustum_t &frustum );
|
|
VMatrix ViewProjFromVectors( const Vector &origin, float flNear, float flFar, float flFOV, float flAspect,
|
|
Vector const &vecForward, Vector const &vecLeft, Vector const &vecUp );
|
|
|
|
enum EBoxOverlapFlags
|
|
{
|
|
BOXCHECK_FLAGS_OVERLAPS_NEAR = 1,
|
|
BOXCHECK_FLAGS_OVERLAPS_FAR = 2,
|
|
};
|
|
|
|
|
|
|
|
|
|
/// Class holding a camera, frustum planes, and transformation matrices, and methods to calculate
|
|
/// them and keep them in sync.
|
|
class CFrustum
|
|
{
|
|
public:
|
|
CFrustum();
|
|
~CFrustum(){}
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Camera fxns
|
|
//--------------------------------------------------------------------------------------------------
|
|
void InitCamera( const Camera_t &Other )
|
|
{
|
|
m_camera = Other;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
// For an off-center projection:
|
|
// flClipSpaceXXXX coordinates are in clip space, where ( -1,-1 ) is the bottom left corner of the screen
|
|
// and ( 1,1 ) is the top right corner of the screen.
|
|
void InitCamera( const Vector &origin, const QAngle &angles, float flNear, float flFar, float flFOV, float flAspect,
|
|
float flClipSpaceBottomLeftX = -1.0f, float flClipSpaceBottomLeftY = -1.0f, float flClipSpaceTopRightX = 1.0f, float flClipSpaceTopRightY = 1.0f )
|
|
{
|
|
m_camera.Init( origin, angles, flNear, flFar, flFOV, flAspect );
|
|
|
|
m_flClipSpaceBottomLeftX = flClipSpaceBottomLeftX;
|
|
m_flClipSpaceBottomLeftY = flClipSpaceBottomLeftY;
|
|
m_flClipSpaceTopRightX = flClipSpaceTopRightX;
|
|
m_flClipSpaceTopRightY = flClipSpaceTopRightY;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
void InitOrthoCamera( const Vector &origin, const QAngle &angles, float flNear, float flFar, float flWidth, float flHeight,
|
|
float flClipSpaceBottomLeftX = -1.0f, float flClipSpaceBottomLeftY = -1.0f, float flClipSpaceTopRightX = 1.0f, float flClipSpaceTopRightY = 1.0f )
|
|
{
|
|
m_camera.InitOrtho( origin, angles, flNear, flFar, flWidth, flHeight );
|
|
m_camera.m_flAspect = flWidth / flHeight;
|
|
|
|
m_flClipSpaceBottomLeftX = flClipSpaceBottomLeftX;
|
|
m_flClipSpaceBottomLeftY = flClipSpaceBottomLeftY;
|
|
m_flClipSpaceTopRightX = flClipSpaceTopRightX;
|
|
m_flClipSpaceTopRightY = flClipSpaceTopRightY;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
bool IsOrthographic() const { return m_camera.IsOrthographic(); }
|
|
|
|
void SetCameraPosition( const Vector &origin );
|
|
const Vector &GetCameraPosition() const { return m_camera.m_origin; }
|
|
|
|
void SetCameraAngles( const QAngle &angles );
|
|
const QAngle &GetCameraAngles() const { return m_camera.m_angles; }
|
|
|
|
// Sets the distance from the camera to the near/far clipping plane in world units.
|
|
void SetCameraNearFarPlanes( float flNear, float flFar );
|
|
void GetCameraNearFarPlanes( float &flNear, float &flFar ) const { flNear = m_camera.m_flZNear; flFar = m_camera.m_flZFar; }
|
|
|
|
// Sets the distance from the camera to the near clipping plane in world units.
|
|
void SetCameraNearPlane( float flNear );
|
|
float GetCameraNearPlane() const { return m_camera.m_flZNear; }
|
|
|
|
// Sets the distance from the camera to the far clipping plane in world units.
|
|
void SetCameraFarPlane( float flFar );
|
|
float GetCameraFarPlane() const { return m_camera.m_flZFar; }
|
|
|
|
// Set the field of view (in degrees)
|
|
void SetCameraFOV( float flFOV );
|
|
float GetCameraFOV() const { return m_camera.m_flFOVX; }
|
|
|
|
void SetCameraWidthHeight( float flWidth, float flHeight );
|
|
void GetCameraWidthHeight( float &width, float &height ) const { width = m_camera.m_flWidth; height = m_camera.m_flHeight; }
|
|
|
|
void SetCameraWidth( float flWidth );
|
|
float GetCameraWidth() const { return m_camera.m_flWidth; }
|
|
|
|
void SetCameraHeight( float flHeight );
|
|
float GetCameraHeight() const { return m_camera.m_flHeight; }
|
|
|
|
void SetCameraAspect( float flAspect );
|
|
float GetCameraAspect() const { return m_camera.m_flAspect; }
|
|
|
|
/// Returns mask of BOXCHECK_FLAGS_xxx indicating the status of the box with respect to this
|
|
/// frustum's near and far clip planes.
|
|
int CheckBoxAgainstNearAndFarPlanes( const VectorAligned &minBounds, const VectorAligned &maxBounds ) const;
|
|
|
|
/// given an AABB, return the values of the near and far plane which will enclose the box
|
|
void GetNearAndFarPlanesAroundBox( float *pNear, float *pFar, AABB_t const &inBox, Vector &vOriginShift ) const;
|
|
|
|
/// Compute the approximate size of a sphere. Rough calculation suitable for lod selection,
|
|
/// etc. Result is in terms of approximate % coverage of the viewport, not taking clipping
|
|
/// into account.
|
|
float ComputeScreenSize( Vector vecOrigin, float flRadius ) const;
|
|
|
|
/// Return the Sin of the FOV
|
|
FORCEINLINE float SinFOV( void ) const { return sin( DEG2RAD( GetCameraFOV() ) ); }
|
|
|
|
const Camera_t &GetCameraStruct() const { return m_camera; }
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Frustum fxns
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
void SetFrustumStruct( const Frustum_t &frustumStruct ) { m_frustumStruct = frustumStruct; }
|
|
|
|
// Camera oriented directions
|
|
const Vector &CameraForward() const { return m_forward; }
|
|
const Vector &CameraLeft() const { return m_left; }
|
|
const Vector &CameraUp() const { return m_up; }
|
|
|
|
// View oriented directions i.e. view align matrix has been applied
|
|
void ViewForward( Vector& vViewForward ) const;
|
|
void ViewLeft( Vector& vViewLeft ) const;
|
|
void ViewUp( Vector& vViewUp ) const;
|
|
|
|
void SetView( VMatrix &mWorldToView ) { m_worldToView = mWorldToView.As3x4(); }
|
|
const matrix3x4_t &GetView() const { return m_worldToView; }
|
|
|
|
void SetProj( VMatrix &mProj ) { m_projection = mProj; }
|
|
const VMatrix &GetProj() const { return m_projection; }
|
|
const VMatrix &GetInvProj() const { return m_invProjection; }
|
|
|
|
// The viewProj and invViewProj matrices are NOT transposed.
|
|
void SetViewProj( VMatrix &viewProj ) { m_viewProj = viewProj; }
|
|
const VMatrix &GetViewProj() const { return m_viewProj; }
|
|
VMatrix GetViewProjTranspose() const { return m_viewProj.Transpose(); }
|
|
|
|
void SetInvViewProj( VMatrix &invViewProj ) { m_invViewProj = invViewProj; }
|
|
const VMatrix &GetInvViewProj() const { return m_invViewProj; }
|
|
VMatrix GetInvViewProjTranspose() const { return m_invViewProj.Transpose(); }
|
|
|
|
bool BoundingVolumeIntersectsFrustum( AABB_t const &box ) const;
|
|
bool BoundingVolumeIntersectsFrustum( Vector const &mins, Vector const &maxes ) const;
|
|
bool BoundingVolumeIntersectsFrustum( AABB_t const &box, Vector &vOriginShift ) const;
|
|
|
|
/// Update the matrix and clip planes for this frustum to reflect the state of the embedded Camera_t
|
|
void UpdateFrustumFromCamera();
|
|
|
|
/// build a full frustum from rotation vectors plus camera vars
|
|
void BuildFrustumFromVectors( const Vector &origin, float flNear, float flFar, float flFOV, float flAspect,
|
|
Vector const &vecForward, Vector const &vecLeft, Vector const &vecUp );
|
|
|
|
void BuildShadowFrustum( VMatrix &newWorldToView, VMatrix &newProj );
|
|
|
|
void BuildFrustumFromParameters(
|
|
const Vector &origin, const QAngle &angles,
|
|
float flNear, float flFar, float flFOV, float flAspect,
|
|
const VMatrix &worldToView, const VMatrix &viewToProj );
|
|
|
|
/// calculate the projection of the 4 view-frustum corner rays onto a plane
|
|
void CalcFarPlaneCameraRelativePoints( Vector *p4PointsOut, float flFarPlane,
|
|
float flClipSpaceBottomLeftX = -1.0f, float flClipSpaceBottomLeftY = -1.0f,
|
|
float flClipSpaceTopRightX = 1.0f, float flClipSpaceTopRightY = 1.0f ) const;
|
|
|
|
|
|
/// concatenate the projection and view matrices, and also update the inverse view and
|
|
/// projection matrices
|
|
void CalcViewProj( );
|
|
|
|
/// Transform a point from world space into camera space.
|
|
Vector4D TransformPointToHomogenousViewCoordinates( Vector const &pnt ) const;
|
|
|
|
void SetClipSpaceBounds( float flClipSpaceBottomLeftX, float flClipSpaceBottomLeftY, float flClipSpaceTopRightX, float flClipSpaceTopRightY );
|
|
|
|
void GetClipSpaceBounds( float &flClipSpaceBottomLeftX, float &flClipSpaceBottomLeftY, float &flClipSpaceTopRightX, float &flClipSpaceTopRightY ) const
|
|
{
|
|
flClipSpaceBottomLeftX = m_flClipSpaceBottomLeftX;
|
|
flClipSpaceBottomLeftY = m_flClipSpaceBottomLeftY;
|
|
flClipSpaceTopRightX = m_flClipSpaceTopRightX;
|
|
flClipSpaceTopRightY = m_flClipSpaceTopRightY;
|
|
}
|
|
|
|
// NOTE: Not tested with ortho projections
|
|
void ComputeBounds( Vector *pMins, Vector *pMaxs ) const;
|
|
void ComputeGeometry( Vector *pVertsOut8 ) const { m_camera.ComputeGeometry( pVertsOut8, m_forward, m_left, m_up ); }
|
|
|
|
const Frustum_t &GetFrustumStruct() const { return m_frustumStruct; }
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
void ViewToWorld( const Vector2D &vViewMinusOneToOne, Vector *pOutWorld );
|
|
void BuildRay( const Vector2D &vViewMinusOneToOne, Vector *pOutRayStart, Vector *pOutRayDirection );
|
|
|
|
protected:
|
|
|
|
Camera_t m_camera; // NOTE: SIMD-aligned
|
|
|
|
Frustum_t m_frustumStruct; // NOTE: SIMD-aligned
|
|
|
|
// For off-center projection
|
|
float m_flClipSpaceBottomLeftX;
|
|
float m_flClipSpaceBottomLeftY;
|
|
float m_flClipSpaceTopRightX;
|
|
float m_flClipSpaceTopRightY;
|
|
|
|
Vector m_forward;
|
|
Vector m_left;
|
|
Vector m_up;
|
|
|
|
// Camera/view matrices. (The space order is: world->camera->view->projection->screenspace.)
|
|
matrix3x4_t m_cameraToWorld; // camera->world (NOT view->world, and not the inverse of m_worldToView)
|
|
matrix3x4_t m_worldToView; // world->view
|
|
|
|
// Projection matrices.
|
|
VMatrix m_projection; // view->proj
|
|
VMatrix m_invProjection; // proj->view
|
|
|
|
// Combined world->projection matrices.
|
|
VMatrix m_viewProj; // world->proj
|
|
VMatrix m_invViewProj; // proj->world
|
|
|
|
bool m_bDirty;
|
|
};
|
|
|
|
inline CFrustum::CFrustum()
|
|
{
|
|
InitCamera( Vector( 0, 0, 0 ), QAngle( 0, 0, 0 ), 10, 100, 90, 1.0f );
|
|
V_memset( &m_frustumStruct, 0, sizeof(Frustum_t) );
|
|
|
|
m_forward.Init( 0, 0, 0 );
|
|
m_left.Init( 0, 0, 0 );
|
|
m_up.Init( 0, 0, 0 );
|
|
|
|
V_memset( &m_cameraToWorld, 0, sizeof(matrix3x4_t) );
|
|
V_memset( &m_worldToView, 0, sizeof(matrix3x4_t) );
|
|
V_memset( &m_projection, 0, sizeof(VMatrix) );
|
|
V_memset( &m_invProjection, 0, sizeof(VMatrix) );
|
|
V_memset( &m_viewProj, 0, sizeof(VMatrix) );
|
|
V_memset( &m_invViewProj, 0, sizeof(VMatrix) );
|
|
|
|
m_bDirty = true;
|
|
}
|
|
|
|
inline void CFrustum::SetCameraPosition( const Vector &origin )
|
|
{
|
|
if ( m_camera.m_origin == origin )
|
|
return;
|
|
|
|
m_camera.m_origin = origin;
|
|
Assert( origin.IsValid() && origin.IsReasonable() );
|
|
|
|
m_bDirty = true;
|
|
}
|
|
|
|
inline void CFrustum::SetCameraAngles( const QAngle &angles )
|
|
{
|
|
if ( m_camera.m_angles == angles )
|
|
return;
|
|
|
|
m_camera.m_angles = angles;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
|
|
inline void CFrustum::SetCameraNearFarPlanes( float flNear, float flFar )
|
|
{
|
|
if ( ( m_camera.m_flZNear == flNear ) && ( m_camera.m_flZFar == flFar ) )
|
|
return;
|
|
|
|
m_camera.m_flZNear = flNear;
|
|
m_camera.m_flZFar = flFar;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
inline void CFrustum::SetCameraNearPlane( float flNear )
|
|
{
|
|
if ( m_camera.m_flZNear == flNear )
|
|
return;
|
|
|
|
m_camera.m_flZNear = flNear;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
inline void CFrustum::SetCameraFarPlane( float flFar )
|
|
{
|
|
if ( m_camera.m_flZFar == flFar )
|
|
return;
|
|
|
|
m_camera.m_flZFar = flFar;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
/// Set the field of view (in degrees)
|
|
inline void CFrustum::SetCameraFOV( float flFOV )
|
|
{
|
|
if ( m_camera.m_flFOVX == flFOV )
|
|
return;
|
|
|
|
m_camera.m_flFOVX = flFOV;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
inline void CFrustum::SetCameraWidthHeight( float flWidth, float flHeight )
|
|
{
|
|
if ( ( m_camera.m_flWidth == flWidth ) && ( m_camera.m_flHeight == flHeight ) )
|
|
return;
|
|
|
|
m_camera.m_flWidth = flWidth;
|
|
m_camera.m_flHeight = flHeight;
|
|
m_camera.m_flAspect = m_camera.m_flWidth / m_camera.m_flHeight;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
inline void CFrustum::SetCameraWidth( float flWidth )
|
|
{
|
|
if ( m_camera.m_flWidth == flWidth )
|
|
return;
|
|
|
|
m_camera.m_flWidth = flWidth;
|
|
m_camera.m_flAspect = m_camera.m_flWidth / m_camera.m_flHeight;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
inline void CFrustum::SetCameraHeight( float flHeight )
|
|
{
|
|
if ( m_camera.m_flHeight == flHeight )
|
|
return;
|
|
|
|
m_camera.m_flHeight = flHeight;
|
|
m_camera.m_flAspect = m_camera.m_flWidth / m_camera.m_flHeight;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
inline void CFrustum::SetCameraAspect( float flAspect )
|
|
{
|
|
if ( m_camera.m_flAspect == flAspect )
|
|
return;
|
|
|
|
m_camera.m_flAspect = flAspect;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
|
|
inline bool CFrustum::BoundingVolumeIntersectsFrustum( AABB_t const &box ) const
|
|
{
|
|
Vector vMins = box.m_vMinBounds - m_camera.m_origin;
|
|
Vector vMaxs = box.m_vMaxBounds - m_camera.m_origin;
|
|
return m_frustumStruct.Intersects( vMins, vMaxs );
|
|
}
|
|
|
|
inline bool CFrustum::BoundingVolumeIntersectsFrustum( Vector const &mins, Vector const &maxes ) const
|
|
{
|
|
Vector vMins = mins - m_camera.m_origin;
|
|
Vector vMaxs = maxes - m_camera.m_origin;
|
|
return m_frustumStruct.Intersects( vMins, vMaxs );
|
|
}
|
|
|
|
inline bool CFrustum::BoundingVolumeIntersectsFrustum( AABB_t const &box, Vector &vOriginShift ) const
|
|
{
|
|
Vector vMins = box.m_vMinBounds - m_camera.m_origin - vOriginShift;
|
|
Vector vMaxs = box.m_vMaxBounds - m_camera.m_origin - vOriginShift;
|
|
return m_frustumStruct.Intersects( vMins, vMaxs );
|
|
}
|
|
|
|
inline Vector4D CFrustum::TransformPointToHomogenousViewCoordinates( Vector const &pnt ) const
|
|
{
|
|
Vector4D v4Rslt;
|
|
GetViewProj().V4Mul( Vector4D( pnt.x, pnt.y, pnt.z, 1.0 ), v4Rslt );
|
|
return v4Rslt;
|
|
}
|
|
|
|
inline void CFrustum::ViewForward( Vector& vViewForward ) const
|
|
{
|
|
Vector vFrustumDir;
|
|
MatrixGetRow( VMatrix( m_worldToView ), Z_AXIS, &vFrustumDir );
|
|
VectorNormalize( vFrustumDir );
|
|
vFrustumDir = -vFrustumDir;
|
|
vViewForward = vFrustumDir;
|
|
}
|
|
|
|
inline void CFrustum::ViewLeft( Vector& vViewLeft ) const
|
|
{
|
|
Vector vFrustumDir;
|
|
MatrixGetRow( VMatrix( m_worldToView ), X_AXIS, &vFrustumDir );
|
|
VectorNormalize( vFrustumDir );
|
|
vViewLeft = -vFrustumDir;
|
|
}
|
|
|
|
inline void CFrustum::ViewUp( Vector& vViewUp ) const
|
|
{
|
|
Vector vFrustumDir;
|
|
MatrixGetRow( VMatrix( m_worldToView ), Y_AXIS, &vFrustumDir );
|
|
VectorNormalize( vFrustumDir );
|
|
vViewUp = vFrustumDir;
|
|
}
|
|
|
|
|
|
inline void CFrustum::SetClipSpaceBounds( float flClipSpaceBottomLeftX, float flClipSpaceBottomLeftY, float flClipSpaceTopRightX, float flClipSpaceTopRightY )
|
|
{
|
|
m_flClipSpaceBottomLeftX = flClipSpaceBottomLeftX;
|
|
m_flClipSpaceBottomLeftY = flClipSpaceBottomLeftY;
|
|
m_flClipSpaceTopRightX = flClipSpaceTopRightX;
|
|
m_flClipSpaceTopRightY = flClipSpaceTopRightY;
|
|
m_bDirty = true;
|
|
}
|
|
|
|
#endif // CAMERA_H
|
|
|