home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwwin / rwmfcvw.cp_ / rwmfcvw.bin
Encoding:
Text File  |  1995-11-14  |  11.5 KB  |  371 lines

  1. // rwmfcvw.cpp : implementation of the CRwView class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "rwmfc.h"
  6.  
  7. #include "rwmfcdoc.h"
  8. #include "rwmfcvw.h"
  9.  
  10. #include "aboutlib.h"
  11.  
  12. #include "pick.h"
  13.  
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char BASED_CODE THIS_FILE[] = __FILE__;
  17. #endif
  18.  
  19. #define MAXCAMERAWIDTH        800
  20. #define MAXCAMERAHEIGHT       600
  21. #define DEFAULTVIEWWINDOWSIZE CREAL(0.4)
  22.  
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CRwView
  25.  
  26. IMPLEMENT_DYNCREATE(CRwView, CView)
  27.  
  28. BEGIN_MESSAGE_MAP(CRwView, CView)
  29.     //{{AFX_MSG_MAP(CRwView)
  30.     ON_WM_SIZE()
  31.     ON_WM_ERASEBKGND()
  32.     ON_COMMAND(ID_APP_ABOUTLIBRARY, OnAppAboutlibrary)
  33.     ON_WM_LBUTTONDOWN()
  34.     ON_WM_MOUSEMOVE()
  35.     ON_WM_LBUTTONUP()
  36.     //}}AFX_MSG_MAP
  37.     // Standard printing commands
  38.     ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
  39.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
  40. END_MESSAGE_MAP()
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CRwView construction/destruction
  44.  
  45. CRwView::CRwView()
  46. {
  47.     m_cameraMaxWidth  = (RwInt32)max(::GetSystemMetrics(SM_CXSCREEN), MAXCAMERAWIDTH);
  48.     m_cameraMaxHeight = (RwInt32)max(::GetSystemMetrics(SM_CYSCREEN), MAXCAMERAHEIGHT);
  49.     
  50.     m_camera = ::RwCreateCamera(m_cameraMaxWidth, m_cameraMaxHeight, NULL);
  51.     if (m_camera == NULL)
  52.     {
  53.         AfxMessageBox("Could not create the 3D camera", MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  54.     }
  55.     else
  56.     {
  57.         ::RwSetCameraProjection(m_camera, rwPERSPECTIVE);
  58.         ::RwSetCameraViewwindow(m_camera, DEFAULTVIEWWINDOWSIZE, DEFAULTVIEWWINDOWSIZE);
  59.         ::RwSetCameraBackColor(m_camera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
  60.         ::RwVCMoveCamera(m_camera, CREAL(0.0), CREAL(0.0), CREAL(-5.0));
  61.     }
  62. }
  63.  
  64. CRwView::~CRwView()
  65. {
  66.     if (m_camera != NULL)
  67.     {
  68.         ::RwDestroyCamera(m_camera);
  69.         m_camera = NULL;
  70.     }
  71. }
  72.  
  73. /////////////////////////////////////////////////////////////////////////////
  74. // CRwView drawing
  75.  
  76. void CRwView::OnDraw(CDC* pDC)
  77. {
  78.     CRwDoc* pDoc = GetDocument();
  79.     ASSERT_VALID(pDoc);
  80.  
  81.     if (m_camera != NULL)
  82.     {
  83.         ::RwInvalidateCameraViewport(m_camera);
  84.         ReRenderView(pDC);
  85.     }
  86. }
  87.  
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CRwView printing
  90.  
  91. BOOL CRwView::OnPreparePrinting(CPrintInfo* pInfo)
  92. {
  93.     // default preparation
  94.     return DoPreparePrinting(pInfo);
  95. }
  96.  
  97. void CRwView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  98. {
  99.     // TODO: add extra initialization before printing
  100. }
  101.  
  102. void CRwView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  103. {
  104.     // TODO: add cleanup after printing
  105. }
  106.  
  107. /////////////////////////////////////////////////////////////////////////////
  108. // CRwView diagnostics
  109.  
  110. #ifdef _DEBUG
  111. void CRwView::AssertValid() const
  112. {
  113.     CView::AssertValid();
  114. }
  115.  
  116. void CRwView::Dump(CDumpContext& dc) const
  117. {
  118.     CView::Dump(dc);
  119. }
  120.  
  121. CRwDoc* CRwView::GetDocument() // non-debug version is inline
  122. {
  123.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CRwDoc)));
  124.     return (CRwDoc*)m_pDocument;
  125. }
  126. #endif //_DEBUG
  127.  
  128. /////////////////////////////////////////////////////////////////////////////
  129. // CRwView message handlers
  130.  
  131. void CRwView::OnSize(UINT nType, int cx, int cy)
  132. {
  133.     CView::OnSize(nType, cx, cy);
  134.  
  135.     if ((m_camera != NULL) && (cx > 0) && (cy > 0))
  136.     {
  137.         RwReal viewWindowWidth;
  138.         RwReal viewWindowHeight;
  139.         
  140.         ::RwSetCameraViewport(m_camera, 0L, 0L, (RwInt32)cx, (RwInt32)cy);
  141.         if (cx > cy)
  142.         {
  143.             viewWindowWidth  = DEFAULTVIEWWINDOWSIZE;
  144.             viewWindowHeight = RDiv(RMul(INT2REAL(cy), DEFAULTVIEWWINDOWSIZE), INT2REAL(cx));
  145.         }
  146.         else
  147.         {
  148.             viewWindowWidth  = RDiv(RMul(INT2REAL(cx), DEFAULTVIEWWINDOWSIZE), INT2REAL(cy));
  149.             viewWindowHeight = DEFAULTVIEWWINDOWSIZE;
  150.         }
  151.         ::RwSetCameraViewwindow(m_camera, viewWindowWidth, viewWindowHeight);
  152.     }
  153. }
  154.  
  155. BOOL CRwView::OnEraseBkgnd(CDC* /* pDC */)
  156. {
  157.     // RenderWare does all the erasing.
  158.     return TRUE;
  159. }
  160.  
  161. void CRwView::OnAppAboutlibrary()
  162. {
  163.     CAboutLibraryDialog aboutLibraryDialog;
  164.     
  165.     if (aboutLibraryDialog.DoModal() == IDOK)
  166.     {
  167.         // Sometimes causes a crash if I ignore the result
  168.         // of DoModel(). Why? Don't know.
  169.     }
  170. }
  171.  
  172. void CRwView::OnLButtonDown(UINT nFlags, CPoint point)
  173. {
  174.     CRwDoc* pDoc = GetDocument();
  175.     ASSERT_VALID(pDoc);
  176.     
  177.     if (pDoc->m_scene != NULL)
  178.     {
  179.         RwPickRecord pick;
  180.         
  181.         if (::RwPickScene(pDoc->m_scene, point.x, point.y, m_camera, &pick))
  182.         {
  183.             if (pick.type == rwPICKCLUMP)
  184.             {
  185.                 /*
  186.                  * We have picked a clump.
  187.                  */
  188.                 if (nFlags & MK_SHIFT)
  189.                     m_mouseMode  = rwvDRAGOBJECT;
  190.                 else
  191.                     m_mouseMode  = rwvSPINOBJECT;
  192.                 m_selectedClump  = pick.object.clump.clump;
  193.                 m_leftButtonDown = TRUE;
  194.                 SetCapture();
  195.             }
  196.             
  197.             m_lastPoint = point;
  198.         }
  199.     }
  200.     
  201.     CView::OnLButtonDown(nFlags, point);
  202. }
  203.  
  204. void CRwView::OnMouseMove(UINT nFlags, CPoint point)
  205. {
  206.     if (m_leftButtonDown)
  207.     {
  208.         RwReal      xDelta;
  209.         RwReal      yDelta;
  210.         RwReal      xAngle;
  211.         RwReal      yAngle;
  212.         RwV3d       up;
  213.         RwV3d       right;
  214.         RwV3d       p;
  215.         RwV3d       o;
  216.         RwClump*    parent;
  217.         RwMatrix4d* tmpMatrix;
  218.         RwMatrix4d* worldToLocal;
  219.     
  220.         CRwDoc* pDoc = GetDocument();
  221.         ASSERT_VALID(pDoc);
  222.         
  223.         switch (m_mouseMode)
  224.         {
  225.             case rwvSPINOBJECT:
  226.                 /*
  227.                  * Compute the angles of spin (simply derived from the mouse move deltas).
  228.                  */
  229.                 yAngle = INT2REAL(point.x - m_lastPoint.x);
  230.                 xAngle = INT2REAL(point.y - m_lastPoint.y);
  231.  
  232.                 /*
  233.                  * In RwView, a clump is spun about its own, local coordinate system,
  234.                  * origin, rather than the origin of the world coordinate system. There
  235.                  * are a number of ways this could be achieved, but the most convenient
  236.                  * is to simply apply the rotations to the clump's joint (articulation)
  237.                  * transform.
  238.                  *
  239.                  * A further important point is that the axes of rotation must be the
  240.                  * camera's Look Up and Look Right vector rather than simply
  241.                  * [CREAL(0.0), CREAL(1.0), CREAL(0.0)] and
  242.                  * [CREAL(1.0), CREAL(0.0), CREAL(0.0)]. This ensures that, if the camera
  243.                  * has been panned, tilted, revolved or transformed so that it no longer
  244.                  * looks down the Z axis, user interaction will still operate correctly,
  245.                  * i.e. moving the mouse to the left will spin the clump clockwise etc.
  246.                  *
  247.                  * Therefore, the first stage is to get the camera's Look Up and
  248.                  * Look Right vectors.
  249.                  */
  250.                 ::RwGetCameraLookUp(m_camera, &up);
  251.                 ::RwGetCameraLookRight(m_camera, &right);
  252.  
  253.                 /*
  254.                  * Unfortunately, rotation about the camera's Look Up and Look Right
  255.                  * vectors is complicated if the clump being manipulated is a child
  256.                  * clump (i.e. not the root of a clump hierarchy). If this is the
  257.                  * case, the camera's vectors have to be transformed into the
  258.                  * coordinate space of the parent of the clump being manipulated.
  259.                  */
  260.                 parent = ::RwGetClumpParent(m_selectedClump);
  261.                 if (parent != NULL)
  262.                 {
  263.                     /*
  264.                      * Get a handle to a couple of temporary matrices.
  265.                      */
  266.                     tmpMatrix    = ::RwPushScratchMatrix();
  267.                     worldToLocal = ::RwPushScratchMatrix();
  268.  
  269.                     /*
  270.                      * Get the parent clump's LTM (which maps local coordinates to
  271.                      * world space).
  272.                      */
  273.                     ::RwGetClumpLTM(parent, tmpMatrix);
  274.  
  275.                     /*
  276.                      * Invert it so that it maps world coordinates to the parent's
  277.                      * local coordinate space.
  278.                      */
  279.                     ::RwInvertMatrix(tmpMatrix, worldToLocal);
  280.  
  281.                     /*
  282.                      * And transform the camera's vectors into local space.
  283.                      */
  284.                     ::RwTransformVector(&up, worldToLocal);
  285.                     ::RwNormalize(&up);
  286.                     ::RwTransformVector(&right, worldToLocal);
  287.                     ::RwNormalize(&right);
  288.  
  289.                     /*
  290.                      * Discard the temporary matrices.
  291.                      */
  292.                     ::RwPopScratchMatrix();
  293.                     ::RwPopScratchMatrix();
  294.                 }
  295.  
  296.                 ::RwPushScratchMatrix();
  297.                 
  298.                     /*
  299.                      * Apply the rotations.
  300.                      */
  301.                     ::RwRotateMatrix(::RwScratchMatrix(), up.x, up.y, up.z, yAngle, rwREPLACE);
  302.                     ::RwRotateMatrix(::RwScratchMatrix(), right.x, right.y, right.z, xAngle, rwPOSTCONCAT);
  303.  
  304.                     /*
  305.                      * Apply the resulting, composite transformation to the clump.
  306.                      */
  307.                     ::RwTransformClumpJoint(m_selectedClump, ::RwScratchMatrix(), rwPOSTCONCAT);
  308.                     
  309.                 ::RwPopScratchMatrix();
  310.                 break;
  311.  
  312.             case rwvDRAGOBJECT:
  313.                 GetClumpPositionUnderPointer(m_selectedClump, m_camera, point.x, point.y, &p);
  314.                 ::RwGetClumpOrigin(m_selectedClump, &o);
  315.                 p.x = RSub(p.x, o.x);
  316.                 p.y = RSub(p.y, o.y);
  317.                 p.z = RSub(p.z, o.z);
  318.                 ::RwPushScratchMatrix();
  319.                     ::RwTranslateMatrix(::RwScratchMatrix(), p.x, p.y, p.z, rwREPLACE);
  320.                     ::RwTransformClump(m_selectedClump, ::RwScratchMatrix(), rwPOSTCONCAT);
  321.                 ::RwPopScratchMatrix();
  322.                 break;
  323.         }
  324.         
  325.         m_lastPoint = point;
  326.         
  327.         // Get all views of the document to update. This triggers a rerender. Rather than
  328.         // directly rerendering we let the OnUpdate() message called via this document
  329.         // function to do our rerendering.
  330.         pDoc->UpdateAllViews(NULL);
  331.     }
  332.     
  333.     CView::OnMouseMove(nFlags, point);
  334. }
  335.  
  336. void CRwView::OnLButtonUp(UINT nFlags, CPoint point)
  337. {
  338.     if (m_leftButtonDown)
  339.     {
  340.         switch (m_mouseMode)
  341.         {
  342.             case rwvSPINOBJECT:
  343.                 m_mouseMode = rwvNOACTION;
  344.                 break;
  345.         }    
  346.         m_leftButtonDown = FALSE;
  347.         ReleaseCapture();
  348.     }
  349.     
  350.     CView::OnLButtonUp(nFlags, point);
  351. }
  352.  
  353. void CRwView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
  354. {
  355.     CDC* pDC = GetDC();
  356.     ReRenderView(pDC);
  357.     ReleaseDC(pDC);
  358. }
  359.  
  360. void CRwView::ReRenderView(CDC* pDC)
  361. {
  362.     CRwDoc* pDoc = GetDocument();
  363.     ASSERT_VALID(pDoc);
  364.     
  365.     ::RwBeginCameraUpdate(m_camera, (void *)(DWORD)m_hWnd);
  366.         ::RwClearCameraViewport(m_camera);
  367.         ::RwRenderScene(pDoc->m_scene);
  368.     ::RwEndCameraUpdate(m_camera);
  369.     ::RwShowCameraImage(m_camera, (void*)(DWORD)pDC->m_hDC);
  370. }
  371.