home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / atl / circcoll / tanglvis.cpp < prev   
C/C++ Source or Header  |  1998-03-26  |  8KB  |  302 lines

  1. // AtlTangramGLVisual.cpp : Implementation of CAtlTangramGLVisual
  2. //
  3. // This is a part of the Active Template Library.
  4. // Copyright (C) 1996-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Active Template Library Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Active Template Library product.
  12.  
  13. #include "stdafx.h"
  14. #include "GLWorld.h"
  15. #include "TanGLVis.h"
  16. #include "event_i_i.c"
  17. #include <windows.h>
  18. #include <olectl.h>
  19.  
  20. // STL Interfaces
  21. #include <new.h>
  22. #include <algorithm>
  23. #include <xmemory>
  24. #include <list>
  25. #include "util.h"
  26. #include "util.cpp"
  27. #include "CGL.h"
  28. #include "CGL.cpp"
  29. #include "CGL-Pal.cpp"
  30.  
  31. // Interfaces
  32. #include "TanCanv_i.c"
  33. #include "AtlModel.h"
  34. #include "GdiWorld.h"
  35. #include "GdiWorld_i.c"
  36.  
  37. // Sub-Components.
  38. #include "AtlModel_i.c"
  39.  
  40. // Other
  41. #include <math.h>
  42. #include <gl/gl.h>
  43. #include <gl/glu.h>
  44.  
  45. ///////////////////////////////////////////////////////////
  46. //
  47. // Destructor
  48. //
  49. CAtlTangramGLVisual::~CAtlTangramGLVisual()
  50. {
  51.  
  52.     // We keep a strong reference to the model.
  53.     // Therefore, we need to release it here.
  54.     m_pModel->Release();
  55.     m_pModel = NULL;
  56.  
  57.     // We maintain a weak reference to GdiWorld to avoid
  58.     // reference cycles. A weak reference means that we
  59.     // do not need to Release m_pGdiWorld here.
  60.  
  61.     // Delete the vertex array.
  62.     delete [] m_ptVertices;
  63. }
  64.  
  65. ///////////////////////////////////////////////////////////
  66. //  ITangramVisual
  67. // ITangramVisual::SetSelected Implementation.
  68.  
  69. HRESULT CAtlTangramGLVisual::SetSelected(BOOL bSelected)
  70. {
  71.     m_bSelected = bSelected;
  72.  
  73.     // Update the display.
  74.     HRESULT hr = m_pWorld->Animate();
  75.     ASSERT_HRESULT(hr);
  76.  
  77.     return S_OK;
  78. }
  79.  
  80. ///////////////////////////////////////////////////////////
  81. // ITangramGLVisual::GetModel Implementation
  82.  
  83. HRESULT CAtlTangramGLVisual::GetModel(const IID& iid, IUnknown** ppI)
  84. {
  85.     if (!IsValidInterfaceOutParam(ppI))
  86.     {
  87.         ASSERT(0);
  88.         return E_POINTER;
  89.     }
  90.  
  91.     return m_pModel->QueryInterface(iid, (void**)ppI) ;
  92. }
  93.  
  94. ///////////////////////////////////////////////////////////
  95. //  ITangramGLVisual
  96. // ITangramGLVisual::Initialize Implementation
  97.  
  98. HRESULT __stdcall
  99. CAtlTangramGLVisual::Initialize(IATLTangramModel* pModel,
  100.     IAtlTangramGLWorld* pWorld)
  101. {
  102.     if (!IsValidInterface(pModel)|| !IsValidInterface(pWorld))
  103.     {
  104.         ASSERT(0);
  105.         return E_POINTER;
  106.     }
  107.  
  108.     if (m_pModel != NULL || m_pWorld != NULL)
  109.     {
  110.         // Cannot re-initialize.
  111.         ASSERT(0);
  112.         return E_FAIL;
  113.     }
  114.  
  115.     // Keep a strong reference to the model.
  116.     m_pModel = pModel;
  117.     m_pModel->AddRef();
  118.  
  119.     // To avoid a cyclical reference count, we have a
  120.     // weak reference to GLWorld. Therefore, we do
  121.     // not AddRef this pointer.
  122.     m_pWorld = pWorld;
  123.  
  124.     // Get the number of vertices in the model.
  125.     HRESULT hr = m_pModel->GetNumberOfVertices(&m_cVertices);
  126.     ASSERT_HRESULT(hr);
  127.  
  128.     // Create an array to hold the vertices.
  129.     m_ptVertices = new TangramPoint2d[m_cVertices];
  130.  
  131.     //  Set up event sync
  132.     // Create a sink object.
  133.     TCHAR buf[128];
  134.     wsprintf(buf, _T("Visual: m_dwRef = %d\n"), m_dwRef);
  135.     ATLTRACE(buf);
  136.  
  137.     // Get the connection point container.
  138.     IConnectionPointContainer* pContainer = NULL;
  139.     hr = pModel->QueryInterface(IID_IConnectionPointContainer,
  140.         (void**)&pContainer);
  141.     ASSERT_HRESULT(hr);
  142.  
  143.     // Get our desired connection point. Cache the pointer so
  144.     // we don't have to get it again.
  145.     hr = pContainer->FindConnectionPoint(IID_IATLTangramModelEvent,
  146.         &m_pIConnectionPoint);
  147.     pContainer->Release();
  148.     ASSERT_HRESULT(hr);
  149.  
  150.     IATLTangramModelEvent* pIATLTangramModelEvent;
  151.     hr = GetUnknown()->QueryInterface(IID_IATLTangramModelEvent,
  152.         (void**)&pIATLTangramModelEvent);
  153.     wsprintf(buf, _T("Visual: m_dwRef = %d\n"), m_dwRef);
  154.     ATLTRACE(buf);
  155.  
  156.     // Ask the visual to advise us of any changes.
  157.     hr = m_pIConnectionPoint->Advise(pIATLTangramModelEvent, &m_dwCookie);
  158.     ASSERT_HRESULT(hr);
  159.  
  160.     wsprintf(buf, _T("Visual: m_dwRef = %d\n"), m_dwRef);
  161.     ATLTRACE(buf);
  162.  
  163.     // We don't need to keep a reference to the sink.
  164.     pIATLTangramModelEvent->Release();
  165.     wsprintf(buf, _T("Visual: m_dwRef = %d\n"), m_dwRef);
  166.     ATLTRACE(buf);
  167.     return S_OK;
  168. }
  169.  
  170.  
  171. ///////////////////////////////////////////////////////////
  172. // ITangramGLVisual::DrawOn Implementation
  173.  
  174. HRESULT CAtlTangramGLVisual::DrawOn(IAtlTangramCanvas* pCanvas)
  175. {
  176.     // Preconditions.
  177.     if (!m_bFirstEvent)
  178.     {
  179.         // We have not received a model change event to initialize use.
  180.         return S_FALSE;
  181.     }
  182.  
  183.     if (!IsValidInterface(pCanvas))
  184.     {
  185.         ASSERT(0);
  186.         return E_POINTER;
  187.     }
  188.  
  189.     double thickness = 0.01;
  190.  
  191.     if (m_bSelected)
  192.         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  193.  
  194.     // Bottom
  195.     glNormal3d(0.0, 0.0, -1.0);
  196.     glBegin(GL_TRIANGLE_FAN);
  197.         for (int i = 0; i < m_cVertices; i++)
  198.             glVertex2d(m_ptVertices[i].x, m_ptVertices[i].y);
  199.  
  200.     glEnd();
  201.  
  202.     // Top
  203.     glNormal3d(0.0, 0.0, 1.0);
  204.     glBegin(GL_TRIANGLE_FAN);
  205.         for (i = 0; i < m_cVertices; i++)
  206.             glVertex3d(m_ptVertices[i].x, m_ptVertices[i].y, thickness);
  207.     glEnd();
  208.  
  209.     // Sides
  210.     for (i = 0; i < m_cVertices; i++)
  211.     {
  212.         int iNextIndex = (i+1) % m_cVertices;
  213.  
  214.         // Compute Normal [v1 - v2] X [v2 - v3] see page 58 of RedBook
  215.  
  216.         // V1 = v1 - v2
  217.         double X1 = m_ptVertices[i].x - m_ptVertices[iNextIndex].x;
  218.         double Y1 = m_ptVertices[i].y - m_ptVertices[iNextIndex].y;
  219.         double Z1 = 0.0; // 0.0f - 0.0f;
  220.  
  221.         // V2 = v2 - v3
  222.         double X2 = 0.0; //m_ptVertices[iNextIndex].x - m_ptVertices[iNextIndex].x;
  223.         double Y2 = 0.0; //m_ptVertices[iNextIndex].y - m_ptVertices[iNextIndex].y;
  224.         double Z2 = -thickness; // 0.0 - thickness;
  225.  
  226.         // V = V1 X V2
  227.         double X = Y1 * Z2; //Y1*Z2 - Z1*Y2  = Y1*Z2 - 0.0*0.0;
  228.         double Y = -X1 * Z2; //Z1*X2 - X1*Z2 = 0.0*0.0 - X1*Z2
  229.         //double Z = 0.0; //X1*Y2 - Y1*X2;
  230.  
  231.         // Normalize
  232.         double d = sqrt(X*X + Y*Y /*+ Z*Z*/);
  233.         ASSERT( d != 0.0);
  234.         X /= d;
  235.         Y /= d;
  236.         //Z /= d;
  237.  
  238.         glNormal3d(X, Y, 0.0/*Z*/);
  239.  
  240.         glBegin(GL_QUADS);
  241.             glVertex3d(m_ptVertices[i].x, m_ptVertices[i].y, 0.0);
  242.             glVertex3d(m_ptVertices[iNextIndex].x,
  243.                 m_ptVertices[iNextIndex].y, 0.0);
  244.             glVertex3d(m_ptVertices[iNextIndex].x,
  245.                 m_ptVertices[iNextIndex].y, thickness);
  246.             glVertex3d(m_ptVertices[i].x, m_ptVertices[i].y, thickness);
  247.         glEnd();
  248.     }
  249.  
  250.     if (m_bSelected)
  251.         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  252.  
  253.     return S_OK;
  254. }
  255.  
  256. ///////////////////////////////////////////////////////////
  257. //  ITangramModelEvent
  258. // ITangramModelEvent::OnModelChange
  259.  
  260. HRESULT __stdcall CAtlTangramGLVisual::OnModelChange()
  261. {
  262.     // Create an array to hold the new vertices.
  263.     TangramPoint2d* pointds = new TangramPoint2d[m_cVertices];
  264.  
  265.     // Get the vertices from the model.
  266.     HRESULT hr = m_pModel->GetVertices(m_cVertices, pointds);
  267.     ASSERT_HRESULT(hr);
  268.  
  269.     // Convert the vertices to our coordinates.
  270.     for (int i = 0; i < m_cVertices; i++)
  271.     {
  272.         hr = m_pWorld->ModelToDevice(pointds[i], &m_ptVertices[i]);
  273.         ASSERT_HRESULT(hr);
  274.     }
  275.  
  276.     // Cleanup;
  277.     delete [] pointds;
  278.  
  279.     // We are in sync.
  280.     m_bFirstEvent = TRUE;
  281.  
  282.     // Update the display.
  283.     hr = m_pWorld->Animate();
  284.     ASSERT_HRESULT(hr);
  285.  
  286.     return S_OK;
  287. }
  288.  
  289. STDMETHODIMP CAtlTangramGLVisual::ReleaseConnectionPoint()
  290. {
  291.     HRESULT hr = S_OK;
  292.     // Release the event source component.
  293.     if (m_pIConnectionPoint != NULL)
  294.     {
  295.         // We no longer need to be enformed of events
  296.         HRESULT hr = m_pIConnectionPoint->Unadvise(m_dwCookie);
  297.         ASSERT_HRESULT(hr);
  298.         m_pIConnectionPoint->Release();
  299.     }
  300.     return hr;
  301. }
  302.