etqw-sdk/source/game/guis/GuiSurfaceRenderable.cpp

424 lines
12 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
/*
================================================================================================================================
================================================================================================================================
WARNING: This is included by the radiant project as well... don't try to use any gamecode stuff in here
================================================================================================================================
================================================================================================================================
*/
#include "../precompiled.h"
#pragma hdrstop
#include "UserInterfaceManager.h"
#include "GuiSurfaceRenderable.h"
#include "../gamesys/Pvs.h"
#include "../../renderer/DeviceContext.h"
/*
===============================================================================
sdGuiSurfaceRenderable
===============================================================================
*/
/*
============
sdGuiSurfaceRenderable::sdGuiSurfaceRenderable
============
*/
sdGuiSurfaceRenderable::sdGuiSurfaceRenderable() {
}
/*
============
sdGuiSurfaceRenderable::~sdGuiSurfaceRenderable
============
*/
sdGuiSurfaceRenderable::~sdGuiSurfaceRenderable() {
Clear();
}
/*
============
sdGuiSurfaceRenderable::Clear
============
*/
void sdGuiSurfaceRenderable::Clear() {
if ( handle.IsValid() ) {
uiManager->FreeUserInterface( handle );
handle.Release();
}
}
/*
============
sdGuiSurfaceRenderable::Init
============
*/
void sdGuiSurfaceRenderable::Init( const guiSurface_t& surface, const guiHandle_t& handle, const int allowInViewID, const bool weaponDepthHack ) {
this->surface = surface;
this->handle = handle;
this->allowInViewID = allowInViewID;
this->weaponDepthHack = weaponDepthHack;
axisLenSquared[0] = surface.axis[0].LengthSqr();
axisLenSquared[1] = surface.axis[1].LengthSqr();
}
#if !defined( MONOLITHIC )
// TEMP TEMP
void R_AxisToModelMatrix( const idMat3 &axis, const idVec3 &origin, float modelMatrix[16] ) {
modelMatrix[0] = axis[0][0];
modelMatrix[4] = axis[1][0];
modelMatrix[8] = axis[2][0];
modelMatrix[12] = origin[0];
modelMatrix[1] = axis[0][1];
modelMatrix[5] = axis[1][1];
modelMatrix[9] = axis[2][1];
modelMatrix[13] = origin[1];
modelMatrix[2] = axis[0][2];
modelMatrix[6] = axis[1][2];
modelMatrix[10] = axis[2][2];
modelMatrix[14] = origin[2];
modelMatrix[3] = 0;
modelMatrix[7] = 0;
modelMatrix[11] = 0;
modelMatrix[15] = 1;
}
#else
void R_AxisToModelMatrix( const idMat3 &axis, const idVec3 &origin, float modelMatrix[16] );
#endif
void R_ModelMatrixToAxis( const float modelMatrix[16], idMat3 &axis, idVec3 &origin ) {
axis[0][0] = modelMatrix[0];
axis[0][1] = modelMatrix[1];
axis[0][2] = modelMatrix[2];
axis[1][0] = modelMatrix[4];
axis[1][1] = modelMatrix[5];
axis[1][2] = modelMatrix[6];
axis[2][0] = modelMatrix[8];
axis[2][1] = modelMatrix[9];
axis[2][2] = modelMatrix[10];
origin[0] = modelMatrix[12];
origin[1] = modelMatrix[13];
origin[2] = modelMatrix[14];
}
/*
==========================
R_MultMatrixAligned
==========================
*/
void R_MultMatrixAligned( const float a[16], const float b[16], float output[16] ) {
#if 0
int i, j;
for ( i = 0 ; i < 4 ; i++ ) {
for ( j = 0 ; j < 4 ; j++ ) {
out[ i * 4 + j ] =
a [ i * 4 + 0 ] * b [ 0 * 4 + j ]
+ a [ i * 4 + 1 ] * b [ 1 * 4 + j ]
+ a [ i * 4 + 2 ] * b [ 2 * 4 + j ]
+ a [ i * 4 + 3 ] * b [ 3 * 4 + j ];
}
}
#elif defined( ID_WIN_X86_SSE )
__asm {
mov edx, a
mov eax, output
mov ecx, b
movss xmm0, dword ptr [edx]
movaps xmm1, xmmword ptr [ecx]
shufps xmm0, xmm0, 0
movss xmm2, dword ptr [edx+4]
mulps xmm0, xmm1
shufps xmm2, xmm2, 0
movaps xmm3, xmmword ptr [ecx+10h]
movss xmm7, dword ptr [edx+8]
mulps xmm2, xmm3
shufps xmm7, xmm7, 0
addps xmm0, xmm2
movaps xmm4, xmmword ptr [ecx+20h]
movss xmm2, dword ptr [edx+0Ch]
mulps xmm7, xmm4
shufps xmm2, xmm2, 0
addps xmm0, xmm7
movaps xmm5, xmmword ptr [ecx+30h]
movss xmm6, dword ptr [edx+10h]
mulps xmm2, xmm5
movss xmm7, dword ptr [edx+14h]
shufps xmm6, xmm6, 0
addps xmm0, xmm2
shufps xmm7, xmm7, 0
movlps qword ptr [eax], xmm0
movhps qword ptr [eax+8], xmm0
mulps xmm7, xmm3
movss xmm0, dword ptr [edx+18h]
mulps xmm6, xmm1
shufps xmm0, xmm0, 0
addps xmm6, xmm7
mulps xmm0, xmm4
movss xmm2, dword ptr [edx+24h]
addps xmm6, xmm0
movss xmm0, dword ptr [edx+1Ch]
movss xmm7, dword ptr [edx+20h]
shufps xmm0, xmm0, 0
shufps xmm7, xmm7, 0
mulps xmm0, xmm5
mulps xmm7, xmm1
addps xmm6, xmm0
shufps xmm2, xmm2, 0
movlps qword ptr [eax+10h], xmm6
movhps qword ptr [eax+18h], xmm6
mulps xmm2, xmm3
movss xmm6, dword ptr [edx+28h]
addps xmm7, xmm2
shufps xmm6, xmm6, 0
movss xmm2, dword ptr [edx+2Ch]
mulps xmm6, xmm4
shufps xmm2, xmm2, 0
addps xmm7, xmm6
mulps xmm2, xmm5
movss xmm0, dword ptr [edx+34h]
addps xmm7, xmm2
shufps xmm0, xmm0, 0
movlps qword ptr [eax+20h], xmm7
movss xmm2, dword ptr [edx+30h]
movhps qword ptr [eax+28h], xmm7
mulps xmm0, xmm3
shufps xmm2, xmm2, 0
movss xmm6, dword ptr [edx+38h]
mulps xmm2, xmm1
shufps xmm6, xmm6, 0
addps xmm2, xmm0
mulps xmm6, xmm4
movss xmm7, dword ptr [edx+3Ch]
shufps xmm7, xmm7, 0
addps xmm2, xmm6
mulps xmm7, xmm5
addps xmm2, xmm7
movaps xmmword ptr [eax+30h], xmm2
}
#else
output[0*4+0] = a[0*4+0]*b[0*4+0] + a[0*4+1]*b[1*4+0] + a[0*4+2]*b[2*4+0] + a[0*4+3]*b[3*4+0];
output[0*4+1] = a[0*4+0]*b[0*4+1] + a[0*4+1]*b[1*4+1] + a[0*4+2]*b[2*4+1] + a[0*4+3]*b[3*4+1];
output[0*4+2] = a[0*4+0]*b[0*4+2] + a[0*4+1]*b[1*4+2] + a[0*4+2]*b[2*4+2] + a[0*4+3]*b[3*4+2];
output[0*4+3] = a[0*4+0]*b[0*4+3] + a[0*4+1]*b[1*4+3] + a[0*4+2]*b[2*4+3] + a[0*4+3]*b[3*4+3];
output[1*4+0] = a[1*4+0]*b[0*4+0] + a[1*4+1]*b[1*4+0] + a[1*4+2]*b[2*4+0] + a[1*4+3]*b[3*4+0];
output[1*4+1] = a[1*4+0]*b[0*4+1] + a[1*4+1]*b[1*4+1] + a[1*4+2]*b[2*4+1] + a[1*4+3]*b[3*4+1];
output[1*4+2] = a[1*4+0]*b[0*4+2] + a[1*4+1]*b[1*4+2] + a[1*4+2]*b[2*4+2] + a[1*4+3]*b[3*4+2];
output[1*4+3] = a[1*4+0]*b[0*4+3] + a[1*4+1]*b[1*4+3] + a[1*4+2]*b[2*4+3] + a[1*4+3]*b[3*4+3];
output[2*4+0] = a[2*4+0]*b[0*4+0] + a[2*4+1]*b[1*4+0] + a[2*4+2]*b[2*4+0] + a[2*4+3]*b[3*4+0];
output[2*4+1] = a[2*4+0]*b[0*4+1] + a[2*4+1]*b[1*4+1] + a[2*4+2]*b[2*4+1] + a[2*4+3]*b[3*4+1];
output[2*4+2] = a[2*4+0]*b[0*4+2] + a[2*4+1]*b[1*4+2] + a[2*4+2]*b[2*4+2] + a[2*4+3]*b[3*4+2];
output[2*4+3] = a[2*4+0]*b[0*4+3] + a[2*4+1]*b[1*4+3] + a[2*4+2]*b[2*4+3] + a[2*4+3]*b[3*4+3];
output[3*4+0] = a[3*4+0]*b[0*4+0] + a[3*4+1]*b[1*4+0] + a[3*4+2]*b[2*4+0] + a[3*4+3]*b[3*4+0];
output[3*4+1] = a[3*4+0]*b[0*4+1] + a[3*4+1]*b[1*4+1] + a[3*4+2]*b[2*4+1] + a[3*4+3]*b[3*4+1];
output[3*4+2] = a[3*4+0]*b[0*4+2] + a[3*4+1]*b[1*4+2] + a[3*4+2]*b[2*4+2] + a[3*4+3]*b[3*4+2];
output[3*4+3] = a[3*4+0]*b[0*4+3] + a[3*4+1]*b[1*4+3] + a[3*4+2]*b[2*4+3] + a[3*4+3]*b[3*4+3];
#endif
}
// TEMP TEMP
/*
============
sdGuiSurfaceRenderable::DrawCulled
============
*/
void sdGuiSurfaceRenderable::DrawCulled( const idFrustum& viewFrustum ) const {
// cull if view is behind the gui plane
idVec3 localViewOrigin = axis.TransposeMultiply( viewFrustum.GetOrigin() - origin );
if ( surface.plane.Side( localViewOrigin, 0.1f ) == SIDE_BACK ) {
return;
}
// calculate worldspace bounds
idBounds worldBounds;
worldBounds.FromTransformedBounds( surface.bounds, origin, axis );
// frustum cull
if ( viewFrustum.CullBounds( worldBounds ) ) {
return;
}
Draw();
}
#if !defined( _EDITWORLD )
/*
============
sdGuiSurfaceRenderable::DrawCulled
============
*/
void sdGuiSurfaceRenderable::DrawCulled( const idPVS& pvs, const pvsHandle_t pvsHandle, const idFrustum& viewFrustum ) const {
// cull if view is behind the gui plane
idVec3 localViewOrigin = axis.TransposeMultiply( viewFrustum.GetOrigin() - origin );
if ( surface.plane.Side( localViewOrigin, 0.1f ) == SIDE_BACK ) {
return;
}
// calculate worldspace bounds
idBounds worldBounds;
worldBounds.FromTransformedBounds( surface.bounds, origin, axis );
// cull by pvs
if ( !pvs.InCurrentPVS( pvsHandle, worldBounds ) ) {
return;
}
// frustum cull
if ( viewFrustum.CullBounds( worldBounds ) ) {
return;
}
Draw();
}
#endif /* !_EDITWORLD */
/*
============
sdGuiSurfaceRenderable::Draw
============
*/
void sdGuiSurfaceRenderable::Draw() const {
sdUserInterface* ui = uiManager->GetUserInterface( handle );
if ( ui != NULL ) {
ALIGN16(float entityModelMatrix[16]);
R_AxisToModelMatrix( axis, origin, entityModelMatrix );
// setup the space
ALIGN16( float guiModelMatrix[16] );
ALIGN16( float modelMatrix[16] );
guiModelMatrix[0] = surface.axis[0][0] / static_cast< float >( SCREEN_WIDTH );
guiModelMatrix[4] = surface.axis[1][0] / static_cast< float >( SCREEN_HEIGHT );
guiModelMatrix[8] = surface.axis[2][0];
guiModelMatrix[12] = surface.origin[0];
guiModelMatrix[1] = surface.axis[0][1] / static_cast< float >( SCREEN_WIDTH );
guiModelMatrix[5] = surface.axis[1][1] / static_cast< float >( SCREEN_HEIGHT );
guiModelMatrix[9] = surface.axis[2][1];
guiModelMatrix[13] = surface.origin[1];
guiModelMatrix[2] = surface.axis[0][2] / static_cast< float >( SCREEN_WIDTH );
guiModelMatrix[6] = surface.axis[1][2] / static_cast< float >( SCREEN_HEIGHT );
guiModelMatrix[10] = surface.axis[2][2];
guiModelMatrix[14] = surface.origin[2];
guiModelMatrix[3] = 0.0f;
guiModelMatrix[7] = 0.0f;
guiModelMatrix[11] = 0.0f;
guiModelMatrix[15] = 1.0f;
R_MultMatrixAligned( guiModelMatrix, entityModelMatrix, modelMatrix );
deviceContext->BeginEmitToCurrentView( modelMatrix, allowInViewID, weaponDepthHack );
// emit the drawing commands
ui->Draw();
deviceContext->End();
}
}
/*
============
sdGuiSurfaceRenderable::Trace
============
*/
guiPoint_t sdGuiSurfaceRenderable::Trace( const idVec3& start, const idVec3& end ) const {
idVec3 localDir, localStart, localEnd;
guiPoint_t pt;
pt.x = pt.y = -1;
// compute distance of start to gui plane
localStart = axis.TransposeMultiply( start - origin );
float d1 = surface.plane.Distance( localStart );
if ( d1 < 0.0f ) {
return pt;
}
// compute distance of end to gui plane
localEnd = axis.TransposeMultiply( end - origin );
float d2 = surface.plane.Distance( localEnd );
if ( d2 >= 0.0f ) {
return pt;
}
float denom = d1 - d2;
float t = d1 / denom;
pt.worldPos = localStart + t * ( localEnd - localStart );
// compute the barycentric coordinates
for ( int i = 0; i < surface.numTris; i++ ) {
float u = surface.edgePlanes[ i ][ 0 ].Distance( pt.worldPos );
if ( u < 0.0f || u > 1.0f ) {
continue;
}
float v = surface.edgePlanes[ i ][ 1 ].Distance( pt.worldPos );
if ( v < 0.0f ) {
continue;
}
float w = 1.0f - u - v;
if ( w < 0.0f ) {
continue;
}
// segment intersects tri at distance t in position s
idVec3 cursor = pt.worldPos - surface.origin;
pt.x = ( cursor * surface.axis[0] ) / axisLenSquared[0];
pt.y = ( cursor * surface.axis[1] ) / axisLenSquared[1];
break;
}
return pt;
}
/*
============
sdGuiSurfaceRenderable::GetGuiNum
============
*/
int sdGuiSurfaceRenderable::GetGuiNum() const {
return surface.guiNum;
}
/*
============
sdGuiSurfaceRenderable::GetGuiHandle
============
*/
guiHandle_t sdGuiSurfaceRenderable::GetGuiHandle() const {
return handle;
}