From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/public/scratchpad3d.cpp | 635 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 635 insertions(+) create mode 100644 mp/src/public/scratchpad3d.cpp (limited to 'mp/src/public/scratchpad3d.cpp') diff --git a/mp/src/public/scratchpad3d.cpp b/mp/src/public/scratchpad3d.cpp new file mode 100644 index 00000000..86ef77f6 --- /dev/null +++ b/mp/src/public/scratchpad3d.cpp @@ -0,0 +1,635 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include +#include "scratchpad3d.h" +#include "tier0/dbg.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifndef POSIX +// NOTE - linux doesn't need any of this code! + +extern "C" +{ + extern void __stdcall Sleep( unsigned long ms ); +}; + + +class CFileRead +{ +public: + CFileRead( IFileSystem* pFileSystem, FileHandle_t fp ) + { + m_pFileSystem = pFileSystem; + m_fp = fp; + m_Pos = 0; + } + + bool Read( void *pDest, int len ) + { + int count = m_pFileSystem->Read( pDest, len, m_fp ); + m_Pos += count; + return count == len; + } + + IFileSystem* m_pFileSystem; + FileHandle_t m_fp; + int m_Pos; +}; + + +// ------------------------------------------------------------------------ // +// CCommand_Point. +// ------------------------------------------------------------------------ // + +void CScratchPad3D::CCommand_Point::Read( CFileRead *pFile ) +{ + pFile->Read( &m_flPointSize, sizeof(m_flPointSize) ); + pFile->Read( &m_Vert, sizeof(m_Vert) ); +} + +void CScratchPad3D::CCommand_Point::Write( IFileSystem* pFileSystem, FileHandle_t fp ) +{ + pFileSystem->Write( &m_flPointSize, sizeof(m_flPointSize), fp ); + pFileSystem->Write( &m_Vert, sizeof(m_Vert), fp ); +} + + +// ------------------------------------------------------------------------ // +// CCommand_Line. +// ------------------------------------------------------------------------ // + +void CScratchPad3D::CCommand_Line::Read( CFileRead *pFile ) +{ + pFile->Read( m_Verts, sizeof(m_Verts) ); +} + +void CScratchPad3D::CCommand_Line::Write( IFileSystem* pFileSystem, FileHandle_t fp ) +{ + pFileSystem->Write( m_Verts, sizeof(m_Verts), fp ); +} + + +// ------------------------------------------------------------------------ // +// CCommand_Polygon. +// ------------------------------------------------------------------------ // + +void CScratchPad3D::CCommand_Polygon::Read( CFileRead *pFile ) +{ + int count; + pFile->Read( &count, sizeof(count) ); + m_Verts.RemoveAll(); + m_Verts.AddMultipleToTail( count ); + + if( count ) + pFile->Read( &m_Verts[0], sizeof(CSPVert)*count ); +} + +void CScratchPad3D::CCommand_Polygon::Write( IFileSystem* pFileSystem, FileHandle_t fp ) +{ + int count = m_Verts.Size(); + pFileSystem->Write( &count, sizeof(count), fp ); + + if( count ) + pFileSystem->Write( &m_Verts[0], sizeof(CSPVert)*count, fp ); +} + + +// ------------------------------------------------------------------------ // +// CCommand_Matrix. +// ------------------------------------------------------------------------ // + +void CScratchPad3D::CCommand_Matrix::Read( CFileRead *pFile ) +{ + pFile->Read( &m_mMatrix, sizeof(m_mMatrix) ); +} + +void CScratchPad3D::CCommand_Matrix::Write( IFileSystem* pFileSystem, FileHandle_t fp ) +{ + pFileSystem->Write( &m_mMatrix, sizeof(m_mMatrix), fp ); +} + + +// ------------------------------------------------------------------------ // +// CCommand_RenderState. +// ------------------------------------------------------------------------ // + +void CScratchPad3D::CCommand_RenderState::Read( CFileRead *pFile ) +{ + pFile->Read( &m_State, sizeof(m_State) ); + pFile->Read( &m_Val, sizeof(m_Val) ); +} + +void CScratchPad3D::CCommand_RenderState::Write( IFileSystem* pFileSystem, FileHandle_t fp ) +{ + pFileSystem->Write( &m_State, sizeof(m_State), fp ); + pFileSystem->Write( &m_Val, sizeof(m_Val), fp ); +} + + +// ------------------------------------------------------------------------ // +// CCommand_Text. +// ------------------------------------------------------------------------ // + +void CScratchPad3D::CCommand_Text::Read( CFileRead *pFile ) +{ + int strLen; + pFile->Read( &strLen, sizeof( strLen ) ); + m_String.SetSize( strLen ); + pFile->Read( m_String.Base(), strLen ); + + pFile->Read( &m_TextParams, sizeof( m_TextParams ) ); +} + + +void CScratchPad3D::CCommand_Text::Write( IFileSystem* pFileSystem, FileHandle_t fp ) +{ + int strLen = m_String.Count(); + pFileSystem->Write( &strLen, sizeof( strLen ), fp ); + pFileSystem->Write( m_String.Base(), strLen, fp ); + + pFileSystem->Write( &m_TextParams, sizeof( m_TextParams ), fp ); +} + + +// ------------------------------------------------------------------------ // +// CScratchPad3D internals. +// ------------------------------------------------------------------------ // + +CScratchPad3D::CScratchPad3D( char const *pFilename, IFileSystem* pFileSystem, bool bAutoClear ) +{ + m_pFileSystem = pFileSystem; + m_pFilename = pFilename; + m_bAutoFlush = true; + + if( bAutoClear ) + Clear(); // Clear whatever is in the file.. +} + +void CScratchPad3D::AutoFlush() +{ + if( m_bAutoFlush ) + Flush(); +} + +void CScratchPad3D::DrawRectGeneric( int iPlane, int otherDim1, int otherDim2, float planeDist, const Vector2D &vMin, const Vector2D &vMax, const CSPColor &vColor ) +{ + Vector verts[4]; + + verts[0][iPlane] = verts[1][iPlane] = verts[2][iPlane] = verts[3][iPlane] = planeDist; + + verts[0][otherDim1] = vMin.x; + verts[0][otherDim2] = vMin.y; + + verts[1][otherDim1] = vMin.x; + verts[1][otherDim2] = vMax.y; + + verts[2][otherDim1] = vMax.x; + verts[2][otherDim2] = vMax.y; + + verts[3][otherDim1] = vMax.x; + verts[3][otherDim2] = vMin.y; + + DrawPolygon( CSPVertList(verts, 4, vColor) ); +} + +void CScratchPad3D::DeleteCommands() +{ + for( int i=0; i < m_Commands.Size(); i++ ) + delete m_Commands[i]; + + m_Commands.RemoveAll(); +} + +bool CScratchPad3D::LoadCommandsFromFile( ) +{ + DeleteCommands(); + + FileHandle_t fp = m_pFileSystem->Open( m_pFilename, "rb" ); + if( !fp ) + return false; + + long fileEndPos = m_pFileSystem->Size( fp ); + + CFileRead fileRead( m_pFileSystem, fp ); + while( fileRead.m_Pos != fileEndPos ) + { + unsigned char iCommand; + fileRead.Read( &iCommand, sizeof(iCommand) ); + + CBaseCommand *pCmd = NULL; + if( iCommand == COMMAND_POINT ) + pCmd = new CCommand_Point; + else if( iCommand == COMMAND_LINE ) + pCmd = new CCommand_Line; + else if( iCommand == COMMAND_POLYGON ) + pCmd = new CCommand_Polygon; + else if( iCommand == COMMAND_MATRIX ) + pCmd = new CCommand_Matrix; + else if( iCommand == COMMAND_RENDERSTATE ) + pCmd = new CCommand_RenderState; + else if ( iCommand == COMMAND_TEXT ) + pCmd = new CCommand_Text; + + if( !pCmd ) + { + Assert( !"LoadCommandsFromFile: invalid file" ); + m_pFileSystem->Close( fp ); + return false; + } + + pCmd->Read( &fileRead ); + m_Commands.AddToTail( pCmd ); + } + + m_pFileSystem->Close( fp ); + return true; +} + + +// ------------------------------------------------------------------------ // +// CScratchPad3D's IScratchPad3D implementation. +// ------------------------------------------------------------------------ // + +void CScratchPad3D::Release() +{ + Flush(); + delete this; +} + +void CScratchPad3D::SetMapping( + const Vector &vInputMin, + const Vector &vInputMax, + const Vector &vOutputMin, + const Vector &vOutputMax ) +{ + CCommand_Matrix *cmd = new CCommand_Matrix; + m_Commands.AddToTail( cmd ); + + Vector vDivisor(1,1,1); + for( int i=0; i < 3; i++ ) + vDivisor[i] = fabs(vInputMax[i] - vInputMin[i]) < 0.0001f ? 0.001f : (vInputMax[i] - vInputMin[i]); + + Vector vScale = (vOutputMax - vOutputMin) / vDivisor; + Vector vShift = -vInputMin * vScale + vOutputMin; + + cmd->m_mMatrix.Init( + vScale.x, 0, 0, vShift.x, + 0, vScale.y, 0, vShift.y, + 0, 0, vScale.z, vShift.z, + 0, 0, 0, 1 ); + + + AutoFlush(); +} + +bool CScratchPad3D::GetAutoFlush() +{ + return m_bAutoFlush; +} + +void CScratchPad3D::SetAutoFlush( bool bAutoFlush ) +{ + m_bAutoFlush = bAutoFlush; + if( m_bAutoFlush ) + Flush(); +} + +void CScratchPad3D::DrawPoint( CSPVert const &v, float flPointSize ) +{ + CCommand_Point *cmd = new CCommand_Point; + m_Commands.AddToTail( cmd ); + + cmd->m_Vert = v; + cmd->m_flPointSize = flPointSize; + + AutoFlush(); +} + +void CScratchPad3D::DrawLine( CSPVert const &v1, CSPVert const &v2 ) +{ + CCommand_Line *cmd = new CCommand_Line; + m_Commands.AddToTail( cmd ); + + cmd->m_Verts[0] = v1; + cmd->m_Verts[1] = v2; + + AutoFlush(); +} + +void CScratchPad3D::DrawPolygon( CSPVertList const &verts ) +{ + CCommand_Polygon *cmd = new CCommand_Polygon; + m_Commands.AddToTail( cmd ); + + cmd->m_Verts.AddVectorToTail( verts.m_Verts ); + + AutoFlush(); +} + +void CScratchPad3D::DrawRectYZ( float xPos, const Vector2D &vMin, const Vector2D &vMax, const CSPColor &vColor ) +{ + DrawRectGeneric( 0, 1, 2, xPos, vMin, vMax, vColor ); +} + +void CScratchPad3D::DrawRectXZ( float yPos, const Vector2D &vMin, const Vector2D &vMax, const CSPColor &vColor ) +{ + DrawRectGeneric( 1, 0, 2, yPos, vMin, vMax, vColor ); +} + +void CScratchPad3D::DrawRectXY( float zPos, const Vector2D &vMin, const Vector2D &vMax, const CSPColor &vColor ) +{ + DrawRectGeneric( 2, 0, 1, zPos, vMin, vMax, vColor ); +} + +void CScratchPad3D::SetRenderState( RenderState state, unsigned long val ) +{ + CCommand_RenderState *cmd = new CCommand_RenderState; + m_Commands.AddToTail( cmd ); + + cmd->m_State = (unsigned long)state; + cmd->m_Val = val; +} + +void CScratchPad3D::DrawWireframeBox( const Vector &vMin, const Vector &vMax, const Vector &vColor ) +{ + // Bottom 4. + DrawLine( + CSPVert(Vector(vMin.x, vMin.y, vMin.z), vColor), + CSPVert(Vector(vMax.x, vMin.y, vMin.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMin.x, vMin.y, vMin.z), vColor), + CSPVert(Vector(vMin.x, vMax.y, vMin.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMax.x, vMin.y, vMin.z), vColor), + CSPVert(Vector(vMax.x, vMax.y, vMin.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMax.x, vMax.y, vMin.z), vColor), + CSPVert(Vector(vMin.x, vMax.y, vMin.z), vColor) ); + + // Top 4. + DrawLine( + CSPVert(Vector(vMin.x, vMin.y, vMax.z), vColor), + CSPVert(Vector(vMax.x, vMin.y, vMax.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMin.x, vMin.y, vMax.z), vColor), + CSPVert(Vector(vMin.x, vMax.y, vMax.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMax.x, vMin.y, vMax.z), vColor), + CSPVert(Vector(vMax.x, vMax.y, vMax.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMax.x, vMax.y, vMax.z), vColor), + CSPVert(Vector(vMin.x, vMax.y, vMax.z), vColor) ); + + // Connecting 4. + DrawLine( + CSPVert(Vector(vMin.x, vMin.y, vMin.z), vColor), + CSPVert(Vector(vMin.x, vMin.y, vMax.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMin.x, vMax.y, vMin.z), vColor), + CSPVert(Vector(vMin.x, vMax.y, vMax.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMax.x, vMax.y, vMin.z), vColor), + CSPVert(Vector(vMax.x, vMax.y, vMax.z), vColor) ); + + DrawLine( + CSPVert(Vector(vMax.x, vMin.y, vMin.z), vColor), + CSPVert(Vector(vMax.x, vMin.y, vMax.z), vColor) ); +} + + +void CScratchPad3D::DrawText( const char *pStr, const CTextParams ¶ms ) +{ + CCommand_Text *cmd = new CCommand_Text; + m_Commands.AddToTail( cmd ); + + cmd->m_String.CopyArray( pStr, strlen( pStr ) + 1 ); + cmd->m_TextParams = params; + + AutoFlush(); +} + + +void CScratchPad3D::Clear() +{ + FileHandle_t fp; + + while( ( fp = m_pFileSystem->Open(m_pFilename, "wb") ) == NULL ) + { +#ifdef _WIN32 + Sleep( 5 ); +#elif POSIX + usleep( 5 ); +#endif + } + + m_pFileSystem->Close( fp ); + + DeleteCommands(); +} + + +void CScratchPad3D::Flush() +{ + FileHandle_t fp; + + while( ( fp = m_pFileSystem->Open(m_pFilename, "ab+") ) == NULL ) + { +#ifdef _WIN32 + Sleep( 5 ); +#elif POSIX + usleep( 5 ); +#endif + } + + // Append the new commands to the file. + for( int i=0; i < m_Commands.Size(); i++ ) + { + m_pFileSystem->Write( &m_Commands[i]->m_iCommand, sizeof(m_Commands[i]->m_iCommand), fp ); + m_Commands[i]->Write( m_pFileSystem, fp ); + } + + m_pFileSystem->Close( fp ); + + DeleteCommands(); +} + +void CScratchPad3D::DrawImageBW( + unsigned char const *pData, + int width, + int height, + int pitchInBytes, + bool bOutlinePixels, + bool bOutlineImage, + Vector *vCorners ) +{ + SPRGBA *pRGBA = new SPRGBA[width*height]; + for( int y=0; y < height; y++ ) + { + SPRGBA *pDest = &pRGBA[ y * width ]; + unsigned char const *pSrc = &pData[ y * pitchInBytes ]; + for( int x=0; x < width; x++ ) + { + pDest->r = pDest->g = pDest->b = *pSrc; + ++pSrc; + ++pDest; + } + } + + DrawImageRGBA( pRGBA, width, height, width*sizeof(SPRGBA), bOutlinePixels, bOutlineImage, vCorners ); + delete [] pRGBA; +} + + +void CScratchPad3D::DrawPolygonsForPixels( + SPRGBA *pData, + int width, + int height, + int pitchInBytes, + Vector *vCorners ) +{ + // Scan top-down. + Vector vCurLeft = vCorners[1]; + Vector vCurRight = vCorners[2]; + + Vector vLeftInc = (vCorners[0] - vCorners[1]) / height; + Vector vRightInc = (vCorners[3] - vCorners[2]) / height; + + Vector vNextLeft = vCurLeft + vLeftInc; + Vector vNextRight = vCurRight + vRightInc; + + Vector vPolyBox[4]; + Vector &vTopLeft = vPolyBox[0]; + Vector &vTopRight = vPolyBox[1]; + Vector &vBottomRight = vPolyBox[2]; + Vector &vBottomLeft = vPolyBox[3]; + + for( int y=0; y < height; y++ ) + { + vTopLeft = vCurLeft; + vBottomLeft = vNextLeft; + + Vector vTopXInc = (vCurRight - vCurLeft) / width; + Vector vBottomXInc = (vNextRight - vNextLeft) / width; + + vTopRight = vTopLeft + vTopXInc; + vBottomRight = vBottomLeft + vBottomXInc; + + SPRGBA *pSrc = &pData[ y * (pitchInBytes/sizeof(SPRGBA)) ]; + for( int x=0; x < width; x++ ) + { + if ( pData ) + DrawPolygon( CSPVertList( vPolyBox, 4, Vector(pSrc->r/255.1f, pSrc->g/255.1f, pSrc->b/255.1f) ) ); + else + DrawPolygon( CSPVertList( vPolyBox, 4, Vector(1,1,1) ) ); + + ++pSrc; + vTopLeft += vTopXInc; + vTopRight += vTopXInc; + vBottomLeft += vBottomXInc; + vBottomRight += vBottomXInc; + } + + vCurLeft += vLeftInc; + vNextLeft += vLeftInc; + vCurRight += vRightInc; + vNextRight += vRightInc; + } +} + + +void CScratchPad3D::DrawImageRGBA( + SPRGBA *pData, + int width, + int height, + int pitchInBytes, + bool bOutlinePixels, + bool bOutlineImage, + Vector *vCorners ) +{ + Assert( pitchInBytes % sizeof(SPRGBA) == 0 ); + + Vector vDefaultCorners[4]; + if ( !vCorners ) + { + vCorners = vDefaultCorners; + vDefaultCorners[0].Init( -100, -100 ); + vDefaultCorners[1].Init( -100, 100 ); + vDefaultCorners[2].Init( 100, 100 ); + vDefaultCorners[3].Init( 100, -100 ); + } + + // Don't auto-flush while drawing all these primitives. + bool bOldAutoFlush = m_bAutoFlush; + m_bAutoFlush = false; + + // Draw solids. + SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Solid ); + DrawPolygonsForPixels( pData, width, height, pitchInBytes, vCorners ); + + // Draw wireframe. + if ( bOutlinePixels ) + { + SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Wireframe ); + DrawPolygonsForPixels( NULL, width, height, pitchInBytes, vCorners ); + } + + // Draw an outline around the whole image. + if ( bOutlineImage ) + { + SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Wireframe ); + DrawPolygon( CSPVertList( vCorners, 4 ) ); + } + + // Restore the old auto-flush state. + m_bAutoFlush = bOldAutoFlush; + AutoFlush(); +} + + +// ------------------------------------------------------------------------ // +// Global functions. +// ------------------------------------------------------------------------ // +IFileSystem* ScratchPad3D_SetupFileSystem() +{ + // Get a filesystem interface. + CSysModule *pModule = Sys_LoadModule( "filesystem_stdio" ); + if( !pModule ) + return NULL; + + CreateInterfaceFn fn = Sys_GetFactory( pModule ); + IFileSystem *pFileSystem; + if( !fn || (pFileSystem = (IFileSystem *)fn( FILESYSTEM_INTERFACE_VERSION, NULL )) == NULL ) + { + Sys_UnloadModule( pModule ); + return NULL; + } + + return pFileSystem; +} + +IScratchPad3D* ScratchPad3D_Create( char const *pFilename ) +{ + IFileSystem *pFileSystem = ScratchPad3D_SetupFileSystem(); + if( !pFileSystem ) + return NULL; + + CScratchPad3D *pRet = new CScratchPad3D( pFilename, pFileSystem, true ); + return pRet; +} +#endif // POSIX + -- cgit v1.2.3