etqw-sdk/source/game/misc/WorldToScreen.h

168 lines
4.7 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#include "../../renderer/DeviceContext.h"
#ifndef __GAME_MISC_WORLDTOSCREEN_H__
#define __GAME_MISC_WORLDTOSCREEN_H__
/*
============
sdWorldToScreenConverter
============
*/
class sdWorldToScreenConverter {
public:
sdWorldToScreenConverter( const renderView_t& view );
sdWorldToScreenConverter( float* projectionMatrix, float* modelViewMatrix );
void Transform( const idVec3& src, idVec2& dst ) const;
void Transform( const idBounds& src, const idMat3& axes, const idVec3& origin, sdBounds2D& dst ) const;
void Setup( const renderView_t& view );
void Setup( float* projectionMatrix, float* modelViewMatrix );
void SetExtents( const idVec2& _extents ) { extents = _extents; }
static bool TransformClipped( const idBounds &bounds, const idMat3& axes, const idVec3& origin, sdBounds2D& dst, const idFrustum& frustum, const idVec2& extents );
protected:
float projectionMatrixArray[ 16 ];
float modelViewMatrixArray[ 16 ];
float* projectionMatrix;
float* modelViewMatrix;
idVec2 extents;
};
/*
======================
sdWorldToScreenConverter::TransformClipped
======================
*/
ID_INLINE bool sdWorldToScreenConverter::TransformClipped( const idBounds &bounds, const idMat3& axes, const idVec3& origin, sdBounds2D& dst, const idFrustum& frustum, const idVec2& extents ) {
idBounds temp;
if ( !frustum.ProjectionBounds( idBox( bounds, origin, axes ), temp ) ) {
return false;
}
dst.GetMins().x = 0.5f * ( 1.0f - temp[ 1 ].y ) * extents.x;
dst.GetMaxs().x = 0.5f * ( 1.0f - temp[ 0 ].y ) * extents.x;
dst.GetMins().y = 0.5f * ( 1.0f - temp[ 1 ].z ) * extents.y;
dst.GetMaxs().y = 0.5f * ( 1.0f - temp[ 0 ].z ) * extents.y;
return true;
}
/*
==========================
sdWorldToScreenConverter::sdWorldToScreenConverter
==========================
*/
ID_INLINE sdWorldToScreenConverter::sdWorldToScreenConverter( const renderView_t& view ) {
const float width = SCREEN_WIDTH * 1.0f / deviceContext->GetAspectRatioCorrection();
extents.Set( width, SCREEN_HEIGHT );
Setup( view );
}
/*
==========================
sdWorldToScreenConverter::sdWorldToScreenConverter
==========================
*/
ID_INLINE sdWorldToScreenConverter::sdWorldToScreenConverter( float* projectionMatrix, float* modelViewMatrix ) {
const float width = SCREEN_WIDTH * 1.0f / deviceContext->GetAspectRatioCorrection();
extents.Set( width, SCREEN_HEIGHT );
Setup( projectionMatrix, modelViewMatrix );
}
/*
==========================
sdWorldToScreenConverter::Transform
==========================
*/
ID_INLINE void sdWorldToScreenConverter::Transform( const idVec3& src, idVec2& dst ) const {
int i;
idPlane eye, clip;
for ( i = 0 ; i < 4 ; i++ ) {
eye[i] =
src[0] * modelViewMatrix[ i + 0 * 4 ] +
src[1] * modelViewMatrix[ i + 1 * 4 ] +
src[2] * modelViewMatrix[ i + 2 * 4 ] +
modelViewMatrix[ i + 3 * 4 ];
}
for ( i = 0 ; i < 4 ; i++ ) {
clip[i] =
eye[0] * projectionMatrix[ i + 0 * 4 ] +
eye[1] * projectionMatrix[ i + 1 * 4 ] +
eye[2] * projectionMatrix[ i + 2 * 4 ] +
eye[3] * projectionMatrix[ i + 3 * 4 ];
}
if( clip[ 3 ] <= 0.01f ) {
clip[ 3 ] = 0.01f;
}
dst[ 0 ] = clip[ 0 ] / clip[ 3 ];
dst[ 1 ] = clip[ 1 ] / clip[ 3 ];
dst[ 0 ] = ( 0.5f * ( 1.0f + dst[ 0 ] ) * extents[ 0 ] );
dst[ 1 ] = ( 0.5f * ( 1.0f - dst[ 1 ] ) * extents[ 1 ] );
}
/*
==========================
sdWorldToScreenConverter::Transform
==========================
*/
ID_INLINE void sdWorldToScreenConverter::Transform( const idBounds& src, const idMat3& axes, const idVec3& origin, sdBounds2D& dst ) const {
idVec3 point;
idVec2 screenPoint;
dst.Clear();
int i;
for ( i = 0; i < 8; i++ ) {
point[ 0 ] = src[ ( i & 1 ) >> 0 ][ 0 ];
point[ 1 ] = src[ ( i & 2 ) >> 1 ][ 1 ];
point[ 2 ] = src[ ( i & 4 ) >> 2 ][ 2 ];
point *= axes;
point += origin;
Transform( point, screenPoint );
dst.AddPoint( screenPoint );
}
}
/*
==========================
sdWorldToScreenConverter::Setup
==========================
*/
ID_INLINE void sdWorldToScreenConverter::Setup( const renderView_t& view ) {
projectionMatrix = projectionMatrixArray;
modelViewMatrix = modelViewMatrixArray;
gameRenderWorld->SetupMatrices( &view, projectionMatrix, modelViewMatrix, false );
}
/*
==========================
sdWorldToScreenConverter::Setup
==========================
*/
ID_INLINE void sdWorldToScreenConverter::Setup( float* projectionMatrix, float* modelViewMatrix ) {
this->projectionMatrix = projectionMatrix;
this->modelViewMatrix = modelViewMatrix;
}
#endif // __GAME_MISC_WORLDTOSCREEN_H__