www.pudn.com > ·ÉÐÐÆ÷Ä£Äâ.rar > 3DWNDNEW.CPP


// 3dWnd.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "Basic.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// One-time class registration mechanism using class static members 
 
const char*	szDDWndClassName = "DDWindowClass"; 
static LRESULT CALLBACK DDWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam); 
 
BOOL C3dWnd::s_bRegistered = C3dWnd::Register(); 
 
// static 
BOOL C3dWnd::Register() 
{ 
	// register the window class we use for 
	// direct draw windows 
	WNDCLASS wc; 
	memset(&wc, 0, sizeof(wc)); 
	wc.style = CS_HREDRAW | CS_VREDRAW; 
	wc.lpfnWndProc = DDWndProc; 
	wc.hInstance = NULL; 
	wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); 
	wc.lpszClassName = szDDWndClassName; 
	wc.hbrBackground = (HBRUSH)::GetStockObject(GRAY_BRUSH); 
	return ::RegisterClass(&wc); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// Window procedure for Direct Draw child window 
 
static LRESULT CALLBACK DDWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) 
{ 
#if 0 
	switch (uiMsg) { 
	case WM_MOVE: 
 
 
		break; 
 
	case WM_SIZE: 
 
 
		break; 
 
 
    default: 
		break; 
    } 
#endif 
    return ::DefWindowProc(hWnd, uiMsg, wParam, lParam); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// C3dWnd 
 
C3dWnd::C3dWnd() 
: m_rcClient(0, 0, 0, 0) 
{ 
	m_pDD = NULL; 
	m_pD3D = NULL; 
	m_pStage = NULL; 
	m_pScene = NULL; 
	m_bEnableUpdates = FALSE; 
	m_iWidth = 320; 
	m_iHeight = 240; 
	m_bRepaintAll = TRUE; 
	m_hwndDD = NULL; 
} 
 
C3dWnd::~C3dWnd() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(C3dWnd, CWnd) 
	//{{AFX_MSG_MAP(C3dWnd) 
	ON_WM_CREATE() 
	ON_WM_DESTROY() 
	ON_WM_MOVE() 
	ON_WM_SIZE() 
	ON_WM_PAINT() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
BOOL C3dWnd::Create(const char* pszCaption, 
					DWORD dwStyle, 
					int x, int y, 
					int cx, int cy, 
					CWnd* pParent/*= NULL*/) 
{ 
	const char* pszClass = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, 
				::LoadCursor(NULL, IDC_ARROW), 
				(HBRUSH)::GetStockObject(GRAY_BRUSH)); 
	 
	return CWnd::CreateEx(0, 
						  pszClass, 
						  pszCaption, 
						  dwStyle, 
						  x, y,  
						  cx, cy, 
						  pParent ? pParent->GetSafeHwnd() : NULL, 
						  NULL); 
} 
 
// Create the stage 
BOOL C3dWnd::_CreateStage() 
{ 
	ASSERT(m_hwndDD); 
 
	// Initialise the direct draw objects 
	m_pDD = new CDirectDraw; 
	if (!m_pDD->Create()) return FALSE; 
 
	// Set the mode for the window 
	if (!m_pDD->SetWindowedMode(m_hwndDD, 
							    m_iWidth, 
							    m_iHeight)) { 
		return FALSE; 
	} 
 
	// Create the Direct3D object 
	m_pD3D = new CDirect3D; 
	if (!m_pD3D->Create(m_pDD)) return FALSE; 
 
	// Set the color model we want 
	if (! m_pD3D->SetMode(D3DCOLOR_RAMP)) return FALSE; 
	 
	// Create a stage 
	m_pStage = new C3dStage; 
	if (!m_pStage->Create(m_pD3D)) return FALSE; 
 
	// attach any current scene 
	m_pStage->SetScene(m_pScene); 
 
	return TRUE; 
} 
 
// Release the stage and its related components 
void C3dWnd::_ReleaseStage() 
{ 
	if (m_pStage) { 
		m_pStage->SetScene(NULL); 
		delete m_pStage; 
		m_pStage = NULL; 
	} 
	if (m_pD3D) { 
		delete m_pD3D; 
		m_pD3D = NULL; 
	} 
	if (m_pDD) { 
		delete m_pDD; 
		m_pDD = NULL; 
	} 
} 
 
