📄 gemvipm.cpp
字号:
/* Copyright (C) Tom Forsyth, 2001.
* All rights reserved worldwide.
*
* This software is provided "as is" without express or implied
* warranties. You may freely copy and compile this source into
* applications you distribute provided that the copyright text
* below is included in the resulting source code, for example:
* "Portions Copyright (C) Tom Forsyth, 2001"
*/
#include "TomsD3DLib.h"
#define STRICT
#define D3D_OVERLOADS
#include <windows.h>
#include <tchar.h>
#include <math.h>
#include <stdio.h>
#include <D3DX8.h>
#include <DInput.h>
#include "D3DApp.h"
#include "D3DFont.h"
#include "D3DUtil.h"
#include "DXUtil.h"
#include "resource.h"
#include "commctrl.h"
#include <list>
#include "object.h"
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
struct CUSTOMVERTEX
{
D3DXVECTOR3 v;
DWORD diffuse;
DWORD specular;
FLOAT tu, tv;
};
#define CUSTOMVERTEX_FVF (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX1)
struct CUSTOM3VERTEX
{
D3DXVECTOR3 v;
DWORD diffuse;
DWORD specular;
FLOAT tu, tv, tt;
};
#define CUSTOM3VERTEX_FVF (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX1|D3DFVF_TEXCOORDSIZE3(0))
struct TVERTEX
{
D3DXVECTOR3 v;
float rhw;
};
#define TVERTEX_FVF (D3DFVF_XYZRHW)
// Fudge - exposes m_pd3dDevice to the outside world.
LPDIRECT3DDEVICE8 g_pd3dDevice = NULL;
// DInput stuff.
IDirectInput8* g_pDI = NULL;
IDirectInputDevice8* g_pMouse = NULL;
HINSTANCE g_hInst = NULL;
BOOL g_bActive = TRUE;
BOOL g_bExclusive = FALSE;
BOOL g_bKeyDownCtrl = FALSE;
BOOL g_bKeyDownShift = FALSE;
BOOL m_bOrbitStrafe = TRUE;
DIMOUSESTATE2 g_dims; // DirectInput mouse state structure
//-----------------------------------------------------------------------------
// Function: SetAcquire
//
// Description:
// Acquire or unacquire the mouse, depending on if the app is active
// Input device must be acquired before the GetDeviceState is called
//
//-----------------------------------------------------------------------------
HRESULT SetAcquire( HWND hWnd )
{
// nothing to do if g_pMouse is NULL
if (NULL == g_pMouse)
return S_FALSE;
if (g_bActive)
{
// acquire the input device
g_pMouse->Acquire();
}
else
{
// unacquire the input device
g_pMouse->Unacquire();
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Function: UpdateInputState
//
// Description:
// Get the input device's state and display it.
//
//-----------------------------------------------------------------------------
char g_szMouseText[256]; // current mouse state text
HRESULT UpdateInputState( HWND hWnd )
{
if (NULL != g_pMouse)
{
HRESULT hr;
hr = DIERR_INPUTLOST;
// if input is lost then acquire and keep trying
while ( DIERR_INPUTLOST == hr )
{
// get the input's device state, and put the state in g_dims
hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &g_dims );
if ( hr == DIERR_INPUTLOST )
{
// DirectInput is telling us that the input stream has
// been interrupted. We aren't tracking any state
// between polls, so we don't have any special reset
// that needs to be done. We just re-acquire and
// try again.
hr = g_pMouse->Acquire();
if ( FAILED(hr) )
{
return hr;
}
}
}
if ( FAILED(hr) )
{
return hr;
}
}
else
{
// No mouse!
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Function: InitDirectInput
//
// Description:
// Initialize the DirectInput variables.
//
//-----------------------------------------------------------------------------
HRESULT InitDirectInput( HWND hWnd, bool bExclusive = FALSE )
{
HRESULT hr;
// Register with the DirectInput subsystem and get a pointer
// to a IDirectInput interface we can use.
hr = DirectInput8Create( g_hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)&g_pDI, NULL );
if ( FAILED(hr) )
{
ASSERT ( FALSE );
return hr;
}
// Obtain an interface to the system mouse device.
hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL );
if ( FAILED(hr) )
{
ASSERT ( FALSE );
return hr;
}
// Set the data format to "mouse format" - a predefined data format
//
// A data format specifies which controls on a device we
// are interested in, and how they should be reported.
//
// This tells DirectInput that we will be passing a
// DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
hr = g_pMouse->SetDataFormat( &c_dfDIMouse2 );
if ( FAILED(hr) )
{
ASSERT ( FALSE );
return hr;
}
// Set the cooperativity level to let DirectInput know how
// this device should interact with the system and with other
// DirectInput applications.
DWORD dwFlags = DISCL_FOREGROUND;
// KLUDGE! Win2k really hates FOREGROUND+EXCLUSIVE devices - don't know why.
#if 0
if ( bExclusive )
{
dwFlags |= DISCL_EXCLUSIVE;
}
else
{
dwFlags |= DISCL_NONEXCLUSIVE;
}
#else
dwFlags |= DISCL_NONEXCLUSIVE;
#endif
hr = g_pMouse->SetCooperativeLevel( hWnd, dwFlags );
if ( FAILED(hr) )
{
ASSERT ( FALSE );
return hr;
}
// And acquire it the first time (the windows message has already missed us).
SetAcquire( hWnd );
return S_OK;
}
//-----------------------------------------------------------------------------
// Function: FreeDirectInput
//
// Description:
// Initialize the DirectInput variables.
//
//-----------------------------------------------------------------------------
HRESULT FreeDirectInput()
{
// Unacquire and release any DirectInputDevice objects.
if (NULL != g_pMouse)
{
// Unacquire the device one last time just in case
// the app tried to exit while the device is still acquired.
g_pMouse->Unacquire();
g_pMouse->Release();
g_pMouse = NULL;
}
// Release any DirectInput objects.
if (NULL != g_pDI)
{
g_pDI->Release();
g_pDI = NULL;
}
return S_OK;
}
// Enter or leave exclusive mode.
HRESULT SetExclusiveMode ( bool bExclusive, HWND hWnd )
{
if ( ( bExclusive && g_bExclusive ) || ( !bExclusive && !g_bExclusive ) )
{
return ( DI_OK );
}
// Need to rip it all down and recreate - what a hassle.
FreeDirectInput();
HRESULT hr = InitDirectInput ( hWnd, bExclusive );
if ( FAILED ( hr ) )
{
return ( hr );
}
g_bExclusive = bExclusive;
return ( hr );
}
//-----------------------------------------------------------------------------
// Name: class CMyD3DApplication
// Desc: Application class. The base class (CD3DApplication) provides the
// generic functionality needed in all Direct3D samples. CMyD3DApplication
// adds functionality specific to this sample program.
//-----------------------------------------------------------------------------
class CMyD3DApplication : public CD3DApplication
{
CD3DFont* m_pFont;
BOOL m_bIgnoreBackFaced;
BOOL m_bShowSlidingWindowInfo;
float m_fSlidingWindowErrorTolerance;
int m_iFindBestErrorCountdown;
VIPMTypeEnum m_vteCurrentDisplayStyle;
BOOL m_bCreateCollapseMode;
int m_iTargetNumCollapses;
float m_fTargetErrorFactor;
BOOL m_bTargetErrorAutoGen;
BOOL m_bWireframe;
int m_iCreateThisManyCollapses;
MeshEdge *m_pedgeBestError;
MeshPt *m_pptBestError;
ObjectInstance m_ObjectInstRoot;
Object *m_pObject;
D3DXMATRIX m_matView;
D3DXMATRIX m_matProjClose;
D3DXMATRIX m_matProjCloseZbias;
D3DXMATRIX m_matProjFar;
HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT );
LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
protected:
HRESULT OneTimeSceneInit();
HRESULT InitDeviceObjects();
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();
HRESULT DeleteDeviceObjects();
HRESULT Render();
HRESULT FrameMove();
HRESULT FinalCleanup();
void SetMenuItems();
public:
CMyD3DApplication();
};
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
// message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
CMyD3DApplication d3dApp;
// DInput needs the instance.
g_hInst = hInst;
if( FAILED( d3dApp.Create( hInst ) ) )
return 0;
return d3dApp.Run();
}
//-----------------------------------------------------------------------------
// Name: CMyD3DApplication()
// Desc: Application constructor. Sets attributes for the app.
//-----------------------------------------------------------------------------
CMyD3DApplication::CMyD3DApplication()
{
m_strWindowTitle = _T("VIPM tester");
m_bUseDepthBuffer = TRUE;
m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
m_bIgnoreBackFaced = TRUE;
m_bShowSlidingWindowInfo = TRUE;
m_bCreateCollapseMode = TRUE;
m_fSlidingWindowErrorTolerance = 0.1f; // 10%
m_iFindBestErrorCountdown = 0;
m_vteCurrentDisplayStyle = VIPMType_Vanilla;
m_iTargetNumCollapses = 0;
m_fTargetErrorFactor = 1.0f;
m_bTargetErrorAutoGen = TRUE;
m_bWireframe = FALSE;
m_iCreateThisManyCollapses = 0;
m_pedgeBestError = NULL;
m_pptBestError = NULL;
g_iMaxNumTrisDrawn = -1; // No limit.
g_bOptimiseVertexOrder = FALSE;
g_bShowVIPMInfo = FALSE;
#if ALLOW_PROGRESS_BARS
g_hWndApp = NULL; // Will be set later.
#endif
}
//-----------------------------------------------------------------------------
// Name: OneTimeSceneInit()
// Desc: Called during initial app startup, this function performs all the
// permanent initialization.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::OneTimeSceneInit()
{
m_pObject = new Object;
ObjectInstance *pInst;
D3DXMATRIX mat;
D3DXMatrixIdentity ( &mat );
pInst = &m_ObjectInstRoot;
// First one should always be at the origin - it's used for editing.
pInst = new ObjectInstance ( m_pObject, pInst );
pInst->matOrn = mat;
pInst->iRenderMethod = m_vteCurrentDisplayStyle;
// Now create loads of objects randomly distributed in a cube or something.
DWORD dwSeed = 0x12345678;
float fSize = 100.f;
for ( int i = 0; i < 1000; i++ )
{
pInst = new ObjectInstance ( m_pObject, pInst );
pInst->matOrn = mat;
pInst->matOrn._41 = ( ( (float)( ( dwSeed >> 0 ) & 0xff ) * ( 1.0f / 255.0f ) ) - 0.5f ) * fSize;
pInst->matOrn._42 = ( ( (float)( ( dwSeed >> 8 ) & 0xff ) * ( 1.0f / 255.0f ) ) - 0.5f ) * fSize;
pInst->matOrn._43 = ( ( (float)( ( dwSeed >> 16 ) & 0xff ) * ( 1.0f / 255.0f ) ) - 0.5f ) * fSize;
pInst->iRenderMethod = m_vteCurrentDisplayStyle;
D3DXMATRIX matTemp;
D3DXMatrixRotationX( &matTemp, (float)( ( dwSeed >> 4 ) & 0xff ) * ( 3.14 / 255.0f ) );
D3DXMatrixMultiply ( &(pInst->matOrn), &matTemp, &(pInst->matOrn) );
D3DXMatrixRotationY( &matTemp, (float)( ( dwSeed >> 12 ) & 0xff ) * ( 3.14 / 255.0f ) );
D3DXMatrixMultiply ( &(pInst->matOrn), &matTemp, &(pInst->matOrn) );
D3DXMatrixRotationZ( &matTemp, (float)( ( dwSeed >> 20 ) & 0xff ) * ( 3.14 / 255.0f ) );
D3DXMatrixMultiply ( &(pInst->matOrn), &matTemp, &(pInst->matOrn) );
// This has no mathematical rigour whatsoever. Just letting you know.
dwSeed += 0x61902856;
dwSeed *= 0x34977;
dwSeed ^= dwSeed >> 23;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FrameMove()
// Desc: Called once per frame, the call is the entry point for animating
// the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FrameMove()
{
return S_OK;
}
void DrawScreenSpacePoint ( D3DXVECTOR3 &vec )
{
TVERTEX vert[4];
vert[0].rhw = 0.5f; // Random non-wierd value.
vert[1].rhw = 0.5f;
vert[2].rhw = 0.5f;
vert[3].rhw = 0.5f;
HRESULT hres;
hres = g_pd3dDevice->SetVertexShader ( TVERTEX_FVF );
const float fSizeOfDot = 4.0f;
vert[0].v = vec;
vert[0].v.y -= fSizeOfDot;
vert[1].v = vec;
vert[1].v.x -= fSizeOfDot * 0.866f;
vert[1].v.y += fSizeOfDot * 0.5f;
vert[2].v = vec;
vert[2].v.x += fSizeOfDot * 0.866f;
vert[2].v.y += fSizeOfDot * 0.5f;
vert[3].v = vert[0].v;
hres = g_pd3dDevice->DrawPrimitiveUP ( D3DPT_LINESTRIP, 3, vert, sizeof(vert[0]) );
}
void DrawScreenSpacePoint ( D3DXVECTOR4 &vec )
{
if ( vec.w > 0.0f )
{
D3DXVECTOR3 vec3 ( vec.x, vec.y, vec.z );
DrawScreenSpacePoint ( vec3 );
}
}
void DrawScreenSpaceEdge ( D3DXVECTOR3 &vecBig, D3DXVECTOR3 &vecSmall )
{
TVERTEX vert[4];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -