home *** CD-ROM | disk | FTP | other *** search
- // 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;
- }
-