int C3dWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)  
{ 
	if (CWnd::OnCreate(lpCreateStruct) == -1) 
		return -1; 
	 
	// create the child window we want direct draw to work with 
	m_hwndDD = ::CreateWindowEx(0, 
								szDDWndClassName, 
								"", 
								WS_VISIBLE | WS_CHILD, 
								0, 0, 
								1, 1, 
								GetSafeHwnd(), 
								NULL, 
								AfxGetInstanceHandle(), 
								NULL); 
	ASSERT(m_hwndDD); 
 
	// save the initial size and position 
	m_iWidth = lpCreateStruct->cx; 
	m_iHeight = lpCreateStruct->cy; 
	m_rcClient = CRect(lpCreateStruct->x, 
				    lpCreateStruct->y, 
					lpCreateStruct->x + lpCreateStruct->cx, 
					lpCreateStruct->y + lpCreateStruct->cy); 
 
	// Create the stage 
	if (!_CreateStage()) return -1; 
	 
	// Create an initial scene 
	m_pScene = new C3dScene; 
	m_pScene->Create(); 
	m_pStage->SetScene(m_pScene); 
 
	// Set up the lighting 
    C3dDirLight dl; 
    dl.Create(0.1, 0.7, 0.1); 
    m_pScene->AddChild(&dl); 
    dl.SetPosition(2, 2, -5); 
    dl.SetDirection(-1, -1, 1, 0, 1, 0); 
    m_pScene->SetAmbientLight(0.1, 0.1, 0.1); 
 
	// Create a shape to add 
	C3dShape sh1; 
	sh1.CreateSphere(1); 
	m_pScene->AddChild(&sh1); 
	C3dShape sh2; 
	sh2.CreateSphere(0.3); 
	sh2.SetColor(0, 0, 1); 
	sh1.AddChild(&sh2); 
	sh2.SetPosition(0, 0, -2); 
	C3dShape sh3; 
	sh3.CreateSphere(0.15); 
	sh3.SetColor(1, 0, 0); 
	sh1.AddChild(&sh3); 
	sh3.SetPosition(0, 0, 5); 
	sh1.SetRotation(1, 1, 0, 0.015); 
 
	// Eanble the idle-time rendering 
	m_bEnableUpdates = TRUE; 
	 
	return 0; 
} 
 
void C3dWnd::OnDestroy()  
{ 
	CWnd::OnDestroy(); 
	 
	// Clean up 
	_ReleaseStage(); 
} 
 
// Make sure the CWnd object gets destroyed when the window 
// is destroyed 
void C3dWnd::PostNcDestroy()  
{ 
	CWnd::PostNcDestroy(); 
	delete this; 
} 
 
// Update the current scene, render it and draw the changes to the screen 
// returns TRUE if it has something to do, FALSE if idle 
BOOL C3dWnd::Update() 
{ 
	if (!m_bEnableUpdates) return FALSE; 
 
	if (!m_pScene) { 
		m_bEnableUpdates = FALSE; 
		return FALSE; 
	} 
 
	RECT rcFrom; 
	rcFrom.left = 0; 
	rcFrom.top = 0; 
	rcFrom.right = m_iWidth; 
	rcFrom.bottom = m_iHeight; 
 
	// if the window has been resized - force an update 
	// of the entire area 
	if (m_bRepaintAll) { 
		m_pStage->ForceUpdate(&rcFrom); 
	} 
 
	// update the scene 
	//m_pStage->Clear(); 
    m_pScene->Move(); 
    m_pStage->Render(); 
	BOOL b; 
 
	// Blt the back buffer to the front buffer so we 
	// can see what we rendered 
	b = m_pDD->GetFrontBuffer()->Blt(&m_rcClient, 
								 m_pDD->GetBackBuffer(), 
								 &rcFrom, 
								 DDBLT_WAIT, 
								 NULL); 
 
	m_bRepaintAll = FALSE; 
	return TRUE; 
} 
 
 
void C3dWnd::OnMove(int x, int y)  
{ 
	// Compute the screen coordinates of the client rectangle 
	m_rcClient = CRect(x, y, x+m_iWidth, y+m_iHeight); 
} 
 
void C3dWnd::OnSize(UINT nType, int cx, int cy)  
{ 
	if ((cx <= 0) || (cy <= 0)) return; 
 
	// resize the child to fit 
	::MoveWindow(m_hwndDD, 0, 0, cx, cy, FALSE); 
 
	if ((cx == m_iWidth) && (cy == m_iHeight)) return; 
	 
	// Shut down and restart 
	_ReleaseStage(); 
 
	// Compute the new screen coordinates 
	m_iWidth = cx; 
	m_iHeight = cy; 
	m_rcClient = CRect(0, 0, m_iWidth, m_iHeight); 
	ClientToScreen(&m_rcClient); 
 
	_CreateStage(); 
	m_bRepaintAll = TRUE; 
} 
 
void C3dWnd::OnPaint()  
{ 
	CPaintDC dc(this); // device context for painting 
	 
	// Behave as though the window was resized 
	m_bRepaintAll = TRUE; 
}