home *** CD-ROM | disk | FTP | other *** search
/ 3D Graphics Programming for Windows 95 / 3D_Graphics_Programming_for_Windows_95_Microsoft_1996.iso / samples / basic / 3dwndnew.cpp next >
Encoding:
C/C++ Source or Header  |  1996-02-02  |  6.7 KB  |  322 lines

  1. // 3dWnd.cpp : implementation file
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "Basic.h"
  6.  
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12.  
  13. /////////////////////////////////////////////////////////////////////////////
  14. // One-time class registration mechanism using class static members
  15.  
  16. const char*    szDDWndClassName = "DDWindowClass";
  17. static LRESULT CALLBACK DDWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);
  18.  
  19. BOOL C3dWnd::s_bRegistered = C3dWnd::Register();
  20.  
  21. // static
  22. BOOL C3dWnd::Register()
  23. {
  24.     // register the window class we use for
  25.     // direct draw windows
  26.     WNDCLASS wc;
  27.     memset(&wc, 0, sizeof(wc));
  28.     wc.style = CS_HREDRAW | CS_VREDRAW;
  29.     wc.lpfnWndProc = DDWndProc;
  30.     wc.hInstance = NULL;
  31.     wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
  32.     wc.lpszClassName = szDDWndClassName;
  33.     wc.hbrBackground = (HBRUSH)::GetStockObject(GRAY_BRUSH);
  34.     return ::RegisterClass(&wc);
  35. }
  36.  
  37. /////////////////////////////////////////////////////////////////////////////
  38. // Window procedure for Direct Draw child window
  39.  
  40. static LRESULT CALLBACK DDWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  41. {
  42. #if 0
  43.     switch (uiMsg) {
  44.     case WM_MOVE:
  45.  
  46.  
  47.         break;
  48.  
  49.     case WM_SIZE:
  50.  
  51.  
  52.         break;
  53.  
  54.  
  55.     default:
  56.         break;
  57.     }
  58. #endif
  59.     return ::DefWindowProc(hWnd, uiMsg, wParam, lParam);
  60. }
  61.  
  62. /////////////////////////////////////////////////////////////////////////////
  63. // C3dWnd
  64.  
  65. C3dWnd::C3dWnd()
  66. : m_rcClient(0, 0, 0, 0)
  67. {
  68.     m_pDD = NULL;
  69.     m_pD3D = NULL;
  70.     m_pStage = NULL;
  71.     m_pScene = NULL;
  72.     m_bEnableUpdates = FALSE;
  73.     m_iWidth = 320;
  74.     m_iHeight = 240;
  75.     m_bRepaintAll = TRUE;
  76.     m_hwndDD = NULL;
  77. }
  78.  
  79. C3dWnd::~C3dWnd()
  80. {
  81. }
  82.  
  83.  
  84. BEGIN_MESSAGE_MAP(C3dWnd, CWnd)
  85.     //{{AFX_MSG_MAP(C3dWnd)
  86.     ON_WM_CREATE()
  87.     ON_WM_DESTROY()
  88.     ON_WM_MOVE()
  89.     ON_WM_SIZE()
  90.     ON_WM_PAINT()
  91.     //}}AFX_MSG_MAP
  92. END_MESSAGE_MAP()
  93.  
  94. BOOL C3dWnd::Create(const char* pszCaption,
  95.                     DWORD dwStyle,
  96.                     int x, int y,
  97.                     int cx, int cy,
  98.                     CWnd* pParent/*= NULL*/)
  99. {
  100.     const char* pszClass = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,
  101.                 ::LoadCursor(NULL, IDC_ARROW),
  102.                 (HBRUSH)::GetStockObject(GRAY_BRUSH));
  103.     
  104.     return CWnd::CreateEx(0,
  105.                           pszClass,
  106.                           pszCaption,
  107.                           dwStyle,
  108.                           x, y, 
  109.                           cx, cy,
  110.                           pParent ? pParent->GetSafeHwnd() : NULL,
  111.                           NULL);
  112. }
  113.  
  114. // Create the stage
  115. BOOL C3dWnd::_CreateStage()
  116. {
  117.     ASSERT(m_hwndDD);
  118.  
  119.     // Initialise the direct draw objects
  120.     m_pDD = new CDirectDraw;
  121.     if (!m_pDD->Create()) return FALSE;
  122.  
  123.     // Set the mode for the window
  124.     if (!m_pDD->SetWindowedMode(m_hwndDD,
  125.                                 m_iWidth,
  126.                                 m_iHeight)) {
  127.         return FALSE;
  128.     }
  129.  
  130.     // Create the Direct3D object
  131.     m_pD3D = new CDirect3D;
  132.     if (!m_pD3D->Create(m_pDD)) return FALSE;
  133.  
  134.     // Set the color model we want
  135.     if (! m_pD3D->SetMode(D3DCOLOR_RAMP)) return FALSE;
  136.     
  137.     // Create a stage
  138.     m_pStage = new C3dStage;
  139.     if (!m_pStage->Create(m_pD3D)) return FALSE;
  140.  
  141.     // attach any current scene
  142.     m_pStage->SetScene(m_pScene);
  143.  
  144.     return TRUE;
  145. }
  146.  
  147. // Release the stage and its related components
  148. void C3dWnd::_ReleaseStage()
  149. {
  150.     if (m_pStage) {
  151.         m_pStage->SetScene(NULL);
  152.         delete m_pStage;
  153.         m_pStage = NULL;
  154.     }
  155.     if (m_pD3D) {
  156.         delete m_pD3D;
  157.         m_pD3D = NULL;
  158.     }
  159.     if (m_pDD) {
  160.         delete m_pDD;
  161.         m_pDD = NULL;
  162.     }
  163. }
  164.  
  165. int C3dWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  166. {
  167.     if (CWnd::OnCreate(lpCreateStruct) == -1)
  168.         return -1;
  169.     
  170.     // create the child window we want direct draw to work with
  171.     m_hwndDD = ::CreateWindowEx(0,
  172.                                 szDDWndClassName,
  173.                                 "",
  174.                                 WS_VISIBLE | WS_CHILD,
  175.                                 0, 0,
  176.                                 1, 1,
  177.                                 GetSafeHwnd(),
  178.                                 NULL,
  179.                                 AfxGetInstanceHandle(),
  180.                                 NULL);
  181.     ASSERT(m_hwndDD);
  182.  
  183.     // save the initial size and position
  184.     m_iWidth = lpCreateStruct->cx;
  185.     m_iHeight = lpCreateStruct->cy;
  186.     m_rcClient = CRect(lpCreateStruct->x,
  187.                     lpCreateStruct->y,
  188.                     lpCreateStruct->x + lpCreateStruct->cx,
  189.                     lpCreateStruct->y + lpCreateStruct->cy);
  190.  
  191.     // Create the stage
  192.     if (!_CreateStage()) return -1;
  193.     
  194.     // Create an initial scene
  195.     m_pScene = new C3dScene;
  196.     m_pScene->Create();
  197.     m_pStage->SetScene(m_pScene);
  198.  
  199.     // Set up the lighting
  200.     C3dDirLight dl;
  201.     dl.Create(0.1, 0.7, 0.1);
  202.     m_pScene->AddChild(&dl);
  203.     dl.SetPosition(2, 2, -5);
  204.     dl.SetDirection(-1, -1, 1, 0, 1, 0);
  205.     m_pScene->SetAmbientLight(0.1, 0.1, 0.1);
  206.  
  207.     // Create a shape to add
  208.     C3dShape sh1;
  209.     sh1.CreateSphere(1);
  210.     m_pScene->AddChild(&sh1);
  211.     C3dShape sh2;
  212.     sh2.CreateSphere(0.3);
  213.     sh2.SetColor(0, 0, 1);
  214.     sh1.AddChild(&sh2);
  215.     sh2.SetPosition(0, 0, -2);
  216.     C3dShape sh3;
  217.     sh3.CreateSphere(0.15);
  218.     sh3.SetColor(1, 0, 0);
  219.     sh1.AddChild(&sh3);
  220.     sh3.SetPosition(0, 0, 5);
  221.     sh1.SetRotation(1, 1, 0, 0.015);
  222.  
  223.     // Eanble the idle-time rendering
  224.     m_bEnableUpdates = TRUE;
  225.     
  226.     return 0;
  227. }
  228.  
  229. void C3dWnd::OnDestroy() 
  230. {
  231.     CWnd::OnDestroy();
  232.     
  233.     // Clean up
  234.     _ReleaseStage();
  235. }
  236.  
  237. // Make sure the CWnd object gets destroyed when the window
  238. // is destroyed
  239. void C3dWnd::PostNcDestroy() 
  240. {
  241.     CWnd::PostNcDestroy();
  242.     delete this;
  243. }
  244.  
  245. // Update the current scene, render it and draw the changes to the screen
  246. // returns TRUE if it has something to do, FALSE if idle
  247. BOOL C3dWnd::Update()
  248. {
  249.     if (!m_bEnableUpdates) return FALSE;
  250.  
  251.     if (!m_pScene) {
  252.         m_bEnableUpdates = FALSE;
  253.         return FALSE;
  254.     }
  255.  
  256.     RECT rcFrom;
  257.     rcFrom.left = 0;
  258.     rcFrom.top = 0;
  259.     rcFrom.right = m_iWidth;
  260.     rcFrom.bottom = m_iHeight;
  261.  
  262.     // if the window has been resized - force an update
  263.     // of the entire area
  264.     if (m_bRepaintAll) {
  265.         m_pStage->ForceUpdate(&rcFrom);
  266.     }
  267.  
  268.     // update the scene
  269.     //m_pStage->Clear();
  270.     m_pScene->Move();
  271.     m_pStage->Render();
  272.     BOOL b;
  273.  
  274.     // Blt the back buffer to the front buffer so we
  275.     // can see what we rendered
  276.     b = m_pDD->GetFrontBuffer()->Blt(&m_rcClient,
  277.                                  m_pDD->GetBackBuffer(),
  278.                                  &rcFrom,
  279.                                  DDBLT_WAIT,
  280.                                  NULL);
  281.  
  282.     m_bRepaintAll = FALSE;
  283.     return TRUE;
  284. }
  285.  
  286.  
  287. void C3dWnd::OnMove(int x, int y) 
  288. {
  289.     // Compute the screen coordinates of the client rectangle
  290.     m_rcClient = CRect(x, y, x+m_iWidth, y+m_iHeight);
  291. }
  292.  
  293. void C3dWnd::OnSize(UINT nType, int cx, int cy) 
  294. {
  295.     if ((cx <= 0) || (cy <= 0)) return;
  296.  
  297.     // resize the child to fit
  298.     ::MoveWindow(m_hwndDD, 0, 0, cx, cy, FALSE);
  299.  
  300.     if ((cx == m_iWidth) && (cy == m_iHeight)) return;
  301.     
  302.     // Shut down and restart
  303.     _ReleaseStage();
  304.  
  305.     // Compute the new screen coordinates
  306.     m_iWidth = cx;
  307.     m_iHeight = cy;
  308.     m_rcClient = CRect(0, 0, m_iWidth, m_iHeight);
  309.     ClientToScreen(&m_rcClient);
  310.  
  311.     _CreateStage();
  312.     m_bRepaintAll = TRUE;
  313. }
  314.  
  315. void C3dWnd::OnPaint() 
  316. {
  317.     CPaintDC dc(this); // device context for painting
  318.     
  319.     // Behave as though the window was resized
  320.     m_bRepaintAll = TRUE;
  321. }
  322.