You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1543 lines
42 KiB
1543 lines
42 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Base rendering utilities for all views |
|
// |
|
// $NoKeywords: $ |
|
//===========================================================================// |
|
|
|
#include "stdafx.h" |
|
#include "MapDoc.h" |
|
#include <VGuiMatSurface/IMatSystemSurface.h> |
|
#include "mathlib/vmatrix.h" |
|
#include "Render.h" |
|
#include "Camera.h" |
|
#include "Material.h" |
|
#include "materialsystem/imesh.h" |
|
#include "datacache\imdlcache.h" |
|
#include "hammer.h" |
|
#include "hammer_mathlib.h" |
|
#include "vgui_controls/Controls.h" |
|
#include "vgui/IScheme.h" |
|
#include "texturesystem.h" |
|
#include "IStudioRender.h" |
|
#include "builddisp.h" |
|
#include "mapview.h" |
|
#include "material.h" |
|
#include <renderparm.h> |
|
#include "materialsystem/IMaterialSystemHardwareConfig.h" |
|
#include "vphysics_interface.h" |
|
#include "materialsystem/MaterialSystem_Config.h" |
|
#include "VGuiWnd.h" |
|
#include "Box3D.h" |
|
#include "MapInstance.h" |
|
|
|
extern IMatSystemSurface *g_pMatSystemSurface; |
|
|
|
static float s_fOneUnitLength = 1; |
|
|
|
CRender::CRender(void) |
|
{ |
|
m_pView = NULL; |
|
|
|
// returns a handle to the default (first loaded) scheme |
|
vgui::IScheme * pScheme = vgui::scheme()->GetIScheme( vgui::scheme()->GetDefaultScheme() ); |
|
if ( pScheme ) |
|
{ |
|
m_DefaultFont = pScheme->GetFont( "Default" ); |
|
} |
|
else |
|
{ |
|
m_DefaultFont = vgui::INVALID_FONT; |
|
|
|
static bool s_bOnce = false; |
|
if ( !s_bOnce ) |
|
{ |
|
s_bOnce = true; |
|
MessageBox( NULL, "Failed to load the default scheme file. The map views may be missing some visual elements.", "Error", MB_OK | MB_ICONEXCLAMATION ); |
|
} |
|
} |
|
|
|
for (int i = 0; i < 2; ++i) |
|
{ |
|
m_pFlat[i] = NULL; |
|
m_pWireframe[i] = NULL; |
|
m_pTranslucentFlat[i] = NULL; |
|
m_pLightmapGrid[i] = NULL; |
|
m_pSelectionOverlay[i] = NULL; |
|
m_pDotted[i] = NULL; |
|
m_pFlatNoZ[i] = NULL; |
|
m_pFlatNoCull[i] = NULL; |
|
} |
|
|
|
m_pCurrentMaterial = NULL; |
|
m_pBoundMaterial = NULL; |
|
|
|
m_nDecalMode = 0; |
|
|
|
m_bIsRendering = false; |
|
m_bIsClientSpace = false; |
|
m_bIsLocalTransform = false; |
|
m_bIsRenderingIntoVGUI = false; |
|
|
|
VMatrix IdentityMatrix; |
|
|
|
IdentityMatrix.Identity(); |
|
m_LocalMatrix.AddToHead( IdentityMatrix ); |
|
|
|
m_OrthoMatrix.Identity(); |
|
m_eCurrentRenderMode = m_eDefaultRenderMode = RENDER_MODE_FLAT; |
|
|
|
m_bInstanceRendering = false; |
|
m_nInstanceCount = 0; |
|
m_InstanceSelectionDepth = 0; |
|
|
|
PushInstanceData( NULL, Vector( 0.0f, 0.0f, 0.0f ), QAngle( 0.0f, 0.0f, 0.0f ) ); // always add a default state |
|
|
|
UpdateStudioRenderConfig( false, false ); |
|
} |
|
|
|
CRender::~CRender(void) |
|
{ |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: this function will push all of the instance data |
|
// Input : pInstanceClass - the func_instance entity |
|
// InstanceOrigin - the translation of the instance |
|
// InstanceAngles - the rotation of the instance |
|
// Output : none |
|
//----------------------------------------------------------------------------- |
|
void CRender::PushInstanceData( CMapInstance *pInstanceClass, Vector &InstanceOrigin, QAngle &InstanceAngles ) |
|
{ |
|
TInstanceState InstanceState; |
|
matrix3x4_t Instance3x4Matrix; |
|
|
|
InstanceState.m_InstanceOrigin = InstanceOrigin; |
|
InstanceState.m_InstanceAngles = InstanceAngles; |
|
InstanceState.m_pInstanceClass = pInstanceClass; |
|
InstanceState.m_pTopInstanceClass = NULL; |
|
|
|
AngleMatrix( InstanceState.m_InstanceAngles, InstanceState.m_InstanceOrigin, Instance3x4Matrix ); |
|
InstanceState.m_InstanceMatrix.Init( Instance3x4Matrix ); |
|
|
|
Vector vecTransformedOrigin; |
|
TransformInstanceVector( InstanceState.m_InstanceOrigin, vecTransformedOrigin ); |
|
m_CurrentInstanceState.m_InstanceOrigin = vecTransformedOrigin; |
|
// RotateInstanceVector( ( Vector )InstanceState.m_InstanceAngles, m_CurrentInstanceState.m_InstanceAngles ); no one uses this right now make sure to store it in the same fashion as vecTransformedOrigin |
|
|
|
if ( m_InstanceState.Count() > 0 ) |
|
{ // first push is just a default state |
|
m_bInstanceRendering = true; |
|
BeginLocalTransfrom( InstanceState.m_InstanceMatrix, true ); |
|
if ( m_CurrentInstanceState.m_pTopInstanceClass == NULL ) |
|
{ |
|
if ( pInstanceClass->IsEditable() == false ) |
|
{ |
|
InstanceState.m_pTopInstanceClass = pInstanceClass; |
|
} |
|
} |
|
else |
|
{ |
|
InstanceState.m_pTopInstanceClass = m_CurrentInstanceState.m_pTopInstanceClass; |
|
} |
|
if ( pInstanceClass->IsSelected() || m_InstanceSelectionDepth ) |
|
{ |
|
m_InstanceSelectionDepth++; |
|
} |
|
InstanceState.m_InstanceMatrix = m_CurrentInstanceState.m_InstanceMatrix * InstanceState.m_InstanceMatrix; |
|
InstanceState.m_bIsEditable = pInstanceClass->IsEditable(); |
|
} |
|
else |
|
{ |
|
m_bInstanceRendering = false; |
|
InstanceState.m_bIsEditable = true; |
|
} |
|
|
|
InstanceState.m_InstanceRenderMatrix = m_LocalMatrix.Head(); |
|
m_InstanceState.AddToHead( InstanceState ); |
|
m_CurrentInstanceState = InstanceState; |
|
|
|
if ( !pInstanceClass ) |
|
{ |
|
} |
|
else if ( m_InstanceSelectionDepth > 0 ) |
|
{ |
|
PushInstanceRendering( INSTANCE_STACE_SELECTED ); |
|
} |
|
else if ( pInstanceClass->IsEditable() || CMapDoc::GetActiveMapDoc()->GetShowInstance() == INSTANCES_SHOW_NORMAL ) |
|
{ |
|
PushInstanceRendering( INSTANCE_STATE_OFF ); |
|
} |
|
else |
|
{ |
|
PushInstanceRendering( GetInstanceClass()->IsSelected() ? INSTANCE_STACE_SELECTED : INSTANCE_STATE_ON ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: this function will pop off the top most instance data |
|
//----------------------------------------------------------------------------- |
|
void CRender::PopInstanceData( void ) |
|
{ |
|
if ( m_CurrentInstanceState.m_pInstanceClass ) |
|
{ |
|
PopInstanceRendering(); |
|
} |
|
|
|
m_InstanceState.Remove( 0 ); |
|
m_CurrentInstanceState = m_InstanceState.Head(); |
|
|
|
if ( m_InstanceState.Count() > 1 ) |
|
{ // first push is just a default state |
|
m_bInstanceRendering = true; |
|
} |
|
else |
|
{ |
|
m_bInstanceRendering = false; |
|
} |
|
|
|
if ( m_InstanceSelectionDepth > 0 ) |
|
{ |
|
m_InstanceSelectionDepth--; |
|
} |
|
|
|
EndLocalTransfrom(); |
|
|
|
// m_CurrentInstanceState.m_InstanceRenderMatrix = m_LocalMatrix.Head(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: this function initializes the stencil buffer for instance rendering |
|
//----------------------------------------------------------------------------- |
|
void CRender::PrepareInstanceStencil( void ) |
|
{ |
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
|
|
#if STENCIL_AS_CALLS |
|
pRenderContext->SetStencilEnable( true ); |
|
pRenderContext->SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS ); |
|
pRenderContext->SetStencilFailOperation( STENCILOPERATION_KEEP ); |
|
pRenderContext->SetStencilZFailOperation( STENCILOPERATION_KEEP ); |
|
pRenderContext->SetStencilWriteMask( 0xff ); |
|
pRenderContext->SetStencilTestMask( 0xff ); |
|
pRenderContext->SetStencilReferenceValue( 0x01 ); |
|
pRenderContext->SetStencilPassOperation( STENCILOPERATION_ZERO); |
|
#else |
|
m_ShaderStencilState.m_bEnable = true; |
|
m_ShaderStencilState.m_CompareFunc = SHADER_STENCILFUNC_ALWAYS; |
|
m_ShaderStencilState.m_FailOp = SHADER_STENCILOP_KEEP; |
|
m_ShaderStencilState.m_ZFailOp = SHADER_STENCILOP_KEEP; |
|
m_ShaderStencilState.m_nWriteMask = 0xff; |
|
m_ShaderStencilState.m_nTestMask = 0xff; |
|
m_ShaderStencilState.m_nReferenceValue = 0x01; |
|
m_ShaderStencilState.m_PassOp = SHADER_STENCILOP_ZERO; |
|
pRenderContext->SetStencilState( m_ShaderStencilState ); |
|
#endif // STENCIL_AS_CALLS |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: this function will draw the various alpha color 2d rectangles for the instance states |
|
//----------------------------------------------------------------------------- |
|
void CRender::DrawInstanceStencil( void ) |
|
{ |
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
CCamera *pCamera = GetCamera(); |
|
|
|
if ( m_nNumInstancesRendered > 0 ) |
|
{ |
|
#if STENCIL_AS_CALLS |
|
pRenderContext->SetStencilPassOperation( STENCILOPERATION_KEEP ); |
|
pRenderContext->SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL ); |
|
#else |
|
m_ShaderStencilState.m_PassOp = SHADER_STENCILOP_KEEP; |
|
m_ShaderStencilState.m_CompareFunc = SHADER_STENCILFUNC_EQUAL; |
|
#endif // STENCIL_AS_CALLS |
|
|
|
Color InstanceColoring; |
|
int width, height; |
|
|
|
pCamera->GetViewPort( width, height ); |
|
PushRenderMode( RENDER_MODE_INSTANCE_OVERLAY ); |
|
|
|
BeginClientSpace(); |
|
InstanceColor( InstanceColoring, false ); |
|
#if STENCIL_AS_CALLS |
|
pRenderContext->SetStencilReferenceValue( 0x01 ); |
|
#else |
|
m_ShaderStencilState.m_nReferenceValue = 0x01; |
|
pRenderContext->SetStencilState( m_ShaderStencilState ); |
|
#endif // STENCIL_AS_CALLS |
|
DrawFilledRect( Vector2D( 0.0f, 0.0f ), Vector2D( width, height ), ( byte * )&InstanceColoring, false ); |
|
|
|
InstanceColor( InstanceColoring, true ); |
|
#if STENCIL_AS_CALLS |
|
pRenderContext->SetStencilTestMask( 0xff ); |
|
pRenderContext->SetStencilReferenceValue( 0x02 ); |
|
#else |
|
m_ShaderStencilState.m_nReferenceValue = 0x02; |
|
pRenderContext->SetStencilState( m_ShaderStencilState ); |
|
#endif // STENCIL_AS_CALLS |
|
DrawFilledRect( Vector2D( 0.0f, 0.0f ), Vector2D( width, height ), ( byte * )&InstanceColoring, false ); |
|
|
|
EndClientSpace(); |
|
PopRenderMode(); |
|
} |
|
#if STENCIL_AS_CALLS |
|
pRenderContext->SetStencilEnable( false ); |
|
#else |
|
m_ShaderStencilState.m_bEnable = false; |
|
pRenderContext->SetStencilState( m_ShaderStencilState ); |
|
#endif // STENCIL_AS_CALLS |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: this function will push all of the instance data |
|
// Input : pInstanceClass - the func_instance entity |
|
// InstanceOrigin - the translation of the instance |
|
// InstanceAngles - the rotation of the instance |
|
// Output : none |
|
//----------------------------------------------------------------------------- |
|
void CRender::PushInstanceRendering( InstanceRenderingState_t State ) |
|
{ |
|
SetInstanceRendering( State ); |
|
|
|
m_InstanceRenderingState.AddToHead( State ); |
|
|
|
if ( State != INSTANCE_STATE_OFF ) |
|
{ |
|
m_nNumInstancesRendered++; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: this function will pop off the top most instance data |
|
//----------------------------------------------------------------------------- |
|
void CRender::PopInstanceRendering( void ) |
|
{ |
|
m_InstanceRenderingState.Remove( 0 ); |
|
if ( m_InstanceRenderingState.Count() > 0 ) |
|
{ |
|
SetInstanceRendering( m_InstanceRenderingState.Head() ); |
|
} |
|
else |
|
{ |
|
SetInstanceRendering( INSTANCE_STATE_OFF ); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Sets the instance rendering state for stencil buffer operations. |
|
// 0 in stencil buffer = normal drawing |
|
// 1 in stencil buffer = instance shaded pass |
|
// 2 in stencil buffer = instance selected shaded pass |
|
// Input : State - the state at which the next drawing operations should impact |
|
// the stencil buffer |
|
//----------------------------------------------------------------------------- |
|
void CRender::SetInstanceRendering( InstanceRenderingState_t State ) |
|
{ |
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
|
|
switch( State ) |
|
{ |
|
case INSTANCE_STATE_OFF: |
|
#ifdef STENCIL_AS_CALLS |
|
pRenderContext->SetStencilPassOperation( STENCILOPERATION_ZERO ); |
|
#else |
|
m_ShaderStencilState.m_PassOp = SHADER_STENCILOP_ZERO; |
|
#endif // STENCIL_AS_CALLS |
|
break; |
|
|
|
case INSTANCE_STATE_ON: |
|
#if STENCIL_AS_CALLS |
|
pRenderContext->SetStencilPassOperation( STENCILOPERATION_REPLACE ); |
|
pRenderContext->SetStencilReferenceValue( 0x01 ); |
|
#else |
|
m_ShaderStencilState.m_PassOp = SHADER_STENCILOP_SET_TO_REFERENCE; |
|
m_ShaderStencilState.m_nReferenceValue = 0x01; |
|
#endif // STENCIL_AS_CALLS |
|
break; |
|
|
|
case INSTANCE_STACE_SELECTED: |
|
#if STENCIL_AS_CALLS |
|
pRenderContext->SetStencilPassOperation( STENCILOPERATION_REPLACE ); |
|
pRenderContext->SetStencilReferenceValue( 0x02 ); |
|
#else |
|
m_ShaderStencilState.m_PassOp = SHADER_STENCILOP_SET_TO_REFERENCE; |
|
m_ShaderStencilState.m_nReferenceValue = 0x02; |
|
#endif // STENCIL_AS_CALLS |
|
break; |
|
} |
|
|
|
#ifndef STENCIL_AS_CALLS |
|
pRenderContext->SetStencilState( m_ShaderStencilState ); |
|
#endif // STENCIL_AS_CALLS |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: This function renders a text string at the given position, width, |
|
// height, and format |
|
// Input: text - the string to print |
|
// pos - the screen space position of the text (the is the top-left of |
|
// a screen space rect) |
|
// width - the width to render the text into |
|
// height - the height to render the text into |
|
// nFlags - define the text format -- see SetTextFormat |
|
//----------------------------------------------------------------------------- |
|
void CRender::DrawText( const char *text, int x, int y, int nFlags ) |
|
{ |
|
wchar_t unicode[ 128 ]; |
|
|
|
mbstowcs( unicode, text, ARRAYSIZE(unicode) ); |
|
|
|
int len = min( 127, Q_strlen( text ) ); |
|
|
|
Assert( m_DefaultFont != vgui::INVALID_FONT ); |
|
bool bJustifyText = nFlags & ( TEXT_JUSTIFY_LEFT | TEXT_JUSTIFY_TOP | TEXT_JUSTIFY_HORZ_CENTER | TEXT_JUSTIFY_VERT_CENTER ); |
|
if ( bJustifyText && m_DefaultFont != vgui::INVALID_FONT ) |
|
{ |
|
int wide,tall; |
|
g_pMatSystemSurface->GetTextSize( m_DefaultFont, unicode, wide, tall ); |
|
|
|
if ( nFlags & TEXT_JUSTIFY_LEFT ) |
|
x -= wide; |
|
|
|
if ( nFlags & TEXT_JUSTIFY_TOP ) |
|
y -= tall; |
|
|
|
if ( nFlags & TEXT_JUSTIFY_HORZ_CENTER ) |
|
x -= wide/2; |
|
|
|
if ( nFlags & TEXT_JUSTIFY_VERT_CENTER ) |
|
y -= tall/2; |
|
} |
|
|
|
PushRenderMode( RENDER_MODE_EXTERN ); |
|
|
|
bool bPopMode = BeginClientSpace(); |
|
|
|
g_pMatSystemSurface->DrawSetTextPos( x, y ); |
|
g_pMatSystemSurface->DrawPrintText( unicode, len ); |
|
|
|
if ( bPopMode ) |
|
EndClientSpace(); |
|
|
|
PopRenderMode(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Uses "world" coordinates |
|
//----------------------------------------------------------------------------- |
|
void CRender::DrawText( const char *text, const Vector2D &vPos, int nOffsetX, int nOffsetY, int nFlags ) |
|
{ |
|
Vector vecActualPos( vPos.x, vPos.y, 0.0f ); |
|
if ( IsInLocalTransformMode() ) |
|
{ |
|
VMatrix matrix; |
|
GetLocalTranform( matrix ); |
|
Vector vWorld = vecActualPos; |
|
Vector3DMultiplyPosition( matrix, vWorld, vecActualPos ); |
|
} |
|
|
|
Vector2D pt; |
|
m_pView->WorldToClient( pt, vecActualPos ); |
|
DrawText( text, (int)pt.x + nOffsetX, (int)pt.y + nOffsetY, nFlags ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: set the text and background (behind text) colors |
|
// Input: tR, tG, tB - text red, green, and blue values : [0...255] |
|
// bkR, bkG, bkB - background red, green, blue values : [0...255] |
|
//----------------------------------------------------------------------------- |
|
void CRender::SetTextColor( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) |
|
{ |
|
m_TextColor.SetColor( r,g,b,a ); |
|
if ( m_bIsRenderingIntoVGUI ) |
|
{ |
|
g_pMatSystemSurface->DrawSetTextColor( m_TextColor ); |
|
} |
|
} |
|
|
|
void CRender::SetHandleColor( unsigned char r, unsigned char g, unsigned char b ) |
|
{ |
|
m_HandleColor.SetColor( r, g, b, 255 ); |
|
} |
|
|
|
void CRender::UpdateStudioRenderConfig( bool bFlat, bool bWireframe ) |
|
{ |
|
StudioRenderConfig_t config; |
|
memset( &config, 0, sizeof( config ) ); |
|
config.fEyeShiftX = 0.0f; |
|
config.fEyeShiftY = 0.0f; |
|
config.fEyeShiftZ = 0.0f; |
|
config.fEyeSize = 0; |
|
config.drawEntities = 1; |
|
config.skin = 0; |
|
config.fullbright = MaterialSystemConfig().nFullbright; |
|
config.bEyeMove = true; |
|
config.bSoftwareSkin = bWireframe; |
|
config.bNoHardware = false; |
|
config.bNoSoftware = false; |
|
config.bTeeth = false; |
|
config.bEyes = true; |
|
config.bFlex = true; |
|
config.bSoftwareLighting = true; |
|
config.bWireframe = bWireframe; |
|
config.bDrawNormals = false; |
|
config.bShowEnvCubemapOnly = false; |
|
g_pStudioRender->UpdateConfig( config ); |
|
} |
|
|
|
void CRender::StartRenderFrame() |
|
{ |
|
Assert( !m_bIsRendering ); |
|
|
|
m_nNumInstancesRendered = 0; |
|
|
|
m_bIsRenderingIntoVGUI = dynamic_cast<CVGuiWnd*>( GetView() ); |
|
if ( m_bIsRenderingIntoVGUI ) |
|
{ |
|
g_pMatSystemSurface->DrawSetTextFont( m_DefaultFont ); |
|
g_pMatSystemSurface->DrawSetTextColor( m_TextColor ); |
|
g_pMatSystemSurface->DrawSetColor( m_DrawColor ); |
|
} |
|
|
|
int width, height; |
|
VMatrix matrix; |
|
CCamera *pCamera = GetCamera(); |
|
|
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
|
|
// build ortho matrix for client space mode |
|
pCamera->GetViewPort( width, height ); |
|
pRenderContext->MatrixMode(MATERIAL_PROJECTION); |
|
pRenderContext->LoadIdentity(); |
|
pRenderContext->Scale( 1, -1, 1 ); |
|
pRenderContext->Ortho(0, 0, width, height, -99999, 99999 ); |
|
pRenderContext->GetMatrix( MATERIAL_PROJECTION, &m_OrthoMatrix ); |
|
|
|
// setup world camera |
|
pCamera->GetProjMatrix(matrix); |
|
pRenderContext->MatrixMode( MATERIAL_PROJECTION ); |
|
pRenderContext->LoadMatrix( matrix ); |
|
|
|
pCamera->GetViewMatrix(matrix); |
|
pRenderContext->MatrixMode( MATERIAL_VIEW ); |
|
pRenderContext->LoadMatrix( matrix ); |
|
|
|
pRenderContext->MatrixMode(MATERIAL_MODEL); |
|
pRenderContext->LoadIdentity(); |
|
|
|
pRenderContext->SetAmbientLight( 1.0, 1.0, 1.0 ); |
|
|
|
pCamera->GetViewMatrix( m_CurrentMatrix ); |
|
|
|
// Disable all the lights.. |
|
for( int i = 0; i < MaterialSystemHardwareConfig()->MaxNumLights(); ++i) |
|
{ |
|
LightDesc_t desc; |
|
desc.m_Type = MATERIAL_LIGHT_DISABLE; |
|
pRenderContext->SetLight( i, desc ); |
|
} |
|
|
|
m_bIsClientSpace = false; |
|
|
|
// reset render mode |
|
m_RenderModeStack.Clear(); |
|
SetRenderMode( m_eDefaultRenderMode, true ); |
|
|
|
// reset colors |
|
m_DrawColor.SetColor( 255,255,255,255 ); |
|
m_TextColor.SetColor( 255,255,255,255 ); |
|
m_HandleColor.SetColor( 255,255,255,255 ); |
|
|
|
s_fOneUnitLength = 1/pCamera->GetZoom(); |
|
|
|
// tell studiorender that we've updated the camera. |
|
if( g_pStudioRender ) |
|
{ |
|
g_pStudioRender->BeginFrame(); |
|
|
|
Vector viewOrigin, viewRight, viewUp, viewForward; |
|
pCamera->GetViewPoint( viewOrigin ); |
|
pCamera->GetViewRight( viewRight ); |
|
pCamera->GetViewUp( viewUp ); |
|
pCamera->GetViewForward( viewForward ); |
|
|
|
g_pStudioRender->SetViewState( viewOrigin, viewRight, viewUp, viewForward ); |
|
|
|
static Vector white[6] = |
|
{ |
|
Vector( 1.0, 1.0, 1.0 ), |
|
Vector( 1.0, 1.0, 1.0 ), |
|
Vector( 1.0, 1.0, 1.0 ), |
|
Vector( 1.0, 1.0, 1.0 ), |
|
Vector( 1.0, 1.0, 1.0 ), |
|
Vector( 1.0, 1.0, 1.0 ), |
|
}; |
|
|
|
g_pStudioRender->SetAmbientLightColors( white ); |
|
} |
|
|
|
m_bIsRendering = true; |
|
} |
|
|
|
void CRender::EndRenderFrame() |
|
{ |
|
Assert( m_bIsRendering ); |
|
Assert( !m_bIsClientSpace ); |
|
Assert( m_RenderModeStack.Count() == 0 ); |
|
Assert( !m_bIsLocalTransform ); |
|
|
|
if ( g_pStudioRender ) |
|
{ |
|
g_pStudioRender->BeginFrame(); |
|
} |
|
|
|
// turn off lighting preview shader state |
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
pRenderContext->SetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING,0); |
|
|
|
m_nFrameCount++; |
|
m_bIsRendering = false; |
|
m_bIsRenderingIntoVGUI = false; |
|
} |
|
|
|
void CRender::DrawLine( const Vector &vStart, const Vector &vEnd ) |
|
{ |
|
float scale = VectorLength( vEnd-vStart ) / ( s_fOneUnitLength * 16 ); |
|
|
|
meshBuilder.Begin(m_pMesh, MATERIAL_LINES, 1); |
|
|
|
meshBuilder.Position3fv(vStart.Base()); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.TexCoord2f(0, 0, 0); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv(vEnd.Base()); |
|
meshBuilder.Color4ubv((byte*)&m_DrawColor); |
|
meshBuilder.TexCoord2f(0, scale, scale); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::BeginLocalTransfrom( const VMatrix &matrix, bool MultiplyCurrent ) |
|
{ |
|
Assert( !m_bIsClientSpace ); |
|
|
|
VMatrix LocalCopy = matrix; |
|
|
|
if ( MultiplyCurrent ) |
|
{ |
|
LocalCopy = m_LocalMatrix.Head() * LocalCopy; |
|
} |
|
m_LocalMatrix.AddToHead( LocalCopy ); |
|
|
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
pRenderContext->MatrixMode(MATERIAL_MODEL); |
|
pRenderContext->PushMatrix(); |
|
pRenderContext->LoadMatrix( m_LocalMatrix.Head() ); |
|
|
|
CCamera *pCamera = GetCamera(); |
|
pCamera->GetViewMatrix( m_CurrentMatrix ); |
|
m_CurrentMatrix = m_CurrentMatrix * LocalCopy; |
|
|
|
m_bIsLocalTransform = true; |
|
} |
|
|
|
void CRender::EndLocalTransfrom() |
|
{ |
|
Assert( m_bIsLocalTransform ); |
|
Assert( !m_bIsClientSpace ); |
|
|
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
|
|
pRenderContext->MatrixMode(MATERIAL_MODEL); |
|
pRenderContext->PopMatrix(); |
|
|
|
m_LocalMatrix.Remove( 0 ); |
|
|
|
CCamera *pCamera = GetCamera(); |
|
pCamera->GetViewMatrix( m_CurrentMatrix ); |
|
if ( m_LocalMatrix.Count() > 1 ) |
|
{ |
|
m_CurrentMatrix = m_CurrentMatrix * m_LocalMatrix.Head(); |
|
m_bIsLocalTransform = true; |
|
} |
|
else |
|
{ |
|
m_bIsLocalTransform = false; |
|
} |
|
} |
|
|
|
bool CRender::IsInLocalTransformMode() |
|
{ |
|
return m_bIsLocalTransform; |
|
} |
|
|
|
void CRender::GetLocalTranform( VMatrix &matrix ) |
|
{ |
|
matrix = m_LocalMatrix.Head(); |
|
} |
|
|
|
bool CRender::BeginClientSpace(void) |
|
{ |
|
if ( m_bIsClientSpace ) |
|
return false; |
|
|
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
|
|
pRenderContext->MatrixMode( MATERIAL_PROJECTION ); |
|
pRenderContext->PushMatrix(); |
|
pRenderContext->LoadMatrix( m_OrthoMatrix ); |
|
|
|
pRenderContext->MatrixMode(MATERIAL_VIEW); |
|
pRenderContext->PushMatrix(); |
|
pRenderContext->LoadIdentity(); |
|
|
|
if ( m_bIsLocalTransform ) |
|
{ |
|
pRenderContext->MatrixMode(MATERIAL_MODEL); |
|
pRenderContext->PushMatrix(); |
|
pRenderContext->LoadIdentity(); |
|
} |
|
|
|
m_bIsClientSpace = true; |
|
|
|
return true; |
|
} |
|
|
|
void CRender::EndClientSpace(void) |
|
{ |
|
Assert( m_bIsClientSpace ); |
|
|
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
|
|
pRenderContext->MatrixMode(MATERIAL_VIEW); |
|
pRenderContext->PopMatrix(); |
|
|
|
pRenderContext->MatrixMode(MATERIAL_PROJECTION); |
|
pRenderContext->PopMatrix(); |
|
|
|
if ( m_bIsLocalTransform ) |
|
{ |
|
pRenderContext->MatrixMode(MATERIAL_MODEL); |
|
pRenderContext->PopMatrix(); |
|
} |
|
|
|
m_bIsClientSpace = false; |
|
} |
|
|
|
void CRender::TransformPoint( Vector2D &vClient, const Vector& vWorld ) |
|
{ |
|
Vector vecActualPos; |
|
|
|
if ( !m_bIsLocalTransform ) |
|
{ |
|
vecActualPos = vWorld; |
|
} |
|
else |
|
{ |
|
m_LocalMatrix.Head().V3Mul( vWorld, vecActualPos ); |
|
} |
|
|
|
m_pView->WorldToClient( vClient, vecActualPos ); |
|
} |
|
|
|
|
|
void CRender::TransformNormal( Vector2D &vClient, const Vector& vWorld ) |
|
{ |
|
Vector2D originClient, normalClient; |
|
TransformPoint( originClient, vec3_origin ); |
|
TransformPoint( normalClient, vWorld ); |
|
vClient = normalClient- originClient; |
|
} |
|
|
|
void CRender::DrawCircle( const Vector &vCenter, const Vector &vNormal, float flRadius, int nSegments) |
|
{ |
|
Vector vx,vy; |
|
|
|
if ( !BuildAxesFromNormal( vNormal, vx, vy ) ) |
|
return; |
|
|
|
vx *= flRadius; |
|
vy *= flRadius; |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINE_LOOP, nSegments ); |
|
|
|
float invDelta = 2.0f * M_PI / nSegments; |
|
for ( int i = 0; i < nSegments; ++i ) |
|
{ |
|
float flRadians = i * invDelta; |
|
float ca = cos( flRadians ); |
|
float sa = sin( flRadians ); |
|
|
|
// Rotate it around the circle |
|
Vector vertex = vCenter + (ca*vx) + (sa*vy); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.Position3fv( &vertex.x ); |
|
meshBuilder.AdvanceVertex(); |
|
} |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::DrawCircle( Vector2D &vCenter, float fRadius, int nSegments, unsigned char *pColor ) |
|
{ |
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINE_LOOP, nSegments ); |
|
|
|
float invDelta = 2.0f * M_PI / nSegments; |
|
for ( int i = 0; i < nSegments; ++i ) |
|
{ |
|
float flRadians = i * invDelta; |
|
float ca = cos( flRadians ); |
|
float sa = sin( flRadians ); |
|
|
|
// Rotate it around the circle |
|
float x = vCenter.x + (fRadius * ca); |
|
float y = vCenter.y + (fRadius * sa); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( x, y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
} |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::DrawCross( Vector2D& ul, Vector2D& lr, unsigned char *pColor ) |
|
{ |
|
// just sizes |
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINES, 2 ); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( ul.x, ul.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( lr.x, lr.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( ul.x, lr.y-1, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( lr.x, ul.y-1, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::DrawRect( Vector2D& ul, Vector2D& lr, unsigned char *pColor ) |
|
{ |
|
Vector2D vScale = (lr-ul)/16; |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINE_LOOP, 4 ); |
|
|
|
Vector2D tex(0,0); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( ul.x, ul.y, 0 ); |
|
meshBuilder.TexCoord2f(0, tex.x, tex.y ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
tex.x += vScale.x; |
|
tex.y += vScale.x; |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( lr.x, ul.y, 0 ); |
|
meshBuilder.TexCoord2f(0, tex.x, tex.y ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
tex.x += vScale.y; |
|
tex.y -= vScale.y; |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( lr.x, lr.y, 0 ); |
|
meshBuilder.TexCoord2f(0, tex.x, tex.y ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
tex.x -= vScale.x; |
|
tex.y -= vScale.x; |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( ul.x, lr.y, 0 ); |
|
meshBuilder.TexCoord2f(0, tex.x, tex.y ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::DrawPlane( const Vector &p0, const Vector &p1, const Vector &p2, const Vector &p3, bool bFill ) |
|
{ |
|
if ( bFill ) |
|
{ |
|
meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, 1 ); |
|
} |
|
else |
|
{ |
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINE_LOOP, 4 ); |
|
} |
|
|
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.Position3fv( &p0.x ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.Position3fv( &p1.x ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.Position3fv( &p2.x ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.Position3fv( &p3.x ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::DrawFilledRect( Vector2D& ul, Vector2D& lr, unsigned char *pColor, bool bBorder ) |
|
{ |
|
static Color black(0,0,0,255); |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, bBorder?2:1 ); |
|
|
|
if ( bBorder ) |
|
{ |
|
meshBuilder.Color4ubv( (byte*)&black ); |
|
meshBuilder.Position3f( ul.x, ul.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( (byte*)&black ); |
|
meshBuilder.Position3f( lr.x, ul.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( (byte*)&black ); |
|
meshBuilder.Position3f( lr.x, lr.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( (byte*)&black ); |
|
meshBuilder.Position3f( ul.x, lr.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
|
|
ul.x+=1; |
|
ul.y+=1; |
|
lr.x-=1; |
|
lr.y-=1; |
|
} |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( ul.x, ul.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( lr.x, ul.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( lr.x, lr.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Color4ubv( pColor ); |
|
meshBuilder.Position3f( ul.x, lr.y, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::DrawHandle( const Vector &vCenter, const Vector2D *vOffset ) |
|
{ |
|
if ( !m_CurrentInstanceState.m_bIsEditable ) |
|
{ |
|
return; |
|
} |
|
|
|
int size = m_nHandleSize; |
|
|
|
bool bPopMode = BeginClientSpace(); |
|
|
|
Vector2D vCenter2D; |
|
|
|
TransformPoint( vCenter2D, vCenter ); |
|
|
|
if ( vOffset ) |
|
{ |
|
vCenter2D += *vOffset; |
|
} |
|
|
|
RoundVector( vCenter2D ); |
|
|
|
if ( m_nHandleType == HANDLE_CROSS ) |
|
size--; |
|
|
|
Vector2D ul( vCenter2D.x-size, vCenter2D.y-size ); |
|
Vector2D lr( vCenter2D.x+size+1, vCenter2D.y+size+1 ); |
|
|
|
switch ( m_nHandleType ) |
|
{ |
|
case HANDLE_SQUARE : DrawFilledRect( ul, lr, (byte*)&m_HandleColor, true );break; |
|
case HANDLE_CIRCLE : DrawCircle( vCenter2D, size, 16, (byte*)&m_HandleColor ); break; |
|
case HANDLE_DIAMOND : break; |
|
case HANDLE_CROSS : DrawCross( ul, lr, (byte*)&m_HandleColor );break; |
|
} |
|
|
|
if ( bPopMode ) |
|
EndClientSpace(); |
|
} |
|
|
|
CCamera *CRender::GetCamera() |
|
{ |
|
return m_pView->GetCamera(); |
|
} |
|
|
|
bool CRender::SetView( CMapView * pView ) |
|
{ |
|
Assert( pView ); |
|
|
|
m_pView = pView; |
|
|
|
// Store off the three materials we use most often... |
|
if ( !GetRequiredMaterial( "editor/wireframe", m_pWireframe[0] ) || |
|
!GetRequiredMaterial( "editor/flat", m_pFlat[0] ) || |
|
!GetRequiredMaterial( "editor/flatdecal", m_pFlat[1] ) || |
|
!GetRequiredMaterial( "editor/translucentflat", m_pTranslucentFlat[0] ) || |
|
!GetRequiredMaterial( "editor/translucentflatdecal", m_pTranslucentFlat[1] ) || |
|
!GetRequiredMaterial( "editor/lightmapgrid", m_pLightmapGrid[0] ) || |
|
!GetRequiredMaterial( "editor/lightmapgriddecal", m_pLightmapGrid[1] ) || |
|
!GetRequiredMaterial( "editor/selectionoverlay", m_pSelectionOverlay[0] ) || |
|
!GetRequiredMaterial( "editor/flatignorez", m_pFlatNoZ[0] ) || |
|
!GetRequiredMaterial( "editor/flatnocull", m_pFlatNoCull[0] ) || |
|
!GetRequiredMaterial( "editor/dotted", m_pDotted[0] ) |
|
) |
|
{ |
|
return false; |
|
} |
|
|
|
// Some materials don't have a separate decal version. |
|
m_pFlatNoZ[1] = m_pFlatNoZ[0]; |
|
m_pFlatNoCull[1] = m_pFlatNoCull[0]; |
|
m_pWireframe[1] = m_pWireframe[0]; |
|
m_pDotted[1] = m_pDotted[0]; |
|
m_pSelectionOverlay[1] = m_pSelectionOverlay[0]; |
|
|
|
return true; |
|
|
|
} |
|
|
|
bool CRender::IsActiveView() |
|
{ |
|
return m_pView->IsActive(); |
|
} |
|
|
|
void CRender::SetDrawColor( const Color &color ) |
|
{ |
|
m_DrawColor = color; |
|
if ( m_bIsRenderingIntoVGUI ) |
|
{ |
|
g_pMatSystemSurface->DrawSetColor( m_DrawColor ); |
|
} |
|
} |
|
|
|
void CRender::GetDrawColor( Color &color ) |
|
{ |
|
color = m_DrawColor; |
|
} |
|
|
|
void CRender::SetDrawColor( unsigned char r, unsigned char g, unsigned char b ) |
|
{ |
|
// current draw color, keep the alpha value |
|
m_DrawColor.SetColor( r, g, b, m_DrawColor.a() ); |
|
if ( m_bIsRenderingIntoVGUI ) |
|
{ |
|
g_pMatSystemSurface->DrawSetColor( m_DrawColor ); |
|
} |
|
} |
|
|
|
void CRender::SetHandleStyle( int size, int type ) |
|
{ |
|
m_nHandleType = type; |
|
m_nHandleSize = size; |
|
} |
|
|
|
void CRender::DrawArrow( Vector const &vStart, Vector const &vEnd ) |
|
{ |
|
Assert(0); |
|
} |
|
|
|
void CRender::DrawPolyLine( int nPoints, const Vector *Points ) |
|
{ |
|
// Draw the box bottom, top, and one corner edge. |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINE_LOOP, nPoints ); |
|
|
|
for (int i= 0; i<nPoints;i++ ) |
|
{ |
|
meshBuilder.Position3fv( &Points[i].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
} |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::DrawDisplacement( CCoreDispInfo *pMapDisp ) |
|
{ |
|
int numVerts = pMapDisp->GetSize(); |
|
int numIndices = pMapDisp->GetRenderIndexCount(); |
|
bool bWireFrame = m_eCurrentRenderMode == RENDER_MODE_WIREFRAME; |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_TRIANGLES, numVerts, numIndices ); |
|
|
|
Color color = m_DrawColor; |
|
|
|
CoreDispVert_t *pVert = pMapDisp->GetDispVertList(); |
|
for (int i = 0; i < numVerts; ++i ) |
|
{ |
|
if ( bWireFrame ) |
|
{ |
|
meshBuilder.Position3fv( pVert[i].m_Vert.Base() ); |
|
meshBuilder.Color4ubv( (byte*)&color ); |
|
meshBuilder.TexCoord2fv( 0, pVert[i].m_TexCoord.Base() ); |
|
meshBuilder.TexCoord2fv( 1, pVert[i].m_LuxelCoords[0].Base() ); |
|
meshBuilder.AdvanceVertex(); |
|
} |
|
else |
|
{ |
|
meshBuilder.Position3fv( pVert[i].m_Vert.Base() ); |
|
meshBuilder.Color4ub( color[0], color[1], color[2], 255 - ( unsigned char )( pVert[i].m_Alpha ) ); |
|
meshBuilder.Normal3fv( pVert[i].m_Normal.Base() ); |
|
meshBuilder.TangentS3fv( pVert[i].m_TangentS.Base() ); |
|
meshBuilder.TangentT3fv( pVert[i].m_TangentT.Base() ); |
|
meshBuilder.TexCoord2fv( 0, pVert[i].m_TexCoord.Base() ); |
|
meshBuilder.TexCoord2fv( 1, pVert[i].m_LuxelCoords[0].Base() ); |
|
meshBuilder.AdvanceVertex(); |
|
} |
|
} |
|
|
|
unsigned short *pIndex = pMapDisp->GetRenderIndexList(); |
|
for ( int i = 0; i < numIndices; ++i ) |
|
{ |
|
meshBuilder.Index( pIndex[i] ); |
|
meshBuilder.AdvanceIndex(); |
|
} |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
void CRender::DrawModel( DrawModelInfo_t* pInfo, matrix3x4_t *pBoneToWorld, const Vector &vOrigin, float fAlpha, bool bWireFrame ) |
|
{ |
|
UpdateStudioRenderConfig( true, bWireFrame ); |
|
|
|
g_pStudioRender->SetAlphaModulation( fAlpha ); |
|
|
|
Vector viewOrigin; |
|
GetCamera()->GetViewPoint( viewOrigin ); |
|
|
|
g_pStudioRender->SetEyeViewTarget( pInfo->m_pStudioHdr, pInfo->m_Body, viewOrigin ); |
|
|
|
g_pStudioRender->DrawModel( NULL, *pInfo, pBoneToWorld, NULL, NULL, vOrigin, STUDIORENDER_DRAW_ENTIRE_MODEL ); |
|
|
|
g_pStudioRender->SetAlphaModulation( 1.0f ); |
|
|
|
// force rendermode reset |
|
SetRenderMode( RENDER_MODE_CURRENT, true ); |
|
} |
|
|
|
void CRender::DrawCollisionModel( MDLHandle_t mdlHandle, const VMatrix &mViewMatrix ) |
|
{ |
|
vcollide_t *pCollide =g_pMDLCache->GetVCollide( mdlHandle ); |
|
|
|
if ( !pCollide || pCollide->solidCount <= 0 ) |
|
return; |
|
|
|
Vector *outVerts; |
|
int vertCount = g_pPhysicsCollision->CreateDebugMesh( pCollide->solids[0], &outVerts ); |
|
|
|
if ( vertCount ) |
|
{ |
|
PushRenderMode( RENDER_MODE_WIREFRAME ); |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_TRIANGLES, vertCount/3 ); |
|
|
|
for ( int j = 0; j < vertCount; j++ ) |
|
{ |
|
Vector out; |
|
mViewMatrix.V3Mul( outVerts[j], out ); |
|
meshBuilder.Position3fv( out.Base() ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.TexCoord2f( 0, 0, 0 ); |
|
meshBuilder.AdvanceVertex(); |
|
} |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
|
|
PopRenderMode(); |
|
} |
|
|
|
g_pPhysicsCollision->DestroyDebugMesh( vertCount, outVerts ); |
|
} |
|
|
|
void CRender::DrawSphere( const Vector &vCenter, int nRadius ) |
|
{ |
|
Assert(0); |
|
} |
|
|
|
void CRender::DrawBoxExt( const Vector &vCenter, float extend, bool bFill) |
|
{ |
|
Vector vExtent( extend, extend, extend ); |
|
Vector vMins = vCenter - vExtent; |
|
Vector vMax = vCenter + vExtent; |
|
|
|
DrawBox( vMins, vMax, bFill ); |
|
} |
|
|
|
void CRender::DrawHandles( int nPoints, const Vector *Points ) |
|
{ |
|
Assert(0); |
|
} |
|
|
|
void CRender::DrawBox( const Vector &vMins, const Vector &vMaxs, bool bFill) |
|
{ |
|
Vector points[8]; |
|
PointsFromBox( vMins, vMaxs, points ); |
|
|
|
if ( bFill ) |
|
{ |
|
Assert(0); |
|
} |
|
else |
|
{ |
|
// Draw the box bottom, top, and one corner edge. |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINE_STRIP, 9 ); |
|
|
|
meshBuilder.Position3fv( &points[0].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[1].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[3].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[2].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[6].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[7].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[5].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[4].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[0].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[2].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
|
|
// Draw the three missing edges. |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINES, 3 ); |
|
|
|
meshBuilder.Position3fv( &points[4].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[6].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[1].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[5].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[3].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3fv( &points[7].x ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
} |
|
|
|
void CRender::DrawPoint( const Vector &vPoint ) |
|
{ |
|
// HACK HACK, MATERIAL_POINTS doesnt work somehow |
|
|
|
meshBuilder.Begin( m_pMesh, MATERIAL_LINES, 1 ); |
|
|
|
meshBuilder.Position3f( vPoint.x, vPoint.y, vPoint.z ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3f( vPoint.x+1, vPoint.y+1, vPoint.z ); |
|
meshBuilder.Color4ubv( (byte*)&m_DrawColor ); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
m_pMesh->Draw(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Binds a texture for rendering. If the texture has never been bound |
|
// to this rendering context, it is uploaded to the driver. |
|
// Input : pTexture - Pointer to the texture object being bound. |
|
//----------------------------------------------------------------------------- |
|
void CRender::BindTexture(IEditorTexture *pTexture) |
|
{ |
|
// These textures must be CMaterials.... |
|
BindMaterial( pTexture->GetMaterial() ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Binds a material for rendering. If the material has never been bound |
|
// to this rendering context, it is uploaded to the driver. |
|
// Input : pMaterial - Pointer to the material object being bound. |
|
//----------------------------------------------------------------------------- |
|
void CRender::BindMaterial( IMaterial *pMaterial ) |
|
{ |
|
if ( m_pBoundMaterial != pMaterial ) |
|
{ |
|
m_pBoundMaterial = pMaterial; |
|
SetRenderMode( RENDER_MODE_CURRENT, true ); |
|
} |
|
} |
|
|
|
|
|
bool CRender::GetRequiredMaterial( const char *pName, IMaterial* &pMaterial ) |
|
{ |
|
pMaterial = NULL; |
|
IEditorTexture *pTex = g_Textures.FindActiveTexture( pName ); |
|
if ( pTex ) |
|
pMaterial = pTex->GetMaterial(); |
|
|
|
if ( pMaterial ) |
|
{ |
|
return true; |
|
} |
|
else |
|
{ |
|
char str[512]; |
|
Q_snprintf( str, sizeof( str ), "Missing material '%s'. Go to Tools | Options | Game Configurations and verify that your game directory is correct.", pName ); |
|
MessageBox( NULL, str, "FATAL ERROR", MB_OK ); |
|
return false; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : eRenderMode - |
|
//----------------------------------------------------------------------------- |
|
void CRender::SetRenderMode(EditorRenderMode_t eRenderMode, bool bForce) |
|
{ |
|
if (eRenderMode == RENDER_MODE_DEFAULT) |
|
{ |
|
eRenderMode = m_eDefaultRenderMode; |
|
} |
|
|
|
if ( eRenderMode == RENDER_MODE_CURRENT ) |
|
{ |
|
eRenderMode = m_eCurrentRenderMode; |
|
} |
|
|
|
if (m_eCurrentRenderMode == eRenderMode && !bForce) |
|
return; |
|
|
|
// Bind the appropriate material based on our mode |
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
switch(eRenderMode) |
|
{ |
|
case RENDER_MODE_DOTTED: |
|
m_pCurrentMaterial = m_pDotted[m_nDecalMode]; |
|
break; |
|
|
|
case RENDER_MODE_FLAT: |
|
// Ensures we get red even for decals |
|
m_pCurrentMaterial = m_pFlat[m_nDecalMode]; |
|
break; |
|
|
|
case RENDER_MODE_TRANSLUCENT_FLAT: |
|
m_pCurrentMaterial = m_pTranslucentFlat[m_nDecalMode]; |
|
break; |
|
|
|
case RENDER_MODE_FLAT_NOZ: |
|
// flat mode but not depth check |
|
m_pCurrentMaterial = m_pFlatNoZ[m_nDecalMode]; |
|
break; |
|
case RENDER_MODE_FLAT_NOCULL: |
|
// flat mode but not depth check |
|
m_pCurrentMaterial = m_pFlatNoCull[m_nDecalMode]; |
|
break; |
|
|
|
case RENDER_MODE_WIREFRAME: |
|
m_pCurrentMaterial = m_pWireframe[m_nDecalMode]; |
|
break; |
|
|
|
case RENDER_MODE_SMOOTHING_GROUP: |
|
m_pCurrentMaterial = m_pFlat[m_nDecalMode]; |
|
break; |
|
|
|
case RENDER_MODE_LIGHTMAP_GRID: |
|
m_pCurrentMaterial = m_pLightmapGrid[m_nDecalMode]; |
|
break; |
|
|
|
case RENDER_MODE_SELECTION_OVERLAY: |
|
case RENDER_MODE_INSTANCE_OVERLAY: |
|
// Ensures we get red even for decals |
|
m_pCurrentMaterial = m_pSelectionOverlay[m_nDecalMode]; |
|
break; |
|
|
|
case RENDER_MODE_TEXTURED: |
|
case RENDER_MODE_TEXTURED_SHADED: |
|
case RENDER_MODE_LIGHT_PREVIEW2: |
|
case RENDER_MODE_LIGHT_PREVIEW_RAYTRACED: |
|
if (m_pBoundMaterial) |
|
{ |
|
if( m_pBoundMaterial->GetPropertyFlag( MATERIAL_PROPERTY_NEEDS_BUMPED_LIGHTMAPS ) ) |
|
{ |
|
pRenderContext->BindLightmapPage( MATERIAL_SYSTEM_LIGHTMAP_PAGE_WHITE_BUMP ); |
|
} |
|
else |
|
{ |
|
pRenderContext->BindLightmapPage( MATERIAL_SYSTEM_LIGHTMAP_PAGE_WHITE ); |
|
} |
|
|
|
m_pCurrentMaterial = m_pBoundMaterial; |
|
} |
|
else |
|
{ |
|
m_pCurrentMaterial = m_pFlat[m_nDecalMode]; |
|
} |
|
break; |
|
} |
|
|
|
Assert( m_pCurrentMaterial != NULL ); |
|
|
|
pRenderContext->Bind( m_pCurrentMaterial ); |
|
|
|
pRenderContext->SetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING,0); |
|
if (eRenderMode==RENDER_MODE_TEXTURED_SHADED) |
|
pRenderContext->SetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING,1); |
|
|
|
if ( |
|
(eRenderMode==RENDER_MODE_LIGHT_PREVIEW2) || |
|
(eRenderMode==RENDER_MODE_LIGHT_PREVIEW_RAYTRACED) |
|
) |
|
pRenderContext->SetIntRenderingParameter(INT_RENDERPARM_ENABLE_FIXED_LIGHTING,2); |
|
|
|
m_pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_pCurrentMaterial ); |
|
|
|
Assert( m_pMesh ); |
|
|
|
m_eCurrentRenderMode = eRenderMode; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : eRenderMode - |
|
//----------------------------------------------------------------------------- |
|
void CRender::SetDefaultRenderMode(EditorRenderMode_t eRenderMode) |
|
{ |
|
Assert( eRenderMode != RENDER_MODE_DEFAULT ); |
|
m_eDefaultRenderMode = eRenderMode; |
|
} |
|
|
|
void CRender::PushRenderMode( EditorRenderMode_t eRenderMode ) |
|
{ |
|
m_RenderModeStack.Push( m_eCurrentRenderMode ); |
|
SetRenderMode( eRenderMode ); |
|
} |
|
|
|
void CRender::PopRenderMode() |
|
{ |
|
SetRenderMode( m_RenderModeStack.Top() ); |
|
m_RenderModeStack.Pop(); |
|
} |
|
|
|
#define CAMERA_RIGHT 0 |
|
#define CAMERA_UP 1 |
|
#define CAMERA_FORWARD 2 |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns a vector indicating the camera's forward axis. |
|
//----------------------------------------------------------------------------- |
|
void CRender::GetViewForward( Vector &ViewForward ) const |
|
{ |
|
ViewForward[ 0 ] = -m_CurrentMatrix[ CAMERA_FORWARD ][ 0 ]; |
|
ViewForward[ 1 ] = -m_CurrentMatrix[ CAMERA_FORWARD ][ 1 ]; |
|
ViewForward[ 2 ] = -m_CurrentMatrix[ CAMERA_FORWARD ][ 2 ]; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns a vector indicating the camera's up axis. |
|
//----------------------------------------------------------------------------- |
|
void CRender::GetViewUp(Vector& ViewUp) const |
|
{ |
|
ViewUp[ 0 ] = m_CurrentMatrix[ CAMERA_UP ][ 0 ]; |
|
ViewUp[ 1 ] = m_CurrentMatrix[ CAMERA_UP ][ 1 ]; |
|
ViewUp[ 2 ] = m_CurrentMatrix[ CAMERA_UP ][ 2 ]; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Returns a vector indicating the camera's right axis. |
|
//----------------------------------------------------------------------------- |
|
void CRender::GetViewRight(Vector& ViewRight) const |
|
{ |
|
ViewRight[ 0 ] = m_CurrentMatrix[ CAMERA_RIGHT ][ 0 ]; |
|
ViewRight[ 1 ] = m_CurrentMatrix[ CAMERA_RIGHT ][ 1 ]; |
|
ViewRight[ 2 ] = m_CurrentMatrix[ CAMERA_RIGHT ][ 2 ]; |
|
}
|
|
|