diff options
Diffstat (limited to 'utils/scratchpad3dviewer')
| -rw-r--r-- | utils/scratchpad3dviewer/d3dapp.cpp | 560 | ||||
| -rw-r--r-- | utils/scratchpad3dviewer/d3dapp.h | 75 | ||||
| -rw-r--r-- | utils/scratchpad3dviewer/resource.h | 34 | ||||
| -rw-r--r-- | utils/scratchpad3dviewer/scratchpad3dviewer.cpp | 928 | ||||
| -rw-r--r-- | utils/scratchpad3dviewer/scratchpad3dviewer.vpc | 55 | ||||
| -rw-r--r-- | utils/scratchpad3dviewer/stdafx.cpp | 15 | ||||
| -rw-r--r-- | utils/scratchpad3dviewer/stdafx.h | 45 |
7 files changed, 1712 insertions, 0 deletions
diff --git a/utils/scratchpad3dviewer/d3dapp.cpp b/utils/scratchpad3dviewer/d3dapp.cpp new file mode 100644 index 0000000..6177144 --- /dev/null +++ b/utils/scratchpad3dviewer/d3dapp.cpp @@ -0,0 +1,560 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// TerrainBlend.cpp : Defines the entry point for the application. +// + +#include "stdafx.h" +#include "resource.h" +#include "mathlib/mathlib.h" +#include "tier0/dbg.h" +#include "tier0/icommandline.h" +#include "tier1/strtools.h" + + +#define MAX_LOADSTRING 100 + +// Global Variables: +HINSTANCE hInst; // current instance +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text +HWND g_hWnd; + +// Foward declarations of functions included in this code module: +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); + +int g_nCapture = 0; +bool g_bFocus = false; + +int g_ScreenWidth, g_ScreenHeight; + +D3DPRESENT_PARAMETERS d3dpp; + + +IDirect3D8 *g_pDirect3D; +IDirect3DDevice8 *g_pDevice; + + +POINT GetWindowCenter() +{ + RECT rc; + GetWindowRect(g_hWnd, &rc); + POINT ret; + ret.x = (rc.left + rc.right) / 2; + ret.y = (rc.top + rc.bottom) / 2; + return ret; +} + + +void CallAppRender( bool bInvalidRect ) +{ + static DWORD lastTime = 0; + static POINT lastMousePos = {0xFFFF, 0xFFFF}; + + // Sample time and mouse position and tell the app to render. + DWORD curTime = GetTickCount(); + float frametime = (curTime - lastTime) / 1000.0f; + if( frametime > 0.1f ) + frametime = 0.1f; + + lastTime = curTime; + + // Get the cursor delta. + POINT curMousePos; + GetCursorPos(&curMousePos); + + int deltaX, deltaY; + + if( lastMousePos.x == 0xFFFF ) + { + deltaX = deltaY = 0; + } + else + { + deltaX = curMousePos.x - lastMousePos.x; + deltaY = curMousePos.y - lastMousePos.y; + } + + // Recenter the cursor. + if( g_nCapture ) + { + lastMousePos = GetWindowCenter(); + SetCursorPos( lastMousePos.x, lastMousePos.y ); + } + else + { + lastMousePos = curMousePos; + } + + AppRender( frametime, (float)deltaX, (float)deltaY, bInvalidRect ); +} + + +SpewRetval_t D3DAppSpewFunc( SpewType_t spewType, char const *pMsg ) +{ + switch (spewType) + { + case SPEW_ERROR: + MessageBox(NULL, pMsg, "FATAL ERROR", MB_OK); + return SPEW_ABORT; + + default: + OutputDebugString(pMsg); +#ifdef _DEBUG + return spewType == SPEW_ASSERT ? SPEW_DEBUGGER : SPEW_CONTINUE; +#else + return SPEW_CONTINUE; +#endif + } +} + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + CommandLine()->CreateCmdLine( Plat_GetCommandLine() ); + + // TODO: Place code here. + SpewOutputFunc( D3DAppSpewFunc ); + MathLib_Init( true, true, true, 2.2f, 2.2f, 0.0f, 2.0f ); + MSG msg; + HACCEL hAccelTable; + + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + strcpy( szWindowClass, "d3dapp" ); + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) + { + return FALSE; + } + + hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TERRAINBLEND); + + + InvalidateRect( g_hWnd, NULL, FALSE ); + + // Main message loop: + while(1) + { + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if(msg.message == WM_QUIT) + break; + + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if(msg.message == WM_QUIT) + break; + + CallAppRender( false ); + } + + AppExit(); + + return msg.wParam; +} + + + +// +// FUNCTION: MyRegisterClass() +// +// PURPOSE: Registers the window class. +// +// COMMENTS: +// +// This function and its usage is only necessary if you want this code +// to be compatible with Win32 systems prior to the 'RegisterClassEx' +// function that was added to Windows 95. It is important to call this function +// so that the application will get 'well formed' small icons associated +// with it. +// +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TERRAINBLEND); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); + + return RegisterClassEx(&wcex); +} + + +void ShutdownD3D() +{ + if( g_pDevice ) + { + g_pDevice->Release(); + g_pDevice = NULL; + } + + if( g_pDirect3D ) + { + g_pDirect3D->Release(); + g_pDirect3D = NULL; + } +} + + +void InitD3D() +{ + ShutdownD3D(); + + + RECT rcClient; + GetClientRect( g_hWnd, &rcClient ); + + g_ScreenWidth = rcClient.right - rcClient.left; + g_ScreenHeight = rcClient.bottom - rcClient.top; + + // Initialize D3D. + g_pDirect3D = Direct3DCreate8( D3D_SDK_VERSION ); + + // Get the current desktop display mode, so we can set up a back + // buffer of the same format + D3DDISPLAYMODE d3ddm; + g_pDirect3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ); + + + // Set up the structure used to create the D3DDevice + ZeroMemory( &d3dpp, sizeof(d3dpp) ); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.EnableAutoDepthStencil = TRUE; + d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; + d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; + + HRESULT hr = g_pDirect3D->CreateDevice( + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + g_hWnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, + &d3dpp, + &g_pDevice); + if( FAILED(hr) ) + { + Sys_Error( "CreateDevice failed (%s)", DXGetErrorString8(hr) ); + } + + g_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); + g_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); +} + +void DoResize() +{ + AppPreResize(); + InitD3D(); + AppPostResize(); + CallAppRender( true ); +} + +// +// FUNCTION: InitInstance(HANDLE, int) +// +// PURPOSE: Saves instance handle and creates main window +// +// COMMENTS: +// +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + hInst = hInstance; // Store instance handle in our global variable + + int x = Sys_FindArgInt( "-x", 0 ); + int y = Sys_FindArgInt( "-y", 0 ); + int w = Sys_FindArgInt( "-width", CW_USEDEFAULT ); + int h = Sys_FindArgInt( "-height", CW_USEDEFAULT ); + + DWORD dwFlags = WS_OVERLAPPEDWINDOW; + + // Get the 'work area' so we don't overlap the taskbar on the top or left. + RECT rcWorkArea; + SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWorkArea, 0 ); + + // If they don't specify anything, maximize the window. + if( x == 0 && y == 0 && w == CW_USEDEFAULT && h == CW_USEDEFAULT ) + { + x = rcWorkArea.left; + y = rcWorkArea.top; + w = rcWorkArea.right - rcWorkArea.left; + h = rcWorkArea.bottom - rcWorkArea.top; + dwFlags |= WS_MAXIMIZE; + } + else + { + x += rcWorkArea.left; + y += rcWorkArea.top; + } + + + g_hWnd = CreateWindow( + szWindowClass, + szTitle, + dwFlags, // window style + x, // x + y, // y + w, // width + h, // height + NULL, + NULL, + hInstance, + NULL); + + if (!g_hWnd) + { + return FALSE; + } + + ShowWindow(g_hWnd, nCmdShow); + UpdateWindow(g_hWnd); + + + InitD3D(); + AppInit(); + + // Reinitialize D3D. For some reason, D3D point primitives are way too large + // unless we do this. + DoResize(); + + return TRUE; +} + + +// +// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes messages for the main window. +// +// WM_COMMAND - process the application menu +// WM_PAINT - Paint the main window +// WM_DESTROY - post a quit message and return +// +// +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint( hWnd, &ps ); + EndPaint( hWnd, &ps ); + + if( g_pDevice ) + CallAppRender( true ); + } + break; + + case WM_KEYDOWN: + { + AppKey( (int)wParam, lParam&0xFFFF ); + } + break; + + case WM_KEYUP: + { + AppKey( (int)wParam, 0 ); + } + break; + + case WM_CHAR: + { + AppChar( (int)wParam ); + } + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + case WM_LBUTTONDOWN: + { + ShowCursor( FALSE ); + SetCapture( g_hWnd ); + g_nCapture++; + } + break; + + case WM_LBUTTONUP: + { + ShowCursor( TRUE ); + ReleaseCapture( ); + g_nCapture--; + } + break; + + case WM_RBUTTONDOWN: + { + ShowCursor( FALSE ); + SetCapture( g_hWnd ); + g_nCapture++; + } + break; + + case WM_RBUTTONUP: + { + ShowCursor( TRUE ); + ReleaseCapture( ); + g_nCapture--; + } + break; + + case WM_SIZE: + { + if( g_pDevice ) + DoResize(); + } + break; + + case WM_SETFOCUS: + { + g_bFocus = true; + } + break; + + case WM_KILLFOCUS: + { + g_bFocus = false; + } + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + + +bool Sys_Error(const char *pMsg, ...) +{ + char msg[4096]; + va_list marker; + + va_start( marker, pMsg ); + V_vsprintf_safe( msg, pMsg, marker ); + va_end( marker ); + + MessageBox( NULL, msg, "Error!", MB_OK ); + exit(1); + return true; +} + + +void Sys_Quit() +{ + PostQuitMessage( 0 ); +} + + +void Sys_SetWindowText( char const *pMsg, ... ) +{ + va_list marker; + char msg[4096]; + + va_start(marker, pMsg); + V_vsprintf_safe(msg, pMsg, marker); + va_end(marker); + + SetWindowText( g_hWnd, msg ); +} + + +bool Sys_GetKeyState( int key ) +{ + int keyTranslations[][2] = + { + {APPKEY_LBUTTON, VK_LBUTTON}, + {APPKEY_RBUTTON, VK_RBUTTON}, + {APPKEY_SPACE, VK_SPACE} + }; + int nKeyTranslations = sizeof(keyTranslations) / sizeof(keyTranslations[0]); + + for( int i=0; i < nKeyTranslations; i++ ) + { + if( key == keyTranslations[i][0] ) + { + key = keyTranslations[i][1]; + break; + } + } + + return !!( GetAsyncKeyState( key ) & 0x8000 ); +} + + +void Sys_Sleep( int ms ) +{ + Sleep( (DWORD)ms ); +} + + +bool Sys_HasFocus() +{ + return g_bFocus; +} + + +char const* Sys_FindArg( char const *pArg, char const *pDefault ) +{ + for( int i=0; i < __argc; i++ ) + { + if( stricmp( __argv[i], pArg ) == 0 ) + return (i+1) < __argc ? __argv[i+1] : ""; + } + + return pDefault; +} + + +int Sys_FindArgInt( char const *pArg, int defaultVal ) +{ + char const *pVal = Sys_FindArg( pArg, NULL ); + if( pVal ) + return atoi( pVal ); + else + return defaultVal; +} + + +int Sys_ScreenWidth() +{ + return g_ScreenWidth; +} + + +int Sys_ScreenHeight() +{ + return g_ScreenHeight; +} + + diff --git a/utils/scratchpad3dviewer/d3dapp.h b/utils/scratchpad3dviewer/d3dapp.h new file mode 100644 index 0000000..4e68db0 --- /dev/null +++ b/utils/scratchpad3dviewer/d3dapp.h @@ -0,0 +1,75 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef D3DAPP_H +#define D3DAPP_H +#ifdef _WIN32 +#pragma once +#endif + + +#include <d3d8.h> + + +// Globals for the app to access. These are valid whenever the app is called. +extern IDirect3D8 *g_pDirect3D; +extern IDirect3DDevice8 *g_pDevice; + + +// Special keys. +#define APPKEY_LBUTTON -1 +#define APPKEY_RBUTTON -2 +#define APPKEY_SPACE -3 + + +// ------------------------------------------------------------------------------------ // +// Functions for the app to provide. +// ------------------------------------------------------------------------------------ // +void AppInit(); + +// Called to update or render the view as often as possible. If bInvalidRect is true, +// then you should always render, so the window's contents are valid. +void AppRender( float frametime, float mouseDeltaX, float mouseDeltaY, bool bInvalidRect ); + +// Release any D3D objects you have here - a resize will happen. +void AppPreResize(); +void AppPostResize(); + +void AppExit( ); +void AppKey( int key, int down ); +void AppChar( int key ); + + + +// ------------------------------------------------------------------------------------ // +// Functions the app can call. +// ------------------------------------------------------------------------------------ // + +// Show an error dialog and quit. +bool Sys_Error(const char *pMsg, ...); + +// Shutdown the app. AppExit() will be called. +void Sys_Quit(); + +void Sys_SetWindowText( char const *pMsg, ... ); + +// Key can be an ASCII key code or an APPKEY_ define. +bool Sys_GetKeyState( int key ); + +void Sys_Sleep( int ms ); + +// Does the app have the focus? +bool Sys_HasFocus(); + +char const* Sys_FindArg( char const *pArg, char const *pDefault=NULL ); +int Sys_FindArgInt( char const *pArg, int defaultVal = -1 ); + +int Sys_ScreenWidth(); +int Sys_ScreenHeight(); + + +#endif // D3DAPP_H diff --git a/utils/scratchpad3dviewer/resource.h b/utils/scratchpad3dviewer/resource.h new file mode 100644 index 0000000..f5a23a6 --- /dev/null +++ b/utils/scratchpad3dviewer/resource.h @@ -0,0 +1,34 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by TERRAINBLEND.RC +// +#define IDR_MAINFRAME 128 +#define IDD_TERRAINBLEND_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDS_APP_TITLE 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDS_HELLO 106 +#define IDI_TERRAINBLEND 107 +#define IDI_SMALL 108 +#define IDC_TERRAINBLEND 109 +#define IDC_MYICON 2 +#define IDC_STATIC -1 +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/utils/scratchpad3dviewer/scratchpad3dviewer.cpp b/utils/scratchpad3dviewer/scratchpad3dviewer.cpp new file mode 100644 index 0000000..c31da71 --- /dev/null +++ b/utils/scratchpad3dviewer/scratchpad3dviewer.cpp @@ -0,0 +1,928 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "stdafx.h" +#include "d3dapp.h" +#include "d3dx8math.h" +#include "mathlib/mathlib.h" +#include "ScratchPad3D.h" +#include "tier1/strtools.h" + + +#define SPColorExpand( c ) (c).m_vColor.x, (c).m_vColor.y, (c).m_vColor.z, (c).m_flAlpha + + +class VertPosDiffuse +{ +public: + inline void Init(Vector const &vPos, float r, float g, float b, float a) + { + m_Pos = vPos; + SetDiffuse( r, g, b, a ); + } + + inline void SetDiffuse( float r, float g, float b, float a ) + { + m_Diffuse[0] = (unsigned char)(b * 255.9f); + m_Diffuse[1] = (unsigned char)(g * 255.9f); + m_Diffuse[2] = (unsigned char)(r * 255.9f); + m_Diffuse[3] = (unsigned char)(a * 255.9f); + } + + inline void SetDiffuse( Vector const &vColor ) + { + SetDiffuse( vColor.x, vColor.y, vColor.z, 1 ); + } + + inline void SetTexCoords( const Vector2D &tCoords ) + { + m_tCoords = tCoords; + } + + static inline DWORD GetFVF() {return D3DFVF_DIFFUSE | D3DFVF_XYZ | D3DFVF_TEX1;} + + Vector m_Pos; + unsigned char m_Diffuse[4]; + Vector2D m_tCoords; +}; + +class PosController +{ +public: + Vector m_vPos; + QAngle m_vAngles; +}; + +int g_nLines, g_nPolygons; + +PosController g_ViewController; +Vector g_IdentityBasis[3] = {Vector(1,0,0), Vector(0,1,0), Vector(0,0,1)}; +Vector g_ViewerPos; +Vector g_ViewerBasis[3]; +VMatrix g_mModelView; +CScratchPad3D *g_pScratchPad = NULL; +FILETIME g_LastWriteTime; +char g_Filename[256]; + + +// ------------------------------------------------------------------------------------------ // +// Helper functions. +// ------------------------------------------------------------------------------------------ // + +inline float FClamp(float val, float min, float max) +{ + return (val < min) ? min : (val > max ? max : val); +} + +inline float FMin(float val1, float val2) +{ + return (val1 < val2) ? val1 : val2; +} + +inline float FMax(float val1, float val2) +{ + return (val1 > val2) ? val1 : val2; +} + +inline float CosDegrees(float angle) +{ + return (float)cos(DEG2RAD(angle)); +} + +inline float SinDegrees(float angle) +{ + return (float)sin(DEG2RAD(angle)); +} + +inline float FRand(float a, float b) +{ + return a + (b - a) * ((float)rand() / VALVE_RAND_MAX); +} + +void CheckResult( HRESULT hr ) +{ + if ( FAILED( hr ) ) + { + Assert( 0 ); + } +} + +void DrawLine2(const Vector &vFrom, const Vector &vTo, float r1, float g1, float b1, float a1, float r2, float g2, float b2, float a2) +{ + VertPosDiffuse verts[2]; + + verts[0].Init( vFrom, r1, g1, b1, 1 ); + verts[1].Init( vTo, r2, g2, b2, 1 ); + + CheckResult ( g_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ) ); + CheckResult( g_pDevice->SetTexture( 0, NULL ) ); + CheckResult( g_pDevice->DrawPrimitiveUP( D3DPT_LINELIST, 1, verts, sizeof(verts[0]) ) ); + + ++g_nLines; +} + + +void DrawLine(const Vector &vFrom, const Vector &vTo, float r, float g, float b, float a) +{ + DrawLine2(vFrom, vTo, r,g,b,a, r,g,b,a); +} + + +// zAngle's range is [-90,90]. +// When zAngle is 0, the position is in the middle of the sphere (vertically). +// When zAngle is 90, the position is at the top of the sphere. +// When zAngle is -90, the position is at the bottom of the sphere. +Vector CalcSphereVecAngles(float xyAngle, float zAngle, float fRadius) +{ + Vector vec; + + vec.x = CosDegrees(xyAngle) * CosDegrees(zAngle); + vec.y = SinDegrees(xyAngle) * CosDegrees(zAngle); + vec.z = SinDegrees(zAngle); + + return vec * fRadius; +} + + +// Figure out the rotation to look from vEye to vDest. +void SetupLookAt( const Vector &vEye, const Vector &vDest, Vector basis[3] ) +{ + basis[0] = (vDest - vEye); // Forward. + VectorNormalize( basis[0] ); + basis[2].Init(0.0f, 0.0f, 1.0f); // Up. + + basis[1] = basis[2].Cross(basis[0]); // Left. + VectorNormalize( basis[1] ); + + basis[2] = basis[0].Cross(basis[1]); // Regenerate up. + VectorNormalize( basis[2] ); +} + + +D3DMATRIX* VEngineToTempD3DMatrix( VMatrix const &mat ) +{ + static VMatrix ret; + ret = mat.Transpose(); + return (D3DMATRIX*)&ret; +} + + +void UpdateView(float mouseDeltaX, float mouseDeltaY) +{ + VMatrix mRot; + PosController *pController; + + + pController = &g_ViewController; + + // WorldCraft-like interface.. + if( Sys_HasFocus() ) + { + Vector vForward, vUp, vRight; + AngleVectors( pController->m_vAngles, &vForward, &vRight, &vUp ); + + static float fAngleScale = 0.4f; + static float fDistScale = 0.5f; + + if( Sys_GetKeyState( APPKEY_LBUTTON ) ) + { + if( Sys_GetKeyState( APPKEY_RBUTTON ) ) + { + // Ok, move forward and backwards. + pController->m_vPos += vForward * -mouseDeltaY * fDistScale; + pController->m_vPos += vRight * mouseDeltaX * fDistScale; + } + else + { + pController->m_vAngles.y += -mouseDeltaX * fAngleScale; + pController->m_vAngles.x += mouseDeltaY * fAngleScale; + } + } + else if( Sys_GetKeyState( APPKEY_RBUTTON ) ) + { + pController->m_vPos += vUp * -mouseDeltaY * fDistScale; + pController->m_vPos += vRight * mouseDeltaX * fDistScale; + } + } + + // Set the projection matrix to 90 degrees. + D3DXMATRIX matProj; + D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/2, Sys_ScreenWidth() / (float)Sys_ScreenHeight(), 1.0f, 10000.0f ); + g_pDevice->SetTransform( D3DTS_PROJECTION, &matProj ); + + + // This matrix converts from D3D coordinates (X=right, Y=up, Z=forward) + // to VEngine coordinates (X=forward, Y=left, Z=up). + VMatrix mD3DToVEngine( + 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + + g_ViewerPos = pController->m_vPos; + mRot = SetupMatrixAngles( pController->m_vAngles ); + + g_mModelView = ~mD3DToVEngine * mRot.Transpose3x3() * SetupMatrixTranslation(-g_ViewerPos); + + CheckResult( g_pDevice->SetTransform( D3DTS_VIEW, VEngineToTempD3DMatrix(g_mModelView) ) ); + + // World matrix is identity.. + VMatrix mIdentity = SetupMatrixIdentity(); + CheckResult( g_pDevice->SetTransform( D3DTS_WORLD, (D3DMATRIX*)&mIdentity ) ); +} + + +// ------------------------------------------------------------------------------------------ // +// ScratchPad3D command implementation. +// ------------------------------------------------------------------------------------------ // + +void CommandRender_Point( CScratchPad3D::CBaseCommand *pInCmd, IDirect3DDevice8 *pDevice ) +{ + CScratchPad3D::CCommand_Point *pCmd = (CScratchPad3D::CCommand_Point*)pInCmd; + + g_pDevice->SetRenderState( D3DRS_POINTSIZE, *((DWORD*)&pCmd->m_flPointSize) ); + + VertPosDiffuse vert; + vert.Init( pCmd->m_Vert.m_vPos, SPColorExpand(pCmd->m_Vert.m_vColor) ); + + g_pDevice->DrawPrimitiveUP( D3DPT_POINTLIST, 1, &vert, sizeof(vert) ); +} + + +VertPosDiffuse g_LineBatchVerts[1024]; +int g_nLineBatchVerts = 0; + + +void CommandRender_LinesStart( IDirect3DDevice8 *pDevice ) +{ + // Set states for line drawing. + CheckResult( g_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ) ); + CheckResult( g_pDevice->SetTexture( 0, NULL ) ); +} + +void CommandRender_LinesStop( IDirect3DDevice8 *pDevice ) +{ + CheckResult( g_pDevice->DrawPrimitiveUP( D3DPT_LINELIST, g_nLineBatchVerts / 2, g_LineBatchVerts, sizeof(g_LineBatchVerts[0]) ) ); + g_nLines += g_nLineBatchVerts / 2; + g_nLineBatchVerts = 0; +} + +void CommandRender_Line( CScratchPad3D::CBaseCommand *pInCmd, IDirect3DDevice8 *pDevice ) +{ + CScratchPad3D::CCommand_Line *pCmd = (CScratchPad3D::CCommand_Line*)pInCmd; + + // Flush out the line cache? + if ( g_nLineBatchVerts == sizeof( g_LineBatchVerts ) / sizeof( g_LineBatchVerts[0] ) ) + { + CommandRender_LinesStop( pDevice ); + } + + g_LineBatchVerts[g_nLineBatchVerts].m_Pos = pCmd->m_Verts[0].m_vPos; + g_LineBatchVerts[g_nLineBatchVerts].SetDiffuse( SPColorExpand( pCmd->m_Verts[0].m_vColor ) ); + ++g_nLineBatchVerts; + + g_LineBatchVerts[g_nLineBatchVerts].m_Pos = pCmd->m_Verts[1].m_vPos; + g_LineBatchVerts[g_nLineBatchVerts].SetDiffuse( SPColorExpand( pCmd->m_Verts[1].m_vColor ) ); + ++g_nLineBatchVerts; +} + + +void CommandRender_Polygon( CScratchPad3D::CBaseCommand *pInCmd, IDirect3DDevice8 *pDevice ) +{ + VertPosDiffuse verts[65]; + CScratchPad3D::CCommand_Polygon *pCmd = (CScratchPad3D::CCommand_Polygon*)pInCmd; + + int nVerts = min( 64, pCmd->m_Verts.Size() ); + for( int i=0; i < nVerts; i++ ) + { + verts[i].m_Pos[0] = pCmd->m_Verts[i].m_vPos.x; + verts[i].m_Pos[1] = pCmd->m_Verts[i].m_vPos.y; + verts[i].m_Pos[2] = pCmd->m_Verts[i].m_vPos.z; + verts[i].SetDiffuse( SPColorExpand( pCmd->m_Verts[i].m_vColor ) ); + } + + // Draw wireframe manually since D3D draws internal edges of the triangle fan. + DWORD dwFillMode; + g_pDevice->GetRenderState( D3DRS_FILLMODE, &dwFillMode ); + if( dwFillMode == D3DFILL_WIREFRAME ) + { + if( nVerts >= 2 ) + { + g_pDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, nVerts-1, verts, sizeof(verts[0]) ); + + verts[nVerts] = verts[0]; + g_pDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, 1, &verts[nVerts-1], sizeof(verts[0]) ); + } + } + else + { + CheckResult( g_pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, nVerts - 2, verts, sizeof(verts[0]) ) ); + } + + ++g_nPolygons; +} + +void CommandRender_Matrix( CScratchPad3D::CBaseCommand *pInCmd, IDirect3DDevice8 *pDevice ) +{ + CScratchPad3D::CCommand_Matrix *pCmd = (CScratchPad3D::CCommand_Matrix*)pInCmd; + + VMatrix mTransposed = pCmd->m_mMatrix.Transpose(); + CheckResult( g_pDevice->SetTransform( D3DTS_WORLD, (D3DMATRIX*)mTransposed.m ) ); +} + +void CommandRender_RenderState( CScratchPad3D::CBaseCommand *pInCmd, IDirect3DDevice8 *pDevice ) +{ + CScratchPad3D::CCommand_RenderState *pCmd = (CScratchPad3D::CCommand_RenderState*)pInCmd; + + switch( pCmd->m_State ) + { + case IScratchPad3D::RS_FillMode: + { + if( pCmd->m_Val == IScratchPad3D::FillMode_Wireframe ) + g_pDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME ); + else + g_pDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + } + break; + + case IScratchPad3D::RS_ZRead: + { + g_pDevice->SetRenderState( D3DRS_ZENABLE, pCmd->m_Val ); + } + break; + + case IScratchPad3D::RS_ZBias: + { + g_pDevice->SetRenderState( D3DRS_ZBIAS, pCmd->m_Val ); + } + break; + } +} + +class CCachedTextData : public CScratchPad3D::ICachedRenderData +{ +public: + CCachedTextData() + { + m_pTexture = NULL; + } + + ~CCachedTextData() + { + if ( m_pTexture ) + m_pTexture->Release(); + } + + virtual void Release() + { + delete this; + } + + IDirect3DTexture8 *m_pTexture; + int m_BitmapWidth; + int m_BitmapHeight; + int m_nChars; +}; + + +void GenerateTextGreyscaleBitmap( + const char *pText, + CUtlVector<unsigned char> &bitmap, + int *pWidth, + int *pHeight ) +{ + *pWidth = *pHeight = 0; + + + // Create a bitmap, font, and HDC. + HDC hDC = CreateCompatibleDC( NULL ); + Assert( hDC ); + + HFONT hFont = ::CreateFontA( + 18, // font height + 0, 0, 0, + FW_MEDIUM, + false, + false, + false, + ANSI_CHARSET, + OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + ANTIALIASED_QUALITY, + DEFAULT_PITCH | FF_DONTCARE, + "Arial" ); + Assert( hDC ); + if ( !hFont ) + { + DeleteDC( hDC ); + return; + } + + + // Create a bitmap. Allow for width of 512. Hopefully, that can fit all the text we need. + int bigImageWidth = 512; + int bigImageHeight = 64; + + BITMAPINFOHEADER bmi; + memset( &bmi, 0, sizeof( bmi ) ); + + bmi.biSize = sizeof(BITMAPINFOHEADER); + bmi.biWidth = bigImageWidth; + bmi.biHeight = -bigImageHeight; + bmi.biBitCount = 24; + bmi.biPlanes = 1; + bmi.biCompression = BI_RGB; + + void *pBits = NULL; + HBITMAP hBitmap = CreateDIBSection( hDC, + (BITMAPINFO*)&bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0 ); + Assert( hBitmap && pBits ); + + if ( !hBitmap ) + { + DeleteObject( hFont ); + DeleteDC( hDC ); + return; + } + + // Select the font and bitmap into the DC. + HFONT hOldFont = (HFONT)SelectObject( hDC, hFont ); + HBITMAP hOldBitmap = (HBITMAP)SelectObject( hDC, hBitmap ); + + + // Draw the text into the DC. + SIZE size; + int textLen = strlen( pText ); + GetTextExtentPoint32( hDC, pText, textLen, &size ); + TextOut( hDC, 0, 0, pText, textLen ); + + // Now copy the bits out. + const unsigned char *pSrcBase = (const unsigned char*)pBits; + *pWidth = size.cx; + *pHeight = size.cy; + bitmap.SetSize( size.cy * size.cx ); + for ( int y=0; y < size.cy; y++ ) + { + for ( int x=0; x < size.cx; x++ ) + { + const unsigned char *pSrc = &pSrcBase[ (y*bigImageWidth+x) * 3 ]; + unsigned char *pDest = &bitmap[y * size.cx + x]; + + int avg = (pSrc[0] + pSrc[1] + pSrc[2]) / 3; + *pDest = 0xFF - (unsigned char)avg; + } + } + + + // Unselect the objects from the DC and cleanup everything. + SelectObject( hDC, hOldFont ); + DeleteObject( hFont ); + + SelectObject( hDC, hOldBitmap ); + DeleteObject( hBitmap ); + + DeleteDC( hDC ); +} + + +IDirect3DTexture8* MakeD3DTextureFromBitmap( + CUtlVector<unsigned char> &bitmap, + int width, + int height, + bool bSolidBackground ) +{ + IDirect3DTexture8 *pRet = NULL; + HRESULT hr = g_pDevice->CreateTexture( + width, + height, + 1, + 0, + D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, + &pRet ); + + if ( !pRet || FAILED( hr ) ) + return NULL; + + // Lock the texture and fill it up. + D3DLOCKED_RECT lockedRect; + hr = pRet->LockRect( 0, &lockedRect, NULL, 0 ); + if ( FAILED( hr ) ) + { + Assert( false ); + pRet->Release(); + return NULL; + } + + // Now fill it up. + unsigned char *pDestData = (unsigned char*)lockedRect.pBits; + for ( int y=0; y < height; y++ ) + { + for ( int x=0; x < width; x++ ) + { + unsigned char *pDestPixel = &pDestData[ (y*lockedRect.Pitch + x*4) ]; + unsigned char cSrcColor = bitmap[y*width+x]; + + if ( bSolidBackground ) + { + pDestPixel[3] = 0xFF; + pDestPixel[0] = pDestPixel[1] = pDestPixel[2] = cSrcColor; + } + else + { + pDestPixel[0] = pDestPixel[1] = pDestPixel[2] = pDestPixel[3] = 0xFF; + pDestPixel[3] = cSrcColor; + } + } + } + + pRet->UnlockRect( 0 ); + return pRet; +} + + +void CommandRender_Text( CScratchPad3D::CBaseCommand *pInCmd, IDirect3DDevice8 *pDevice ) +{ + CScratchPad3D::CCommand_Text *pCmd = (CScratchPad3D::CCommand_Text*)pInCmd; + CTextParams *pParams = &pCmd->m_TextParams; + + // First, see if we've already generated the texture for this string. + CCachedTextData *pCached = (CCachedTextData*)pCmd->m_pCachedRenderData; + if ( !pCached ) + { + // Generate a bitmap for this text string. + CUtlVector<unsigned char> bitmap; + int width, height; + GenerateTextGreyscaleBitmap( pCmd->m_String.Base(), bitmap, &width, &height ); + + // Convert the bitmap into a D3D texture. + pCached = new CCachedTextData; + pCached->m_pTexture = MakeD3DTextureFromBitmap( bitmap, width, height, pParams->m_bSolidBackground ); + pCached->m_BitmapWidth = width; + pCached->m_BitmapHeight = height; + pCached->m_nChars = strlen( pCmd->m_String.Base() ); + + // Cache it. + pCmd->m_pCachedRenderData = pCached; + } + + + // Figure out its orientation vectors. + Vector vForward, vRight, vUp; + AngleVectors( pParams->m_vAngles, &vForward, &vRight, &vUp ); + + // Backface removal? + bool bFlip = true; + if ( vForward.Dot( g_ViewerPos - pParams->m_vPos ) < 0 ) + { + if ( pParams->m_bTwoSided ) + bFlip = false; + else + return; + } + + // This is really kludgy, but it's the best info we have here. + float flTotalWidth = pParams->m_flLetterWidth * pCached->m_nChars; + + float flAvgCharWidth = (float)flTotalWidth / pCached->m_nChars; + float flTotalHeight = flAvgCharWidth * 3; + + Vector vShift( 0, 0, 0 ); + if ( pParams->m_bCentered ) + vShift = vRight * ( -flTotalWidth/2 ) + vUp * ( flTotalHeight/2 ); + + // Now draw the quad with the texture in it. + VertPosDiffuse quad[5]; // Leave space for 1 more for the line strip for the border. + + quad[0].m_Pos = pParams->m_vPos; + quad[1].m_Pos = pParams->m_vPos + vRight * flTotalWidth; + quad[2].m_Pos = quad[1].m_Pos - vUp * flTotalHeight; + quad[3].m_Pos = pParams->m_vPos - vUp * flTotalHeight; + + // Set tex coords. + if ( bFlip ) + { + quad[0].m_tCoords.Init( 1, 0 ); + quad[1].m_tCoords.Init( 0, 0 ); + quad[2].m_tCoords.Init( 0, 1 ); + quad[3].m_tCoords.Init( 1, 1 ); + } + else + { + quad[0].m_tCoords.Init( 0, 0 ); + quad[1].m_tCoords.Init( 1, 0 ); + quad[2].m_tCoords.Init( 1, 1 ); + quad[3].m_tCoords.Init( 0, 1 ); + } + + for ( int i=0; i < 4; i++ ) + { + quad[i].m_Pos += vShift; + quad[i].SetDiffuse( pParams->m_vColor.x, pParams->m_vColor.y, pParams->m_vColor.z, pParams->m_flAlpha ); + } + + + // Draw. + + // Backup render states. + DWORD tss[][3] = { + { D3DTSS_COLOROP, D3DTOP_MODULATE, 0 }, + { D3DTSS_COLORARG1, D3DTA_DIFFUSE, 0 }, + { D3DTSS_COLORARG2, D3DTA_TEXTURE, 0 }, + { D3DTSS_ALPHAOP, D3DTOP_MODULATE, 0 }, + { D3DTSS_ALPHAARG1, D3DTA_DIFFUSE, 0 }, + { D3DTSS_ALPHAARG2, D3DTA_TEXTURE, 0 } + }; + #define NUM_TSS ( sizeof( tss ) / sizeof( tss[0] ) ) + + DWORD rss[][3] = { + { D3DRS_ALPHABLENDENABLE, TRUE, 0 }, + { D3DRS_FILLMODE, D3DFILL_SOLID, 0 }, + { D3DRS_SRCBLEND, D3DBLEND_SRCALPHA, 0 }, + { D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA, 0 }, + { D3DRS_FILLMODE, D3DFILL_SOLID, 0 } + }; + #define NUM_RSS ( sizeof( rss ) / sizeof( rss[0] ) ) + + for ( int i=0; i < NUM_TSS; i++ ) + { + g_pDevice->GetTextureStageState( 0, (D3DTEXTURESTAGESTATETYPE)tss[i][0], &tss[i][2] ); + g_pDevice->SetTextureStageState( 0, (D3DTEXTURESTAGESTATETYPE)tss[i][0], tss[i][1] ); + } + for ( int i=0; i < NUM_RSS; i++ ) + { + g_pDevice->GetRenderState( (D3DRENDERSTATETYPE)rss[i][0], &rss[i][2] ); + g_pDevice->SetRenderState( (D3DRENDERSTATETYPE)rss[i][0], rss[i][1] ); + } + + + g_pDevice->SetTexture( 0, pCached->m_pTexture ); + CheckResult( g_pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, quad, sizeof(quad[0]) ) ); + g_pDevice->SetTexture( 0, NULL ); + + ++g_nPolygons; + + + // Restore render states. + for ( int i=0; i < NUM_TSS; i++ ) + g_pDevice->SetTextureStageState( 0, (D3DTEXTURESTAGESTATETYPE)tss[i][0], tss[i][2] ); + + for ( int i=0; i < NUM_RSS; i++ ) + g_pDevice->SetRenderState( (D3DRENDERSTATETYPE)rss[i][0], rss[i][2] ); + + + // Draw wireframe outline.. + if ( pParams->m_bOutline ) + { + DWORD fillMode; + g_pDevice->GetRenderState( D3DRS_FILLMODE, &fillMode ); + g_pDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME ); + + quad[4] = quad[0]; + g_pDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, 4, quad, sizeof(quad[0]) ); + + g_pDevice->SetRenderState( D3DRS_FILLMODE, fillMode ); + } +} + + +typedef void (*CommandRenderFunction_Start)( IDirect3DDevice8 *pDevice ); +typedef void (*CommandRenderFunction_Stop)( IDirect3DDevice8 *pDevice ); +typedef void (*CommandRenderFunction)( CScratchPad3D::CBaseCommand *pInCmd, IDirect3DDevice8 *pDevice ); + +class CCommandRenderFunctions +{ +public: + CommandRenderFunction_Start m_StartFn; + CommandRenderFunction_Start m_StopFn; + CommandRenderFunction m_RenderFn; +}; + +CCommandRenderFunctions g_CommandRenderFunctions[CScratchPad3D::COMMAND_NUMCOMMANDS] = +{ + { NULL, NULL, CommandRender_Point }, + { CommandRender_LinesStart, CommandRender_LinesStop, CommandRender_Line }, + { NULL, NULL, CommandRender_Polygon }, + { NULL, NULL, CommandRender_Matrix }, + { NULL, NULL, CommandRender_RenderState }, + { NULL, NULL, CommandRender_Text } +}; + + +void RunCommands( ) +{ + // Set all the initial states. + g_pDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + g_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE ); + + VMatrix mIdentity = SetupMatrixIdentity(); + g_pDevice->SetTransform( D3DTS_WORLD, (D3DMATRIX*)&mIdentity ); + + int iLastCmd = -1; + for( int i=0; i < g_pScratchPad->m_Commands.Size(); i++ ) + { + CScratchPad3D::CBaseCommand *pCmd = g_pScratchPad->m_Commands[i]; + + if( pCmd->m_iCommand >= 0 && pCmd->m_iCommand < CScratchPad3D::COMMAND_NUMCOMMANDS ) + { + // Call the start/stop handlers for this command type if they exist. + // These can be used to batch primitives. + if ( pCmd->m_iCommand != iLastCmd ) + { + if ( iLastCmd != -1 ) + { + if ( g_CommandRenderFunctions[iLastCmd].m_StopFn ) + g_CommandRenderFunctions[iLastCmd].m_StopFn( g_pDevice ); + } + + iLastCmd = pCmd->m_iCommand; + + if ( g_CommandRenderFunctions[pCmd->m_iCommand].m_StartFn ) + g_CommandRenderFunctions[pCmd->m_iCommand].m_StartFn( g_pDevice ); + } + + g_CommandRenderFunctions[pCmd->m_iCommand].m_RenderFn( pCmd, g_pDevice ); + } + } + + // Call the final stop function. + if ( iLastCmd != -1 ) + { + if ( g_CommandRenderFunctions[iLastCmd].m_StopFn ) + g_CommandRenderFunctions[iLastCmd].m_StopFn( g_pDevice ); + } +} + + +bool CheckForNewFile( bool bForce ) +{ + // See if the file has changed.. + HANDLE hFile = CreateFile( + g_pScratchPad->m_pFilename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL ); + + if( !hFile ) + return false; + + FILETIME createTime, accessTime, writeTime; + if( !GetFileTime( hFile, &createTime, &accessTime, &writeTime ) ) + { + CloseHandle( hFile ); + return false; + } + + bool bChange = false; + if( memcmp(&writeTime, &g_LastWriteTime, sizeof(writeTime)) != 0 || bForce ) + { + bChange = g_pScratchPad->LoadCommandsFromFile(); + if( bChange ) + { + memcpy( &g_LastWriteTime, &writeTime, sizeof(writeTime) ); + } + } + + CloseHandle( hFile ); + return bChange; +} + + +// ------------------------------------------------------------------------------------------ // +// App callbacks. +// ------------------------------------------------------------------------------------------ // + +void UpdateWindowText() +{ + char str[512]; + sprintf( str, "ScratchPad3DViewer: <%s> lines: %d, polygons: %d", g_Filename, g_nLines, g_nPolygons ); + Sys_SetWindowText( str ); +} + + +void AppInit() +{ + // Viewer info. + g_ViewController.m_vPos.Init( -200, 0, 0 ); + g_ViewController.m_vAngles.Init( 0, 0, 0 ); + + char const *pFilename = Sys_FindArg( "-file", "scratch.pad" ); + Q_strncpy( g_Filename, pFilename, sizeof( g_Filename ) ); + + IFileSystem *pFileSystem = ScratchPad3D_SetupFileSystem(); + if( !pFileSystem || pFileSystem->Init() != INIT_OK ) + { + Sys_Quit(); + } + + // FIXME: I took this out of scratchpad 3d, not sure if this is even necessary any more + pFileSystem->AddSearchPath( ".", "PLATFORM" ); + + g_pScratchPad = new CScratchPad3D( pFilename, pFileSystem, false ); + + g_nLines = g_nPolygons = 0; + UpdateWindowText(); + + g_pDevice->SetRenderState( D3DRS_EDGEANTIALIAS, FALSE ); + g_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); + g_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); + g_pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE ); + g_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE ); + g_pDevice->SetTexture( 0, NULL ); + + // Setup point scaling parameters. + float flOne=1; + float flZero=0; + g_pDevice->SetRenderState( D3DRS_POINTSCALEENABLE, TRUE ); + g_pDevice->SetRenderState( D3DRS_POINTSCALE_A, *((DWORD*)&flZero) ); + g_pDevice->SetRenderState( D3DRS_POINTSCALE_B, *((DWORD*)&flZero) ); + g_pDevice->SetRenderState( D3DRS_POINTSCALE_C, *((DWORD*)&flOne) ); + + memset( &g_LastWriteTime, 0, sizeof(g_LastWriteTime) ); +} + + +void AppRender( float frametime, float mouseDeltaX, float mouseDeltaY, bool bInvalidRect ) +{ + g_nLines = 0; + g_nPolygons = 0; + + g_pDevice->SetVertexShader( VertPosDiffuse::GetFVF() ); + + if( !bInvalidRect && + !Sys_GetKeyState( APPKEY_LBUTTON ) && + !Sys_GetKeyState( APPKEY_RBUTTON ) && + !CheckForNewFile(false) ) + { + Sys_Sleep( 100 ); + return; + } + + g_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1, 0 ); + + g_pDevice->BeginScene(); + + UpdateView( mouseDeltaX, mouseDeltaY ); + + RunCommands(); + + g_pDevice->EndScene(); + + g_pDevice->Present( NULL, NULL, NULL, NULL ); + + UpdateWindowText(); +} + + +void AppPreResize() +{ + for( int i=0; i < g_pScratchPad->m_Commands.Size(); i++ ) + { + CScratchPad3D::CBaseCommand *pCmd = g_pScratchPad->m_Commands[i]; + + if ( pCmd->m_iCommand == CScratchPad3D::COMMAND_TEXT ) + { + // Delete the cached data if there is any. + pCmd->ReleaseCachedRenderData(); + } + } +} + +void AppPostResize() +{ +} + + +void AppExit( ) +{ +} + + +void AppKey( int key, int down ) +{ + if( key == 27 ) + { + Sys_Quit(); + } + else if( toupper(key) == 'U' ) + { + CheckForNewFile( true ); + AppRender( 0.1f, 0, 0, true ); + } +} + + +void AppChar( int key ) +{ +} + + + + diff --git a/utils/scratchpad3dviewer/scratchpad3dviewer.vpc b/utils/scratchpad3dviewer/scratchpad3dviewer.vpc new file mode 100644 index 0000000..f58fe84 --- /dev/null +++ b/utils/scratchpad3dviewer/scratchpad3dviewer.vpc @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// SCRATCHPAD3DVIEWER.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin" + +$Include "$SRCDIR\vpc_scripts\source_exe_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,$SRCDIR\dx9sdk\include" + $PreprocessorDefinitions "$BASE;NO_MATHLIB_FTOL" + } + + $Linker + { + $AdditionalDependencies "$BASE $SRCDIR\dx9sdk\lib\dxerr8.lib $SRCDIR\dx9sdk\lib\d3d8.lib $SRCDIR\dx9sdk\lib\d3dx.lib odbc32.lib odbccp32.lib" + } +} + +$Project "ScratchPad3DViewer" +{ + $Folder "Source Files" + { + $File "d3dapp.cpp" + $File "$SRCDIR\public\ScratchPad3D.cpp" + $File "ScratchPad3DViewer.cpp" + $File "StdAfx.cpp" + } + + $Folder "Header Files" + { + $File "d3dapp.h" + $File "$SRCDIR\public\filesystem.h" + $File "$SRCDIR\public\tier1\interface.h" + $File "$SRCDIR\public\IScratchPad3D.h" + $File "$SRCDIR\public\mathlib\mathlib.h" + $File "resource.h" + $File "$SRCDIR\public\ScratchPad3D.h" + $File "StdAfx.h" + $File "$SRCDIR\public\tier1\utlvector.h" + $File "$SRCDIR\public\mathlib\vector.h" + $File "$SRCDIR\public\mathlib\vmatrix.h" + } + + $Folder "Link Libraries" + { + $Lib mathlib + } +} diff --git a/utils/scratchpad3dviewer/stdafx.cpp b/utils/scratchpad3dviewer/stdafx.cpp new file mode 100644 index 0000000..f070499 --- /dev/null +++ b/utils/scratchpad3dviewer/stdafx.cpp @@ -0,0 +1,15 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.cpp : source file that includes just the standard includes +// TerrainBlend.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/utils/scratchpad3dviewer/stdafx.h b/utils/scratchpad3dviewer/stdafx.h new file mode 100644 index 0000000..488bccd --- /dev/null +++ b/utils/scratchpad3dviewer/stdafx.h @@ -0,0 +1,45 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) +#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + + +// Windows Header Files: +#include <windows.h> + +#include "tier0/basetypes.h" + +// C RunTime Header Files +#include <stdio.h> +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> +#include <tchar.h> +#include <d3d8.h> +#include <dxerr8.h> +#include "d3dapp.h" + +// Local Header Files + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_) |