mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-09-19 20:16:10 +08:00
Added original SDK code for Alien Swarm.
This commit is contained in:
302
public/mathlib/camera.h
Normal file
302
public/mathlib/camera.h
Normal file
@ -0,0 +1,302 @@
|
||||
//====== Copyright <20> 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 "tier0/memalloc.h"
|
||||
// declarations for camera and frustum
|
||||
|
||||
struct Camera_t
|
||||
{
|
||||
Vector m_origin;
|
||||
QAngle m_angles;
|
||||
float m_flFOVX; // FOV for X/width
|
||||
float m_flZNear;
|
||||
float m_flZFar;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// accessors for generated matrices
|
||||
//-----------------------------------------------------------------------------
|
||||
void ComputeViewMatrix( VMatrix *pWorldToView, const Camera_t& camera );
|
||||
void ComputeViewMatrix( matrix3x4_t *pWorldToView, const Camera_t& camera );
|
||||
void ComputeViewMatrix( matrix3x4_t *pWorldToView, matrix3x4_t *pWorldToCamera, const Camera_t &camera );
|
||||
void ComputeProjectionMatrix( VMatrix *pCameraToProjection, const Camera_t& camera, int width, int height );
|
||||
void ComputeProjectionMatrix( VMatrix *pCameraToProjection, float flZNear, float flZFar, float flFOVX, float flAspectRatio );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Computes the screen space position given a screen size
|
||||
//-----------------------------------------------------------------------------
|
||||
void ComputeScreenSpacePosition( Vector2D *pScreenPosition, const Vector &vecWorldPosition,
|
||||
const Camera_t &camera, int width, int height );
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// AABB
|
||||
//--------------------------------------------------------------------------------------
|
||||
struct AABB_t
|
||||
{
|
||||
DECLARE_BYTESWAP_DATADESC();
|
||||
|
||||
Vector m_vMinBounds;
|
||||
Vector m_vMaxBounds;
|
||||
|
||||
Vector GetCenter() const { return ( m_vMaxBounds + m_vMinBounds ) / 2.0f; }
|
||||
|
||||
float GetMinDistToPoint( const Vector &vPoint ) const
|
||||
{
|
||||
return CalcDistanceToAABB( m_vMinBounds, m_vMaxBounds, vPoint );
|
||||
}
|
||||
|
||||
void CreatePlanesFrom( Vector4D *pPlanes ) const
|
||||
{
|
||||
// X
|
||||
pPlanes[0] = Vector4D( 1, 0, 0, -m_vMaxBounds.x );
|
||||
pPlanes[1] = Vector4D( -1, 0, 0, m_vMinBounds.x );
|
||||
|
||||
// Y
|
||||
pPlanes[2] = Vector4D( 0, 1, 0, -m_vMaxBounds.y );
|
||||
pPlanes[3] = Vector4D( 0, -1, 0, m_vMinBounds.y );
|
||||
|
||||
// Z
|
||||
pPlanes[4] = Vector4D( 0, 0, 1, -m_vMaxBounds.z );
|
||||
pPlanes[5] = Vector4D( 0, 0, -1, m_vMinBounds.z );
|
||||
}
|
||||
|
||||
// set the aabb to be invalid (max < min )
|
||||
void MakeInvalid( void )
|
||||
{
|
||||
m_vMinBounds.Init( FLT_MAX, FLT_MAX, FLT_MAX );
|
||||
m_vMaxBounds.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class CFrustum
|
||||
{
|
||||
public:
|
||||
CFrustum()
|
||||
{
|
||||
}
|
||||
|
||||
~CFrustum()
|
||||
{
|
||||
}
|
||||
|
||||
bool 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_frustum.CullBox( vMins, vMaxs );
|
||||
}
|
||||
|
||||
bool BoundingVolumeIntersectsFrustum( Vector const &mins, Vector const &maxes ) const
|
||||
{
|
||||
Vector vMins = mins - m_camera.m_origin;
|
||||
Vector vMaxs = maxes - m_camera.m_origin;
|
||||
return !m_frustum.CullBox( vMins, vMaxs );
|
||||
}
|
||||
|
||||
bool 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_frustum.CullBox( vMins, vMaxs );
|
||||
}
|
||||
|
||||
FORCEINLINE bool CheckBoxInline( const VectorAligned &mins, const VectorAligned &maxs )
|
||||
{
|
||||
fltx4 fl4Origin = LoadAlignedSIMD( &m_camera.m_origin );
|
||||
fltx4 mins4 = SubSIMD( LoadAlignedSIMD( &mins.x ), fl4Origin );
|
||||
fltx4 maxs4 = SubSIMD( LoadAlignedSIMD( &maxs.x ), fl4Origin );
|
||||
|
||||
fltx4 minx = SplatXSIMD(mins4);
|
||||
fltx4 miny = SplatYSIMD(mins4);
|
||||
fltx4 minz = SplatZSIMD(mins4);
|
||||
fltx4 maxx = SplatXSIMD(maxs4);
|
||||
fltx4 maxy = SplatYSIMD(maxs4);
|
||||
fltx4 maxz = SplatZSIMD(maxs4);
|
||||
|
||||
// compute the dot product of the normal and the farthest corner
|
||||
// dotBack0 = DotProduct( normal, normals.x < 0 ? mins.x : maxs.x );
|
||||
for ( int i = 0; i < 2; i++ )
|
||||
{
|
||||
fltx4 xTotalBack = MulSIMD( m_frustum.planes[i].nX, MaskedAssign( m_frustum.planes[i].xSign, minx, maxx ) );
|
||||
fltx4 yTotalBack = MulSIMD( m_frustum.planes[i].nY, MaskedAssign( m_frustum.planes[i].ySign, miny, maxy ) );
|
||||
fltx4 zTotalBack = MulSIMD( m_frustum.planes[i].nZ, MaskedAssign( m_frustum.planes[i].zSign, minz, maxz ) );
|
||||
fltx4 dotBack = AddSIMD( xTotalBack, AddSIMD(yTotalBack, zTotalBack) );
|
||||
// if plane of the farthest corner is behind the plane, then the box is completely outside this plane
|
||||
#if _X360
|
||||
if ( !XMVector3GreaterOrEqual( dotBack, m_frustum.planes[i].dist ) )
|
||||
return false;
|
||||
#else
|
||||
fltx4 isOut = CmpLtSIMD( dotBack, m_frustum.planes[i].dist );
|
||||
if ( IsAnyNegative(isOut) )
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetNearAndFarPlanesAroundBox( float *pNear, float *pFar, AABB_t const &inBox, Vector &vOriginShift ) const
|
||||
{
|
||||
AABB_t box = inBox;
|
||||
box.m_vMinBounds -= vOriginShift;
|
||||
box.m_vMaxBounds -= vOriginShift;
|
||||
|
||||
Vector vCorners[8];
|
||||
vCorners[0] = box.m_vMinBounds;
|
||||
vCorners[1] = Vector( box.m_vMinBounds.x, box.m_vMinBounds.y, box.m_vMaxBounds.z );
|
||||
vCorners[2] = Vector( box.m_vMinBounds.x, box.m_vMaxBounds.y, box.m_vMinBounds.z );
|
||||
vCorners[3] = Vector( box.m_vMinBounds.x, box.m_vMaxBounds.y, box.m_vMaxBounds.z );
|
||||
|
||||
vCorners[4] = Vector( box.m_vMaxBounds.x, box.m_vMinBounds.y, box.m_vMinBounds.z );
|
||||
vCorners[5] = Vector( box.m_vMaxBounds.x, box.m_vMinBounds.y, box.m_vMaxBounds.z );
|
||||
vCorners[6] = Vector( box.m_vMaxBounds.x, box.m_vMaxBounds.y, box.m_vMinBounds.z );
|
||||
vCorners[7] = box.m_vMaxBounds;
|
||||
|
||||
float flNear = FLT_MAX;//m_camera.m_flZNear;
|
||||
float flFar = -FLT_MAX;//m_camera.m_flZFar;
|
||||
for ( int i=0; i<8; ++i )
|
||||
{
|
||||
Vector vDelta = vCorners[i] - m_camera.m_origin;
|
||||
float flDist = DotProduct( m_forward, vDelta );
|
||||
flNear = MIN( flNear, flDist );
|
||||
flFar = MAX( flFar, flDist );
|
||||
}
|
||||
|
||||
*pNear = flNear;
|
||||
*pFar = flFar;
|
||||
}
|
||||
|
||||
void UpdateFrustumFromCamera()
|
||||
{
|
||||
ComputeViewMatrix( &m_worldToView, &m_cameraToWorld, m_camera );
|
||||
ComputeProjectionMatrix( &m_projection, m_camera.m_flZNear, m_camera.m_flZFar, m_camera.m_flFOVX, m_flAspect );
|
||||
|
||||
m_viewProj = (m_projection * VMatrix(m_worldToView)).Transpose();
|
||||
MatrixGetColumn( m_cameraToWorld, 0, m_forward );
|
||||
MatrixGetColumn( m_cameraToWorld, 1, m_left );
|
||||
MatrixGetColumn( m_cameraToWorld, 2, m_up );
|
||||
|
||||
// NOTE: Don't pass camera origin here. Compute it locally so that voxels can be translated here
|
||||
// and the plane constants retain precision over large world coordinate spaces
|
||||
// Also the voxel renderer needs the camera information anyway to compute LOD so this is
|
||||
// convenient
|
||||
GeneratePerspectiveFrustum( vec3_origin, m_camera.m_angles, m_camera.m_flZNear, m_camera.m_flZFar, m_camera.m_flFOVX, m_flAspect, m_frustum );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Just cram this here since until I figure out how to convert from direction to angles
|
||||
static VMatrix ViewMatrixRH( Vector &vEye, Vector &vAt, Vector &vUp )
|
||||
{
|
||||
Vector xAxis, yAxis;
|
||||
Vector zAxis = vEye - vAt;
|
||||
xAxis = CrossProduct( vUp, zAxis );
|
||||
yAxis = CrossProduct( zAxis, xAxis );
|
||||
xAxis.NormalizeInPlace();
|
||||
yAxis.NormalizeInPlace();
|
||||
zAxis.NormalizeInPlace();
|
||||
float flDotX = -DotProduct( xAxis, vEye );
|
||||
float flDotY = -DotProduct( yAxis, vEye );
|
||||
float flDotZ = -DotProduct( zAxis, vEye );
|
||||
VMatrix mRet(
|
||||
xAxis.x, yAxis.x, zAxis.x, 0,
|
||||
xAxis.y, yAxis.y, zAxis.y, 0,
|
||||
xAxis.z, yAxis.z, zAxis.z, 0,
|
||||
flDotX, flDotY, flDotZ, 1 );
|
||||
return mRet.Transpose();
|
||||
}
|
||||
|
||||
VMatrix OrthoMatrixRH( float flWidth, float flHeight, float flNear, float flFar )
|
||||
{
|
||||
float flDelta = flNear - flFar;
|
||||
|
||||
VMatrix mRet(
|
||||
2.0f / flWidth, 0, 0, 0,
|
||||
0, 2.0f / flHeight, 0, 0,
|
||||
0, 0, 1.0f / flDelta, 0,
|
||||
0, 0, flNear / flDelta, 1 );
|
||||
return mRet.Transpose();
|
||||
}
|
||||
|
||||
|
||||
const Vector &Forward() const { return m_forward; }
|
||||
const Vector &Left() const { return m_left; }
|
||||
const Vector &Up() const { return m_up; }
|
||||
|
||||
void SetView( VMatrix &mView ) { m_worldToView = mView.As3x4(); }
|
||||
void SetProj( VMatrix &mProj ) { m_projection = mProj; }
|
||||
void CalcViewProj( ) { m_viewProj = (m_projection * VMatrix(m_worldToView)).Transpose(); }
|
||||
void SetFrustum( const Frustum_t &frustum ) { m_frustum = frustum; }
|
||||
void SetForward( Vector &forward ) { m_forward = forward; }
|
||||
void SetNearFarPlanes( float flNear, float flFar ) { m_camera.m_flZNear = flNear; m_camera.m_flZFar = flFar; }
|
||||
void SetCameraPosition( const Vector &origin ) { m_camera.m_origin = origin; }
|
||||
void SetCameraAngles( const QAngle &angles ) { m_camera.m_angles = angles; }
|
||||
void SetAspect( float flAspect ) { m_flAspect = flAspect; }
|
||||
void SetFOV( float flFOV ) { m_camera.m_flFOVX = flFOV; }
|
||||
|
||||
const Vector &GetCameraPosition() const { return m_camera.m_origin; }
|
||||
const QAngle &GetCameraAngles() const { return m_camera.m_angles; }
|
||||
const matrix3x4_t &GetView() const { return m_worldToView; }
|
||||
const VMatrix &GetProj() const { return m_projection; }
|
||||
const VMatrix &GetViewProj() const { return m_viewProj; }
|
||||
float GetAspect() const { return m_flAspect; }
|
||||
float GetNearPlane() const { return m_camera.m_flZNear; }
|
||||
float GetFarPlane() const { return m_camera.m_flZFar; }
|
||||
float GetFOV() const { return m_camera.m_flFOVX; }
|
||||
|
||||
void InitCamera( const Vector &origin, const QAngle &angles, float flNear, float flFar, float flFOV, float flAspect )
|
||||
{
|
||||
m_camera.m_origin = origin;
|
||||
m_camera.m_angles = angles;
|
||||
m_camera.m_flZNear = flNear;
|
||||
m_camera.m_flZFar = flFar;
|
||||
m_camera.m_flFOVX = flFOV;
|
||||
m_flAspect = flAspect;
|
||||
}
|
||||
|
||||
protected:
|
||||
ALIGN16 Frustum_t m_frustum;
|
||||
ALIGN16 Camera_t m_camera;
|
||||
float m_flAspect;
|
||||
Vector m_forward;
|
||||
Vector m_left;
|
||||
Vector m_up;
|
||||
|
||||
matrix3x4_t m_cameraToWorld;
|
||||
matrix3x4_t m_worldToView;
|
||||
VMatrix m_viewToWorld;
|
||||
VMatrix m_projection;
|
||||
VMatrix m_viewProj;
|
||||
};
|
||||
|
||||
#endif // CAMERA_H
|
||||
|
Reference in New Issue
Block a user