500 lines
16 KiB
C++
500 lines
16 KiB
C++
//======= Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ======
|
|
//
|
|
// A class representing a camera
|
|
//
|
|
//===============================================================================
|
|
|
|
#include "movieobjects/dmecamera.h"
|
|
#include "tier0/dbg.h"
|
|
#include "datamodel/dmelementfactoryhelper.h"
|
|
#include "mathlib/vector.h"
|
|
#include "movieobjects/dmetransform.h"
|
|
#include "materialsystem/imaterialsystem.h"
|
|
#include "movieobjects_interfaces.h"
|
|
#include "tier2/tier2.h"
|
|
|
|
// FIXME: REMOVE
|
|
#include "istudiorender.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Expose this class to the scene database
|
|
//-----------------------------------------------------------------------------
|
|
IMPLEMENT_ELEMENT_FACTORY( DmeCamera, CDmeCamera );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::OnConstruction()
|
|
{
|
|
m_flFieldOfView.InitAndSet( this, "fieldOfView", 30.0f );
|
|
|
|
// FIXME: This currently matches the client DLL for HL2
|
|
// but we probably need a way of getting this state from the client DLL
|
|
m_zNear.InitAndSet( this, "znear", 3.0f );
|
|
m_zFar.InitAndSet( this, "zfar", 16384.0f * 1.73205080757f );
|
|
|
|
m_flFocalDistance.InitAndSet( this, "focalDistance", 72.0f);
|
|
m_flZeroParallaxDistance.InitAndSet( this, "zeroParallaxDistance", 75.0f );
|
|
m_flEyeSeparation.InitAndSet( this, "eyeSeparation", 0.75f );
|
|
m_flAperture.InitAndSet( this, "aperture", 0.2f);
|
|
m_shutterSpeed.InitAndSet( this, "shutterSpeed", DmeTime_t( 0.5f / 24.0f ) );
|
|
m_flToneMapScale.InitAndSet( this, "toneMapScale", 1.0f );
|
|
m_flAOBias.InitAndSet( this, "SSAOBias", 0.0005f );
|
|
m_flAOStrength.InitAndSet( this, "SSAOStrength", 1.0f );
|
|
m_flAORadius.InitAndSet( this, "SSAORadius", 15.0f );
|
|
m_flBloomScale.InitAndSet( this, "bloomScale", 0.28f );
|
|
m_nDoFQuality.InitAndSet( this, "depthOfFieldQuality", 0 );
|
|
m_nMotionBlurQuality.InitAndSet( this, "motionBlurQuality", 0 );
|
|
m_flBloomWidth.InitAndSet( this, "bloomWidth", 9.0f );
|
|
m_bOrtho.InitAndSet( this, "ortho", false );
|
|
|
|
// Ortho
|
|
m_nAxis.InitAndSet( this, "axis", 0 );
|
|
m_bWasBehindFrustum.InitAndSet( this, "behindfrustum", false );
|
|
m_flDistance.InitAndSet( this, "distance", 32.0f );
|
|
for ( int i = 0; i < AXIS_COUNT; ++i )
|
|
{
|
|
char sz[ 32 ];
|
|
Q_snprintf( sz, sizeof( sz ), "scale%d", i );
|
|
m_flScale[ i ].InitAndSet( this, sz, 1.0f );
|
|
Q_snprintf( sz, sizeof( sz ), "lookat%d", i );
|
|
m_vecLookAt[ i ].Init( this, sz );
|
|
}
|
|
|
|
m_vecAxis.Init();
|
|
m_vecOrigin.Init();
|
|
m_angRotation.Init();
|
|
SetIdentityMatrix( m_Transform );
|
|
}
|
|
|
|
void CDmeCamera::OnDestruction()
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Loads the material system view matrix based on the transform
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::LoadViewMatrix( bool bUseEngineCoordinateSystem )
|
|
{
|
|
if ( !g_pMaterialSystem )
|
|
return;
|
|
|
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
|
VMatrix view;
|
|
GetViewMatrix( view, bUseEngineCoordinateSystem );
|
|
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
|
pRenderContext->LoadMatrix( view );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Loads the material system projection matrix based on the fov, etc.
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::LoadProjectionMatrix( int nDisplayWidth, int nDisplayHeight )
|
|
{
|
|
if ( !g_pMaterialSystem )
|
|
return;
|
|
|
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
|
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
|
|
|
VMatrix proj;
|
|
GetProjectionMatrix( proj, nDisplayWidth, nDisplayHeight );
|
|
pRenderContext->LoadMatrix( proj );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets up studiorender camera state
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::LoadStudioRenderCameraState()
|
|
{
|
|
// FIXME: Remove this! This should automatically happen in DrawModel
|
|
// in studiorender.
|
|
if ( !g_pStudioRender )
|
|
return;
|
|
|
|
matrix3x4_t transform;
|
|
GetTransform()->GetTransform( transform );
|
|
|
|
Vector vecOrigin, vecRight, vecUp, vecForward;
|
|
MatrixGetColumn( transform, 0, vecRight );
|
|
MatrixGetColumn( transform, 1, vecUp );
|
|
MatrixGetColumn( transform, 2, vecForward );
|
|
MatrixGetColumn( transform, 3, vecOrigin );
|
|
g_pStudioRender->SetViewState( vecOrigin, vecRight, vecUp, vecForward );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the x FOV (the full angle)
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetFOVx() const
|
|
{
|
|
return m_flFieldOfView;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the near Z in inches
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetNearZ() const
|
|
{
|
|
return m_zNear;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets the near Z in inches
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::SetNearZ( float zNear )
|
|
{
|
|
m_zNear = zNear;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the far Z in inches
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetFarZ() const
|
|
{
|
|
return m_zFar;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets the far Z in inches
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::SetFarZ( float zFar )
|
|
{
|
|
m_zFar = zFar;
|
|
}
|
|
|
|
void CDmeCamera::SetFOVx( float fov )
|
|
{
|
|
m_flFieldOfView = fov;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the focal distance in inches
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetFocalDistance() const
|
|
{
|
|
return m_flFocalDistance;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets the focal distance in inches
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::SetFocalDistance( const float &flFocalDistance )
|
|
{
|
|
m_flFocalDistance = flFocalDistance;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the zero-parallax distance in inches
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetZeroParallaxDistance() const
|
|
{
|
|
return m_flZeroParallaxDistance;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets the zero-parallax distance in inches
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::SetZeroParallaxDistance( const float &flZeroParallaxDistance )
|
|
{
|
|
m_flZeroParallaxDistance = flZeroParallaxDistance;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the eye separation distance in inches
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetEyeSeparation() const
|
|
{
|
|
return m_flEyeSeparation;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets the eye separation distance in inches
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::SetEyeSeparation( const float &flEyeSeparation )
|
|
{
|
|
m_flEyeSeparation = flEyeSeparation;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the camera aperture in inches
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetAperture() const
|
|
{
|
|
return m_flAperture;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the camera aperture in inches
|
|
//-----------------------------------------------------------------------------
|
|
DmeTime_t CDmeCamera::GetShutterSpeed() const
|
|
{
|
|
return m_shutterSpeed;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the tone map scale
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetToneMapScale() const
|
|
{
|
|
return m_flToneMapScale;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the camera's Ambient occlusion bias
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetAOBias() const
|
|
{
|
|
return m_flAOBias;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the camera's Ambient occlusion strength
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetAOStrength() const
|
|
{
|
|
return m_flAOStrength;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the camera's Ambient occlusion radius
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetAORadius() const
|
|
{
|
|
return m_flAORadius;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the bloom scale
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetBloomScale() const
|
|
{
|
|
return m_flBloomScale;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the bloom width
|
|
//-----------------------------------------------------------------------------
|
|
float CDmeCamera::GetBloomWidth() const
|
|
{
|
|
return m_flBloomWidth;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the number of Depth of Field samples
|
|
//-----------------------------------------------------------------------------
|
|
int CDmeCamera::GetDepthOfFieldQuality() const
|
|
{
|
|
return m_nDoFQuality;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the number of Motion Blur samples
|
|
//-----------------------------------------------------------------------------
|
|
int CDmeCamera::GetMotionBlurQuality() const
|
|
{
|
|
return m_nMotionBlurQuality;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the view direction
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::GetViewDirection( Vector *pDirection )
|
|
{
|
|
matrix3x4_t transform;
|
|
GetTransform()->GetTransform( transform );
|
|
MatrixGetColumn( transform, 2, *pDirection );
|
|
|
|
// We look down the -z axis
|
|
*pDirection *= -1.0f;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets up render state in the material system for rendering
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::SetupRenderState( int nDisplayWidth, int nDisplayHeight, bool bUseEngineCoordinateSystem /* = false */ )
|
|
{
|
|
LoadViewMatrix( bUseEngineCoordinateSystem );
|
|
LoadProjectionMatrix( nDisplayWidth, nDisplayHeight );
|
|
LoadStudioRenderCameraState( );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// accessors for generated matrices
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::GetViewMatrix( VMatrix &view, bool bUseEngineCoordinateSystem /* = false */ )
|
|
{
|
|
matrix3x4_t transform, invTransform;
|
|
CDmeTransform *pTransform = GetTransform();
|
|
pTransform->GetTransform( transform );
|
|
|
|
if ( bUseEngineCoordinateSystem )
|
|
{
|
|
VMatrix matRotate( transform );
|
|
VMatrix matRotateZ;
|
|
MatrixBuildRotationAboutAxis( matRotateZ, Vector(0,0,1), -90 );
|
|
MatrixMultiply( matRotate, matRotateZ, matRotate );
|
|
|
|
VMatrix matRotateX;
|
|
MatrixBuildRotationAboutAxis( matRotateX, Vector(1,0,0), 90 );
|
|
MatrixMultiply( matRotate, matRotateX, matRotate );
|
|
transform = matRotate.As3x4();
|
|
}
|
|
|
|
MatrixInvert( transform, invTransform );
|
|
view.Init( invTransform );
|
|
}
|
|
|
|
void CDmeCamera::GetProjectionMatrix( VMatrix &proj, int width, int height )
|
|
{
|
|
float flFOV = m_flFieldOfView.Get();
|
|
float flZNear = m_zNear.Get();
|
|
float flZFar = m_zFar.Get();
|
|
float flApsectRatio = (float)width / (float)height;
|
|
|
|
// MatrixBuildPerspective( proj, flFOV, flFOV * flApsectRatio, flZNear, flZFar );
|
|
|
|
#if 1
|
|
float halfWidth = tan( flFOV * M_PI / 360.0 );
|
|
float halfHeight = halfWidth / flApsectRatio;
|
|
#else
|
|
float halfHeight = tan( flFOV * M_PI / 360.0 );
|
|
float halfWidth = flApsectRatio * halfHeight;
|
|
#endif
|
|
memset( proj.Base(), 0, sizeof( proj ) );
|
|
proj[0][0] = 1.0f / halfWidth;
|
|
proj[1][1] = 1.0f / halfHeight;
|
|
proj[2][2] = flZFar / ( flZNear - flZFar );
|
|
proj[3][2] = -1.0f;
|
|
proj[2][3] = flZNear * flZFar / ( flZNear - flZFar );
|
|
}
|
|
|
|
void CDmeCamera::GetViewProjectionInverse( VMatrix &viewprojinv, int width, int height )
|
|
{
|
|
VMatrix view, proj;
|
|
GetViewMatrix( view );
|
|
GetProjectionMatrix( proj, width, height );
|
|
|
|
VMatrix viewproj;
|
|
MatrixMultiply( proj, view, viewproj );
|
|
bool success = MatrixInverseGeneral( viewproj, viewprojinv );
|
|
if ( !success )
|
|
{
|
|
Assert( 0 );
|
|
MatrixInverseTR( viewproj, viewprojinv );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Computes the screen space position given a screen size
|
|
//-----------------------------------------------------------------------------
|
|
void CDmeCamera::ComputeScreenSpacePosition( const Vector &vecWorldPosition, int width, int height, Vector2D *pScreenPosition )
|
|
{
|
|
VMatrix view, proj, viewproj;
|
|
GetViewMatrix( view );
|
|
GetProjectionMatrix( proj, width, height );
|
|
MatrixMultiply( proj, view, viewproj );
|
|
|
|
Vector vecScreenPos;
|
|
Vector3DMultiplyPositionProjective( viewproj, vecWorldPosition, vecScreenPos );
|
|
|
|
pScreenPosition->x = ( vecScreenPos.x + 1.0f ) * width / 2.0f;
|
|
pScreenPosition->y = ( -vecScreenPos.y + 1.0f ) * height / 2.0f;
|
|
}
|
|
|
|
const matrix3x4_t &CDmeCamera::GetOrthoTransform() const
|
|
{
|
|
return m_Transform;
|
|
}
|
|
|
|
const Vector &CDmeCamera::GetOrthoAbsOrigin() const
|
|
{
|
|
return m_vecOrigin;
|
|
}
|
|
|
|
const QAngle &CDmeCamera::GetOrthoAbsAngles() const
|
|
{
|
|
return m_angRotation;
|
|
}
|
|
|
|
void CDmeCamera::OrthoUpdate()
|
|
{
|
|
m_vecAxis.Init( 0, 0, 0 );
|
|
switch ( m_nAxis )
|
|
{
|
|
default:
|
|
Assert( 0 );
|
|
case AXIS_X:
|
|
m_vecAxis[ 1 ] = 1;
|
|
break;
|
|
case AXIS_Y:
|
|
m_vecAxis[ 2 ] = -1;
|
|
break;
|
|
case AXIS_Z:
|
|
m_vecAxis[ 0 ] = 1;
|
|
break;
|
|
case AXIS_X_NEG:
|
|
m_vecAxis[ 1 ] = -1;
|
|
break;
|
|
case AXIS_Y_NEG:
|
|
m_vecAxis[ 2 ] = 1;
|
|
break;
|
|
case AXIS_Z_NEG:
|
|
m_vecAxis[ 0 ] = -1;
|
|
break;
|
|
}
|
|
|
|
m_vecOrigin = m_vecLookAt[ m_nAxis ].Get() - m_flDistance * m_vecAxis;
|
|
Assert( m_vecOrigin.IsValid() );
|
|
|
|
VectorAngles( m_vecAxis,m_angRotation );
|
|
AngleMatrix( m_angRotation, m_vecOrigin, m_Transform );
|
|
}
|
|
|
|
void CDmeCamera::FromCamera( CDmeCamera *pCamera )
|
|
{
|
|
m_bOrtho = pCamera->m_bOrtho;
|
|
matrix3x4_t mat;
|
|
pCamera->GetAbsTransform( mat );
|
|
MatrixCopy( mat, m_Transform );
|
|
m_flFieldOfView = pCamera->GetFOVx();
|
|
|
|
for ( int i = 0; i < AXIS_COUNT; ++i )
|
|
{
|
|
m_vecLookAt[ i ] =pCamera->m_vecLookAt[ i ];
|
|
m_flScale[ i ] = pCamera->m_flScale[ i ];
|
|
}
|
|
m_flDistance = pCamera->m_flDistance;
|
|
m_nAxis = pCamera->m_nAxis;
|
|
m_bWasBehindFrustum = pCamera->m_bWasBehindFrustum;
|
|
|
|
if ( m_bOrtho )
|
|
{
|
|
OrthoUpdate();
|
|
}
|
|
}
|
|
|
|
void CDmeCamera::ToCamera( CDmeCamera *pCamera )
|
|
{
|
|
pCamera->m_bOrtho = m_bOrtho;
|
|
pCamera->SetFOVx( m_flFieldOfView );
|
|
pCamera->SetAbsTransform( m_Transform );
|
|
|
|
for ( int i = 0; i < AXIS_COUNT; ++i )
|
|
{
|
|
pCamera->m_vecLookAt[ i ] = m_vecLookAt[ i ];
|
|
pCamera->m_flScale[ i ] = m_flScale[ i ];
|
|
}
|
|
pCamera->m_flDistance = m_flDistance;
|
|
pCamera->m_nAxis = m_nAxis;
|
|
pCamera->m_bWasBehindFrustum = m_bWasBehindFrustum;
|
|
|
|
if ( m_bOrtho )
|
|
{
|
|
pCamera->OrthoUpdate();
|
|
}
|
|
} |