mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-02 17:02:17 +00:00
560 lines
20 KiB
C++
560 lines
20 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition Source Code 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.
|
|
|
|
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
#ifndef __RENDERMATRIX_H__
|
|
#define __RENDERMATRIX_H__
|
|
|
|
static const int NUM_FRUSTUM_CORNERS = 8;
|
|
|
|
struct frustumCorners_t
|
|
{
|
|
float x[NUM_FRUSTUM_CORNERS];
|
|
float y[NUM_FRUSTUM_CORNERS];
|
|
float z[NUM_FRUSTUM_CORNERS];
|
|
};
|
|
|
|
enum frustumCull_t
|
|
{
|
|
FRUSTUM_CULL_FRONT = 1,
|
|
FRUSTUM_CULL_BACK = 2,
|
|
FRUSTUM_CULL_CROSS = 3
|
|
};
|
|
|
|
/*
|
|
================================================================================================
|
|
|
|
idRenderMatrix
|
|
|
|
This is a row-major matrix and transforms are applied with left-multiplication.
|
|
|
|
================================================================================================
|
|
*/
|
|
class idRenderMatrix
|
|
{
|
|
public:
|
|
idRenderMatrix() {}
|
|
ID_INLINE idRenderMatrix( float a0, float a1, float a2, float a3,
|
|
float b0, float b1, float b2, float b3,
|
|
float c0, float c1, float c2, float c3,
|
|
float d0, float d1, float d2, float d3 );
|
|
|
|
const float* operator[]( int index ) const
|
|
{
|
|
assert( index >= 0 && index < 4 );
|
|
return &m[index * 4];
|
|
}
|
|
float* operator[]( int index )
|
|
{
|
|
assert( index >= 0 && index < 4 );
|
|
return &m[index * 4];
|
|
}
|
|
|
|
void Zero()
|
|
{
|
|
memset( m, 0, sizeof( m ) );
|
|
}
|
|
ID_INLINE void Identity();
|
|
|
|
// Matrix classification (only meant to be used for asserts).
|
|
ID_INLINE bool IsZero( float epsilon ) const;
|
|
ID_INLINE bool IsIdentity( float epsilon ) const;
|
|
ID_INLINE bool IsAffineTransform( float epsilon ) const;
|
|
ID_INLINE bool IsUniformScale( float epsilon ) const;
|
|
|
|
// Transform a point.
|
|
// NOTE: the idVec3 out variant does not divide by W.
|
|
ID_INLINE void TransformPoint( const idVec3& in, idVec3& out ) const;
|
|
ID_INLINE void TransformPoint( const idVec3& in, idVec4& out ) const;
|
|
ID_INLINE void TransformPoint( const idVec4& in, idVec4& out ) const;
|
|
|
|
// These assume the matrix has no non-uniform scaling or shearing.
|
|
// NOTE: a direction will only stay normalized if the matrix has no skewing or scaling.
|
|
ID_INLINE void TransformDir( const idVec3& in, idVec3& out, bool normalize ) const;
|
|
ID_INLINE void TransformPlane( const idPlane& in, idPlane& out, bool normalize ) const;
|
|
|
|
// These transforms work with non-uniform scaling and shearing by multiplying
|
|
// with 'transpose(inverse(M))' where this matrix is assumed to be 'inverse(M)'.
|
|
ID_INLINE void InverseTransformDir( const idVec3& in, idVec3& out, bool normalize ) const;
|
|
ID_INLINE void InverseTransformPlane( const idPlane& in, idPlane& out, bool normalize ) const;
|
|
|
|
// Project a point.
|
|
static ID_INLINE void TransformModelToClip( const idVec3& src, const idRenderMatrix& modelMatrix, const idRenderMatrix& projectionMatrix, idVec4& eye, idVec4& clip );
|
|
static ID_INLINE void TransformClipToDevice( const idVec4& clip, idVec3& ndc );
|
|
|
|
// Create a matrix that goes from local space to the space defined by the 'origin' and 'axis'.
|
|
static void CreateFromOriginAxis( const idVec3& origin, const idMat3& axis, idRenderMatrix& out );
|
|
static void CreateFromOriginAxisScale( const idVec3& origin, const idMat3& axis, const idVec3& scale, idRenderMatrix& out );
|
|
|
|
// Create a matrix that goes from a global coordinate to a view coordinate (OpenGL looking down -Z) based on the given view origin/axis.
|
|
static void CreateViewMatrix( const idVec3& origin, const idMat3& axis, idRenderMatrix& out );
|
|
|
|
// Create a projection matrix.
|
|
static void CreateProjectionMatrix( float xMin, float xMax, float yMin, float yMax, float zNear, float zFar, idRenderMatrix& out );
|
|
static void CreateProjectionMatrixFov( float xFovDegrees, float yFovDegrees, float zNear, float zFar, float xOffset, float yOffset, idRenderMatrix& out );
|
|
|
|
// Apply depth hacks to a projection matrix.
|
|
static ID_INLINE void ApplyDepthHack( idRenderMatrix& src );
|
|
static ID_INLINE void ApplyModelDepthHack( idRenderMatrix& src, float value );
|
|
|
|
// Offset and scale the given matrix such that the result matrix transforms the unit-cube to exactly cover the given bounds (and the inverse).
|
|
static void OffsetScaleForBounds( const idRenderMatrix& src, const idBounds& bounds, idRenderMatrix& out );
|
|
static void InverseOffsetScaleForBounds( const idRenderMatrix& src, const idBounds& bounds, idRenderMatrix& out );
|
|
|
|
// Basic matrix operations.
|
|
static void Transpose( const idRenderMatrix& src, idRenderMatrix& out );
|
|
static void Multiply( const idRenderMatrix& a, const idRenderMatrix& b, idRenderMatrix& out );
|
|
static bool Inverse( const idRenderMatrix& src, idRenderMatrix& out );
|
|
static void InverseByTranspose( const idRenderMatrix& src, idRenderMatrix& out );
|
|
static bool InverseByDoubles( const idRenderMatrix& src, idRenderMatrix& out );
|
|
|
|
// Copy or create a matrix that is stored directly into four float4 vectors which is useful for directly setting vertex program uniforms.
|
|
static void CopyMatrix( const idRenderMatrix& matrix, idVec4& row0, idVec4& row1, idVec4& row2, idVec4& row3 );
|
|
static void SetMVP( const idRenderMatrix& mvp, idVec4& row0, idVec4& row1, idVec4& row2, idVec4& row3, bool& negativeDeterminant );
|
|
static void SetMVPForBounds( const idRenderMatrix& mvp, const idBounds& bounds, idVec4& row0, idVec4& row1, idVec4& row2, idVec4& row3, bool& negativeDeterminant );
|
|
static void SetMVPForInverseProject( const idRenderMatrix& mvp, const idRenderMatrix& inverseProject, idVec4& row0, idVec4& row1, idVec4& row2, idVec4& row3, bool& negativeDeterminant );
|
|
|
|
// Cull to a Model-View-Projection (MVP) matrix.
|
|
static bool CullPointToMVP( const idRenderMatrix& mvp, const idVec3& point, bool zeroToOne = false );
|
|
static bool CullPointToMVPbits( const idRenderMatrix& mvp, const idVec3& point, byte* outBits, bool zeroToOne = false );
|
|
static bool CullBoundsToMVP( const idRenderMatrix& mvp, const idBounds& bounds, bool zeroToOne = false );
|
|
static bool CullBoundsToMVPbits( const idRenderMatrix& mvp, const idBounds& bounds, byte* outBits, bool zeroToOne = false );
|
|
static bool CullExtrudedBoundsToMVP( const idRenderMatrix& mvp, const idBounds& bounds, const idVec3& extrudeDirection, const idPlane& clipPlane, bool zeroToOne = false );
|
|
static bool CullExtrudedBoundsToMVPbits( const idRenderMatrix& mvp, const idBounds& bounds, const idVec3& extrudeDirection, const idPlane& clipPlane, byte* outBits, bool zeroToOne = false );
|
|
|
|
// Calculate the projected bounds.
|
|
static void ProjectedBounds( idBounds& projected, const idRenderMatrix& mvp, const idBounds& bounds, bool windowSpace = true );
|
|
static void ProjectedNearClippedBounds( idBounds& projected, const idRenderMatrix& mvp, const idBounds& bounds, bool windowSpace = true );
|
|
static void ProjectedFullyClippedBounds( idBounds& projected, const idRenderMatrix& mvp, const idBounds& bounds, bool windowSpace = true );
|
|
|
|
// Calculate the projected depth bounds.
|
|
static void DepthBoundsForBounds( float& min, float& max, const idRenderMatrix& mvp, const idBounds& bounds, bool windowSpace = true );
|
|
static void DepthBoundsForExtrudedBounds( float& min, float& max, const idRenderMatrix& mvp, const idBounds& bounds, const idVec3& extrudeDirection, const idPlane& clipPlane, bool windowSpace = true );
|
|
static void DepthBoundsForShadowBounds( float& min, float& max, const idRenderMatrix& mvp, const idBounds& bounds, const idVec3& localLightOrigin, bool windowSpace = true );
|
|
|
|
// Create frustum planes and corners from a matrix.
|
|
static void GetFrustumPlanes( idPlane planes[6], const idRenderMatrix& frustum, bool zeroToOne, bool normalize );
|
|
static void GetFrustumCorners( frustumCorners_t& corners, const idRenderMatrix& frustumTransform, const idBounds& frustumBounds );
|
|
static frustumCull_t CullFrustumCornersToPlane( const frustumCorners_t& corners, const idPlane& plane );
|
|
|
|
private:
|
|
float m[16];
|
|
};
|
|
|
|
extern const idRenderMatrix renderMatrix_identity;
|
|
extern const idRenderMatrix renderMatrix_flipToOpenGL;
|
|
extern const idRenderMatrix renderMatrix_windowSpaceToClipSpace;
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::idRenderMatrix
|
|
========================
|
|
*/
|
|
ID_INLINE idRenderMatrix::idRenderMatrix( float a0, float a1, float a2, float a3,
|
|
float b0, float b1, float b2, float b3,
|
|
float c0, float c1, float c2, float c3,
|
|
float d0, float d1, float d2, float d3 )
|
|
{
|
|
m[0 * 4 + 0] = a0;
|
|
m[0 * 4 + 1] = a1;
|
|
m[0 * 4 + 2] = a2;
|
|
m[0 * 4 + 3] = a3;
|
|
m[1 * 4 + 0] = b0;
|
|
m[1 * 4 + 1] = b1;
|
|
m[1 * 4 + 2] = b2;
|
|
m[1 * 4 + 3] = b3;
|
|
m[2 * 4 + 0] = c0;
|
|
m[2 * 4 + 1] = c1;
|
|
m[2 * 4 + 2] = c2;
|
|
m[2 * 4 + 3] = c3;
|
|
m[3 * 4 + 0] = d0;
|
|
m[3 * 4 + 1] = d1;
|
|
m[3 * 4 + 2] = d2;
|
|
m[3 * 4 + 3] = d3;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::Identity
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::Identity()
|
|
{
|
|
m[0 * 4 + 0] = 1.0f;
|
|
m[0 * 4 + 1] = 0.0f;
|
|
m[0 * 4 + 2] = 0.0f;
|
|
m[0 * 4 + 3] = 0.0f;
|
|
|
|
m[1 * 4 + 0] = 0.0f;
|
|
m[1 * 4 + 1] = 1.0f;
|
|
m[1 * 4 + 2] = 0.0f;
|
|
m[1 * 4 + 3] = 0.0f;
|
|
|
|
m[2 * 4 + 0] = 0.0f;
|
|
m[2 * 4 + 1] = 0.0f;
|
|
m[2 * 4 + 2] = 1.0f;
|
|
m[2 * 4 + 3] = 0.0f;
|
|
|
|
m[3 * 4 + 0] = 0.0f;
|
|
m[3 * 4 + 1] = 0.0f;
|
|
m[3 * 4 + 2] = 0.0f;
|
|
m[3 * 4 + 3] = 1.0f;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::IsZero
|
|
========================
|
|
*/
|
|
ID_INLINE bool idRenderMatrix::IsZero( float epsilon ) const
|
|
{
|
|
for( int i = 0; i < 16; i++ )
|
|
{
|
|
if( idMath::Fabs( m[i] ) > epsilon )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::IsIdentity
|
|
========================
|
|
*/
|
|
ID_INLINE bool idRenderMatrix::IsIdentity( float epsilon ) const
|
|
{
|
|
for( int i = 0; i < 4; i++ )
|
|
{
|
|
for( int j = 0; j < 4; j++ )
|
|
{
|
|
if( i == j )
|
|
{
|
|
if( idMath::Fabs( m[i * 4 + j] - 1.0f ) > epsilon )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( idMath::Fabs( m[i * 4 + j] ) > epsilon )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::IsAffineTransform
|
|
========================
|
|
*/
|
|
ID_INLINE bool idRenderMatrix::IsAffineTransform( float epsilon ) const
|
|
{
|
|
if( idMath::Fabs( m[3 * 4 + 0] ) > epsilon ||
|
|
idMath::Fabs( m[3 * 4 + 1] ) > epsilon ||
|
|
idMath::Fabs( m[3 * 4 + 2] ) > epsilon ||
|
|
idMath::Fabs( m[3 * 4 + 3] - 1.0f ) > epsilon )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::IsUniformScale
|
|
========================
|
|
*/
|
|
ID_INLINE bool idRenderMatrix::IsUniformScale( float epsilon ) const
|
|
{
|
|
float d0 = idMath::InvSqrt( m[0 * 4 + 0] * m[0 * 4 + 0] + m[1 * 4 + 0] * m[1 * 4 + 0] + m[2 * 4 + 0] * m[2 * 4 + 0] );
|
|
float d1 = idMath::InvSqrt( m[0 * 4 + 1] * m[0 * 4 + 1] + m[1 * 4 + 1] * m[1 * 4 + 1] + m[2 * 4 + 1] * m[2 * 4 + 1] );
|
|
float d2 = idMath::InvSqrt( m[0 * 4 + 2] * m[0 * 4 + 2] + m[1 * 4 + 2] * m[1 * 4 + 2] + m[2 * 4 + 2] * m[2 * 4 + 2] );
|
|
if( idMath::Fabs( d0 - d1 ) > epsilon )
|
|
{
|
|
return false;
|
|
}
|
|
if( idMath::Fabs( d1 - d2 ) > epsilon )
|
|
{
|
|
return false;
|
|
}
|
|
if( idMath::Fabs( d0 - d2 ) > epsilon )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::TransformPoint
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::TransformPoint( const idVec3& in, idVec3& out ) const
|
|
{
|
|
assert( in.ToFloatPtr() != out.ToFloatPtr() );
|
|
const idRenderMatrix& matrix = *this;
|
|
out[0] = in[0] * matrix[0][0] + in[1] * matrix[0][1] + in[2] * matrix[0][2] + matrix[0][3];
|
|
out[1] = in[0] * matrix[1][0] + in[1] * matrix[1][1] + in[2] * matrix[1][2] + matrix[1][3];
|
|
out[2] = in[0] * matrix[2][0] + in[1] * matrix[2][1] + in[2] * matrix[2][2] + matrix[2][3];
|
|
assert( idMath::Fabs( in[0] * matrix[3][0] + in[1] * matrix[3][1] + in[2] * matrix[3][2] + matrix[3][3] - 1.0f ) < 0.01f );
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::TransformPoint
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::TransformPoint( const idVec3& in, idVec4& out ) const
|
|
{
|
|
assert( in.ToFloatPtr() != out.ToFloatPtr() );
|
|
const idRenderMatrix& matrix = *this;
|
|
out[0] = in[0] * matrix[0][0] + in[1] * matrix[0][1] + in[2] * matrix[0][2] + matrix[0][3];
|
|
out[1] = in[0] * matrix[1][0] + in[1] * matrix[1][1] + in[2] * matrix[1][2] + matrix[1][3];
|
|
out[2] = in[0] * matrix[2][0] + in[1] * matrix[2][1] + in[2] * matrix[2][2] + matrix[2][3];
|
|
out[3] = in[0] * matrix[3][0] + in[1] * matrix[3][1] + in[2] * matrix[3][2] + matrix[3][3];
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::TransformPoint
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::TransformPoint( const idVec4& in, idVec4& out ) const
|
|
{
|
|
assert( in.ToFloatPtr() != out.ToFloatPtr() );
|
|
const idRenderMatrix& matrix = *this;
|
|
out[0] = in[0] * matrix[0][0] + in[1] * matrix[0][1] + in[2] * matrix[0][2] + in[3] * matrix[0][3];
|
|
out[1] = in[0] * matrix[1][0] + in[1] * matrix[1][1] + in[2] * matrix[1][2] + in[3] * matrix[1][3];
|
|
out[2] = in[0] * matrix[2][0] + in[1] * matrix[2][1] + in[2] * matrix[2][2] + in[3] * matrix[2][3];
|
|
out[3] = in[0] * matrix[3][0] + in[1] * matrix[3][1] + in[2] * matrix[3][2] + in[3] * matrix[3][3];
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::TransformDir
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::TransformDir( const idVec3& in, idVec3& out, bool normalize ) const
|
|
{
|
|
const idRenderMatrix& matrix = *this;
|
|
float p0 = in[0] * matrix[0][0] + in[1] * matrix[0][1] + in[2] * matrix[0][2];
|
|
float p1 = in[0] * matrix[1][0] + in[1] * matrix[1][1] + in[2] * matrix[1][2];
|
|
float p2 = in[0] * matrix[2][0] + in[1] * matrix[2][1] + in[2] * matrix[2][2];
|
|
if( normalize )
|
|
{
|
|
float r = idMath::InvSqrt( p0 * p0 + p1 * p1 + p2 * p2 );
|
|
p0 *= r;
|
|
p1 *= r;
|
|
p2 *= r;
|
|
}
|
|
out[0] = p0;
|
|
out[1] = p1;
|
|
out[2] = p2;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::TransformPlane
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::TransformPlane( const idPlane& in, idPlane& out, bool normalize ) const
|
|
{
|
|
assert( IsUniformScale( 0.01f ) );
|
|
const idRenderMatrix& matrix = *this;
|
|
float p0 = in[0] * matrix[0][0] + in[1] * matrix[0][1] + in[2] * matrix[0][2];
|
|
float p1 = in[0] * matrix[1][0] + in[1] * matrix[1][1] + in[2] * matrix[1][2];
|
|
float p2 = in[0] * matrix[2][0] + in[1] * matrix[2][1] + in[2] * matrix[2][2];
|
|
float d0 = matrix[0][3] - p0 * in[3];
|
|
float d1 = matrix[1][3] - p1 * in[3];
|
|
float d2 = matrix[2][3] - p2 * in[3];
|
|
if( normalize )
|
|
{
|
|
float r = idMath::InvSqrt( p0 * p0 + p1 * p1 + p2 * p2 );
|
|
p0 *= r;
|
|
p1 *= r;
|
|
p2 *= r;
|
|
}
|
|
out[0] = p0;
|
|
out[1] = p1;
|
|
out[2] = p2;
|
|
out[3] = - p0 * d0 - p1 * d1 - p2 * d2;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::InverseTransformDir
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::InverseTransformDir( const idVec3& in, idVec3& out, bool normalize ) const
|
|
{
|
|
assert( in.ToFloatPtr() != out.ToFloatPtr() );
|
|
const idRenderMatrix& matrix = *this;
|
|
float p0 = in[0] * matrix[0][0] + in[1] * matrix[1][0] + in[2] * matrix[2][0];
|
|
float p1 = in[0] * matrix[0][1] + in[1] * matrix[1][1] + in[2] * matrix[2][1];
|
|
float p2 = in[0] * matrix[0][2] + in[1] * matrix[1][2] + in[2] * matrix[2][2];
|
|
if( normalize )
|
|
{
|
|
float r = idMath::InvSqrt( p0 * p0 + p1 * p1 + p2 * p2 );
|
|
p0 *= r;
|
|
p1 *= r;
|
|
p2 *= r;
|
|
}
|
|
out[0] = p0;
|
|
out[1] = p1;
|
|
out[2] = p2;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::InverseTransformPlane
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::InverseTransformPlane( const idPlane& in, idPlane& out, bool normalize ) const
|
|
{
|
|
assert( in.ToFloatPtr() != out.ToFloatPtr() );
|
|
const idRenderMatrix& matrix = *this;
|
|
float p0 = in[0] * matrix[0][0] + in[1] * matrix[1][0] + in[2] * matrix[2][0] + in[3] * matrix[3][0];
|
|
float p1 = in[0] * matrix[0][1] + in[1] * matrix[1][1] + in[2] * matrix[2][1] + in[3] * matrix[3][1];
|
|
float p2 = in[0] * matrix[0][2] + in[1] * matrix[1][2] + in[2] * matrix[2][2] + in[3] * matrix[3][2];
|
|
float p3 = in[0] * matrix[0][3] + in[1] * matrix[1][3] + in[2] * matrix[2][3] + in[3] * matrix[3][3];
|
|
if( normalize )
|
|
{
|
|
float r = idMath::InvSqrt( p0 * p0 + p1 * p1 + p2 * p2 );
|
|
p0 *= r;
|
|
p1 *= r;
|
|
p2 *= r;
|
|
p3 *= r;
|
|
}
|
|
out[0] = p0;
|
|
out[1] = p1;
|
|
out[2] = p2;
|
|
out[3] = p3;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::TransformModelToClip
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::TransformModelToClip( const idVec3& src, const idRenderMatrix& modelMatrix, const idRenderMatrix& projectionMatrix, idVec4& eye, idVec4& clip )
|
|
{
|
|
for( int i = 0; i < 4; i++ )
|
|
{
|
|
eye[i] = modelMatrix[i][0] * src[0] +
|
|
modelMatrix[i][1] * src[1] +
|
|
modelMatrix[i][2] * src[2] +
|
|
modelMatrix[i][3];
|
|
}
|
|
for( int i = 0; i < 4; i++ )
|
|
{
|
|
clip[i] = projectionMatrix[i][0] * eye[0] +
|
|
projectionMatrix[i][1] * eye[1] +
|
|
projectionMatrix[i][2] * eye[2] +
|
|
projectionMatrix[i][3] * eye[3];
|
|
}
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::TransformClipToDevice
|
|
|
|
Clip to normalized device coordinates.
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::TransformClipToDevice( const idVec4& clip, idVec3& ndc )
|
|
{
|
|
assert( idMath::Fabs( clip[3] ) > idMath::FLT_SMALLEST_NON_DENORMAL );
|
|
float r = 1.0f / clip[3];
|
|
ndc[0] = clip[0] * r;
|
|
ndc[1] = clip[1] * r;
|
|
ndc[2] = clip[2] * r;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::ApplyDepthHack
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::ApplyDepthHack( idRenderMatrix& src )
|
|
{
|
|
// scale projected z by 25%
|
|
src.m[2 * 4 + 0] *= 0.25f;
|
|
src.m[2 * 4 + 1] *= 0.25f;
|
|
src.m[2 * 4 + 2] *= 0.25f;
|
|
src.m[2 * 4 + 3] *= 0.25f;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::ApplyModelDepthHack
|
|
========================
|
|
*/
|
|
ID_INLINE void idRenderMatrix::ApplyModelDepthHack( idRenderMatrix& src, float value )
|
|
{
|
|
// offset projected z
|
|
src.m[2 * 4 + 3] -= value;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::CullPointToMVP
|
|
========================
|
|
*/
|
|
ID_INLINE bool idRenderMatrix::CullPointToMVP( const idRenderMatrix& mvp, const idVec3& point, bool zeroToOne )
|
|
{
|
|
byte bits;
|
|
return CullPointToMVPbits( mvp, point, &bits, zeroToOne );
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::CullBoundsToMVP
|
|
========================
|
|
*/
|
|
ID_INLINE bool idRenderMatrix::CullBoundsToMVP( const idRenderMatrix& mvp, const idBounds& bounds, bool zeroToOne )
|
|
{
|
|
byte bits;
|
|
return CullBoundsToMVPbits( mvp, bounds, &bits, zeroToOne );
|
|
}
|
|
|
|
/*
|
|
========================
|
|
idRenderMatrix::CullExtrudedBoundsToMVP
|
|
========================
|
|
*/
|
|
ID_INLINE bool idRenderMatrix::CullExtrudedBoundsToMVP( const idRenderMatrix& mvp, const idBounds& bounds, const idVec3& extrudeDirection, const idPlane& clipPlane, bool zeroToOne )
|
|
{
|
|
byte bits;
|
|
return CullExtrudedBoundsToMVPbits( mvp, bounds, extrudeDirection, clipPlane, &bits, zeroToOne );
|
|
}
|
|
|
|
#endif // !__RENDERMATRIX_H__
|