|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "uigeometry.h"
#include "materialsystem/imaterialsystem.h"
#include "mathlib/vector.h"
#include "gamegraphic.h"
#include "graphicgroup.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CGeometry::CGeometry() { m_Center.x = 0; m_Center.y = 0;
m_Scale.x = 1; m_Scale.y = 1;
m_Rotation = 0;
m_Color.r = 255; m_Color.g = 255; m_Color.b = 255; m_Color.a = 255;
m_TopColor.r = 255; m_TopColor.g = 255; m_TopColor.b = 255; m_TopColor.a = 255;
m_BottomColor.r = 255; m_BottomColor.g = 255; m_BottomColor.b = 255; m_BottomColor.a = 255;
m_bHorizontalGradient = false;
m_SheetSequenceNumber = 0; m_AnimationRate = 1;
m_Sublayer = -1; m_bMaintainAspectRatio = true; m_bVisible = true;
m_AnimStartTime = DMETIME_ZERO; m_bAnimate = false;
m_bDirtyExtents = false; }
//-----------------------------------------------------------------------------
// Rendering helper
// Calculate a matrix that will transform the points of the geometry, which are
// currently relative to the center, into screen coords.
//-----------------------------------------------------------------------------
void CGeometry::UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo, const CGraphicGroup *pGroup ) { Assert( pGroup ); if ( !pGroup->IsStageGroup() ) { if ( pGroup->GetVisible() == false ) { Assert( m_bVisible == pGroup->GetVisible() ); } } if ( !m_bVisible ) return;
// Update positions relative to the center, texture coords, and vertex colors
// If the group maintains aspect ratio it will already have handled this in its transform update.
Vector2D center; bool bUseMaintainedMatrix = m_bMaintainAspectRatio && !pGroup->MaintainAspectRatio(); if ( bUseMaintainedMatrix ) { // If this is the case we transform the center to screen coords first.
// Then take into account any size scaling in the scalemat
// Note this is not accounting for groups or rotations.
matrix3x4_t screenScalemat; SetScaleMatrix( stageRenderInfo.parentScale.x, stageRenderInfo.parentScale.y, 1, screenScalemat ); Vector centerVec( m_Center.x, m_Center.y, 0 ); Vector centerInScreen; VectorTransform( centerVec, screenScalemat, centerInScreen );
// Remove the uniform scale component from the center because it will come back in GetRenderTransform()
float scaleToUse; if ( stageRenderInfo.parentScale.x > stageRenderInfo.parentScale.y ) { scaleToUse = stageRenderInfo.parentScale.y; } else { scaleToUse = stageRenderInfo.parentScale.x; } SetScaleMatrix( 1/scaleToUse, 1/scaleToUse, 1, screenScalemat ); Vector tempCenter; VectorTransform( centerInScreen, screenScalemat, tempCenter ); center.x = tempCenter.x; center.y = tempCenter.y;
/* old version.
// If this is the case we transform the center to screen coords first.
// Then take into account any size scaling in the scalemat
matrix3x4_t screenScalemat; SetScaleMatrix( stageRenderInfo.parentScale.x, stageRenderInfo.parentScale.y, 1, screenScalemat ); Vector centerVec( m_Center.x, m_Center.y, 0 ); Vector centerInScreen; VectorTransform( centerVec, screenScalemat, centerInScreen ); center.x = centerInScreen.x; center.y = centerInScreen.y; */ } else { center = m_Center; }
matrix3x4_t transmat; Vector position( center.x, center.y, 0 ); SetIdentityMatrix( transmat ); PositionMatrix( position, transmat );
matrix3x4_t scalemat; SetScaleMatrix( m_Scale.x, m_Scale.y, 1, scalemat );
matrix3x4_t rotmat; Vector axis( 0, 0, 1 ); MatrixBuildRotationAboutAxis( axis, m_Rotation, rotmat );
matrix3x4_t temp; MatrixMultiply( rotmat, scalemat, temp ); matrix3x4_t rawToLocal; MatrixMultiply( transmat, temp, rawToLocal );
matrix3x4_t groupToScreen; // Use the matrix that doesn't contain any scale changes if we should
pGroup->GetRenderTransform( groupToScreen, bUseMaintainedMatrix ); MatrixMultiply( groupToScreen, rawToLocal, m_RenderToScreen );
if ( m_bDirtyExtents ) { CalculateExtentsMatrix( stageRenderInfo, pGroup ); } }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGeometry::UpdateRenderData( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex ) { if ( !m_bVisible ) return;
int i = renderGeometryLists[firstListIndex].AddToTail(); CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
// Now transform our array of positions into local graphic coord system.
int nCount = m_RelativePositions.Count(); for ( int i = 0; i < nCount; ++i ) { // Position
Vector relativePosition( m_RelativePositions[i].x, m_RelativePositions[i].y, 0 ); Vector screenpos; VectorTransform( relativePosition, m_RenderToScreen, screenpos ); renderGeometry.m_Positions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );; // TexCoord
renderGeometry.m_TextureCoords.AddToTail( m_TextureCoords[i] ); // Vertex Color
renderGeometry.m_VertexColors.AddToTail( m_VertexColors[i] ); }
// Triangles
nCount = m_Triangles.Count(); for ( int i = 0; i < nCount; ++i ) { renderGeometry.m_Triangles.AddToTail( m_Triangles[i] ); }
// Anim Info
renderGeometry.m_SheetSequenceNumber = m_SheetSequenceNumber; renderGeometry.m_AnimationRate = m_AnimationRate; renderGeometry.m_bAnimate = m_bAnimate; renderGeometry.m_AnimStartTime = m_AnimStartTime; renderGeometry.m_pImageAlias = NULL;
CalculateExtents(); }
//-----------------------------------------------------------------------------
// Calculate the rectangular extents of this graphic.
//-----------------------------------------------------------------------------
void CGeometry::CalculateExtentsMatrix( const StageRenderInfo_t &stageRenderInfo, const CGraphicGroup *pGroup ) { Assert( pGroup );
// Update positions relative to the center, texture coords, and vertex colors
// If the group maintains aspect ratio it will already have handled this in its transform update.
Vector2D center; bool bUseMaintainedMatrix = m_bMaintainAspectRatio && !pGroup->MaintainAspectRatio(); if ( bUseMaintainedMatrix ) { // If this is the case we transform the center to screen coords first.
// Then take into account any size scaling in the scalemat
matrix3x4_t screenScalemat; SetScaleMatrix( stageRenderInfo.parentScale.x, stageRenderInfo.parentScale.y, 1, screenScalemat ); Vector centerVec( m_Center.x, m_Center.y, 0 ); Vector centerInScreen; VectorTransform( centerVec, screenScalemat, centerInScreen ); center.x = centerInScreen.x; center.y = centerInScreen.y; } else { center = m_Center; }
matrix3x4_t transmat; Vector position( center.x, center.y, 0 ); SetIdentityMatrix( transmat ); PositionMatrix( position, transmat );
// TODO: account for scaling anims?
matrix3x4_t scalemat; SetScaleMatrix( m_Scale.x, m_Scale.y, 1, scalemat );
// Rotation is ignored.
matrix3x4_t rotmat; Vector axis( 0, 0, 1 ); MatrixBuildRotationAboutAxis( axis, 0, rotmat );
matrix3x4_t temp; MatrixMultiply( rotmat, scalemat, temp ); matrix3x4_t rawToLocal; MatrixMultiply( transmat, temp, rawToLocal );
matrix3x4_t groupToScreen; // Use the matrix that doesn't contain any scale changes if we should
pGroup->GetRenderTransform( groupToScreen, bUseMaintainedMatrix ); MatrixMultiply( groupToScreen, rawToLocal, m_ExtentsMatrix ); }
//-----------------------------------------------------------------------------
// Calculate the rectangular extents of this graphic.
//-----------------------------------------------------------------------------
void CGeometry::CalculateExtents() { if ( !m_bDirtyExtents ) return;
// Now transform our array of positions into local graphic coord system.
int nCount = m_RelativePositions.Count(); CUtlVector< Vector2D > screenPositions; for ( int i = 0; i < nCount; ++i ) { // Position
Vector relativePosition( m_RelativePositions[i].x, m_RelativePositions[i].y, 0 ); Vector screenpos; VectorTransform( relativePosition, m_ExtentsMatrix, screenpos ); screenPositions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );; }
// left most position is x.
m_Extents.m_TopLeft.x = INT_MAX; for ( int i = 0; i < screenPositions.Count(); ++i ) { if ( m_Extents.m_TopLeft.x > screenPositions[i].x ) m_Extents.m_TopLeft.x = screenPositions[i].x; }
// top most position is y.
m_Extents.m_TopLeft.y = INT_MAX; for ( int i = 0; i < screenPositions.Count(); ++i ) { if ( m_Extents.m_TopLeft.y > screenPositions[i].y ) m_Extents.m_TopLeft.y = screenPositions[i].y; }
// right most position is x
m_Extents.m_BottomRight.x = INT_MIN; for ( int i = 0; i < screenPositions.Count(); ++i ) { if ( m_Extents.m_BottomRight.x < screenPositions[i].x ) m_Extents.m_BottomRight.x = screenPositions[i].x; }
// bottom most position is y
m_Extents.m_BottomRight.y = INT_MIN; for ( int i = 0; i < screenPositions.Count(); ++i ) { if ( m_Extents.m_BottomRight.y < screenPositions[i].y ) m_Extents.m_BottomRight.y = screenPositions[i].y; }
m_bDirtyExtents = false; }
//-----------------------------------------------------------------------------
// Return the rectangular bounds of this object
//-----------------------------------------------------------------------------
void CGeometry::GetBounds( Rect_t &bounds ) { bounds.x = m_Extents.m_TopLeft.x; bounds.y = m_Extents.m_TopLeft.x; bounds.width = m_Extents.m_BottomRight.x - m_Extents.m_TopLeft.x; bounds.height = m_Extents.m_BottomRight.y - m_Extents.m_TopLeft.y; }
//-----------------------------------------------------------------------------
// Purpose: Set the vertex colors of the graphic using the base color and the gradient colors.
//-----------------------------------------------------------------------------
void CGeometry::SetResultantColor( color32 parentColor ) { SetResultantColor( true, parentColor ); SetResultantColor( false, parentColor ); }
//-----------------------------------------------------------------------------
// Purpose: Set the vertex colors of the graphic using the base color and the gradient colors.
//-----------------------------------------------------------------------------
void CGeometry::SetResultantColor( bool bTop, color32 parentColor ) { if ( bTop ) { color32 localColor; localColor.r = (int)( (float)m_TopColor.r * (float)(m_Color.r/255.0) ); localColor.g = (int)( (float)m_TopColor.g * (float)(m_Color.g/255.0) ); localColor.b = (int)( (float)m_TopColor.b * (float)(m_Color.b/255.0) ); localColor.a = (int)( (float)m_TopColor.a * (float)(m_Color.a/255.0) );
color32 resultantColor; resultantColor.r = (int)( (float)localColor.r * (float)(parentColor.r/255.0) ); resultantColor.g = (int)( (float)localColor.g * (float)(parentColor.g/255.0) ); resultantColor.b = (int)( (float)localColor.b * (float)(parentColor.b/255.0) ); resultantColor.a = (int)( (float)localColor.a * (float)(parentColor.a/255.0) );
SetTopVerticesColor( resultantColor ); } else { color32 localColor; localColor.r = (int)( (float)m_BottomColor.r * (float)(m_Color.r/255.0) ); localColor.g = (int)( (float)m_BottomColor.g * (float)(m_Color.g/255.0) ); localColor.b = (int)( (float)m_BottomColor.b * (float)(m_Color.b/255.0) ); localColor.a = (int)( (float)m_BottomColor.a * (float)(m_Color.a/255.0) );
color32 resultantColor; resultantColor.r = (int)( (float)localColor.r * (float)(parentColor.r/255.0) ); resultantColor.g = (int)( (float)localColor.g * (float)(parentColor.g/255.0) ); resultantColor.b = (int)( (float)localColor.b * (float)(parentColor.b/255.0) ); resultantColor.a = (int)( (float)localColor.a * (float)(parentColor.a/255.0) );
SetBottomVerticesColor( resultantColor ); } }
//-----------------------------------------------------------------------------
// Note corner colors will be stomped if the base graphic's color changes.
//-----------------------------------------------------------------------------
void CGeometry::SetTopVerticesColor( color32 c ) { if ( m_bHorizontalGradient ) { for ( int i = 0; i < m_VertexColors.Count(); i += 4 ) { m_VertexColors[i] = c; m_VertexColors[i+3] = c; } } else { for ( int i = 0; i < m_VertexColors.Count(); i += 4 ) { m_VertexColors[i] = c; m_VertexColors[i+1] = c; } } }
//-----------------------------------------------------------------------------
// Note corner colors will be stomped if the base graphic's color changes.
//-----------------------------------------------------------------------------
void CGeometry::SetBottomVerticesColor( color32 c ) { if ( m_bHorizontalGradient ) { for ( int i = 0; i < m_VertexColors.Count(); i += 4 ) { m_VertexColors[i+1] = c; m_VertexColors[i+2] = c; } } else { for ( int i = 0; i < m_VertexColors.Count(); i += 4 ) { m_VertexColors[i + 2] = c; m_VertexColors[i + 3] = c; } } }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGeometry::DrawExtents( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex, color32 extentLineColor ) { if ( !m_bVisible ) return;
float lineWidth = 2.0; // Time to invent some render data to draw this thing.
{ int i = renderGeometryLists[firstListIndex].AddToTail(); CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_TopLeft.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_TopLeft.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_TopLeft.y + lineWidth ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_TopLeft.y + lineWidth ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
// Triangles
CTriangle tri; tri.m_PointIndex[0] = 0; tri.m_PointIndex[1] = 1; tri.m_PointIndex[2] = 2; renderGeometry.m_Triangles.AddToTail( tri ); tri.m_PointIndex[0] = 0; tri.m_PointIndex[1] = 2; tri.m_PointIndex[2] = 3; renderGeometry.m_Triangles.AddToTail( tri ); // Anim Info
renderGeometry.m_SheetSequenceNumber = 0; renderGeometry.m_AnimationRate = m_AnimationRate; renderGeometry.m_bAnimate = false; renderGeometry.m_AnimStartTime = m_AnimStartTime; renderGeometry.m_pImageAlias = NULL; }
{ // Time to invent some render data to draw this thing.
int i = renderGeometryLists[firstListIndex].AddToTail(); CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x - lineWidth, m_Extents.m_TopLeft.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_TopLeft.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_BottomRight.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x - lineWidth, m_Extents.m_BottomRight.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
// Triangles
CTriangle tri; tri.m_PointIndex[0] = 0; tri.m_PointIndex[1] = 1; tri.m_PointIndex[2] = 2; renderGeometry.m_Triangles.AddToTail( tri ); tri.m_PointIndex[0] = 0; tri.m_PointIndex[1] = 2; tri.m_PointIndex[2] = 3; renderGeometry.m_Triangles.AddToTail( tri );
// Anim Info
renderGeometry.m_SheetSequenceNumber = 0; renderGeometry.m_AnimationRate = m_AnimationRate; renderGeometry.m_bAnimate = false; renderGeometry.m_AnimStartTime = m_AnimStartTime; renderGeometry.m_pImageAlias = NULL; }
{ int i = renderGeometryLists[firstListIndex].AddToTail(); CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_BottomRight.y - lineWidth ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_BottomRight.y - lineWidth ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_BottomRight.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_BottomRight.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
// Triangles
CTriangle tri; tri.m_PointIndex[0] = 0; tri.m_PointIndex[1] = 1; tri.m_PointIndex[2] = 2; renderGeometry.m_Triangles.AddToTail( tri ); tri.m_PointIndex[0] = 0; tri.m_PointIndex[1] = 2; tri.m_PointIndex[2] = 3; renderGeometry.m_Triangles.AddToTail( tri );
// Anim Info
renderGeometry.m_SheetSequenceNumber = 0; renderGeometry.m_AnimationRate = m_AnimationRate; renderGeometry.m_bAnimate = false; renderGeometry.m_AnimStartTime = m_AnimStartTime; renderGeometry.m_pImageAlias = NULL; } { // Time to invent some render data to draw this thing.
int i = renderGeometryLists[firstListIndex].AddToTail(); CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i]; renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_TopLeft.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x + lineWidth, m_Extents.m_TopLeft.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x + lineWidth, m_Extents.m_BottomRight.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_BottomRight.y ) ); renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) ); renderGeometry.m_VertexColors.AddToTail( extentLineColor );
// Triangles
CTriangle tri; tri.m_PointIndex[0] = 0; tri.m_PointIndex[1] = 1; tri.m_PointIndex[2] = 2; renderGeometry.m_Triangles.AddToTail( tri ); tri.m_PointIndex[0] = 0; tri.m_PointIndex[1] = 2; tri.m_PointIndex[2] = 3; renderGeometry.m_Triangles.AddToTail( tri );
// Anim Info
renderGeometry.m_SheetSequenceNumber = 0; renderGeometry.m_AnimationRate = m_AnimationRate; renderGeometry.m_bAnimate = false; renderGeometry.m_AnimStartTime = m_AnimStartTime; renderGeometry.m_pImageAlias = NULL; } }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CRenderGeometry::GetTriangleCount() { return m_Triangles.Count(); }
int CRenderGeometry::GetVertexCount() { return m_Positions.Count(); }
DmeTime_t CRenderGeometry::GetAnimStartTime() { return m_AnimStartTime; }
//-----------------------------------------------------------------------------
// Return true if the point x, y lies inside the triangle.
// Triangle points should be supplied in clockwise dir.
//-----------------------------------------------------------------------------
bool PointTriangleHitTest( Vector2D tringleVert0, Vector2D tringleVert1, Vector2D tringleVert2, Vector2D point ) { // Compute vectors
Vector2D v0 = tringleVert2 - tringleVert0; Vector2D v1 = tringleVert1 - tringleVert0; Vector2D v2 = point - tringleVert0;
// Compute dot products
float dot00 = v0.Dot( v0 ); float dot01 = v0.Dot( v1 ); float dot02 = v0.Dot( v2 ); float dot11 = v1.Dot( v1 ); float dot12 = v1.Dot( v2 );
// Compute barycentric coordinates
float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); float u = (dot11 * dot02 - dot01 * dot12) * invDenom; float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
// Check if point is in triangle
return ( u > 0 ) && ( v > 0 ) && ( u + v < 1 ); }
|