home *** CD-ROM | disk | FTP | other *** search
- // rwmfcvw.cpp : implementation of the CRwView class
- //
-
- #include "stdafx.h"
- #include "rwmfc.h"
-
- #include "rwmfcdoc.h"
- #include "rwmfcvw.h"
-
- #include "aboutlib.h"
-
- #include "pick.h"
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- #define MAXCAMERAWIDTH 800
- #define MAXCAMERAHEIGHT 600
- #define DEFAULTVIEWWINDOWSIZE CREAL(0.4)
-
- /////////////////////////////////////////////////////////////////////////////
- // CRwView
-
- IMPLEMENT_DYNCREATE(CRwView, CView)
-
- BEGIN_MESSAGE_MAP(CRwView, CView)
- //{{AFX_MSG_MAP(CRwView)
- ON_WM_SIZE()
- ON_WM_ERASEBKGND()
- ON_COMMAND(ID_APP_ABOUTLIBRARY, OnAppAboutlibrary)
- ON_WM_LBUTTONDOWN()
- ON_WM_MOUSEMOVE()
- ON_WM_LBUTTONUP()
- //}}AFX_MSG_MAP
- // Standard printing commands
- ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
- ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
- END_MESSAGE_MAP()
-
- /////////////////////////////////////////////////////////////////////////////
- // CRwView construction/destruction
-
- CRwView::CRwView()
- {
- m_cameraMaxWidth = (RwInt32)max(::GetSystemMetrics(SM_CXSCREEN), MAXCAMERAWIDTH);
- m_cameraMaxHeight = (RwInt32)max(::GetSystemMetrics(SM_CYSCREEN), MAXCAMERAHEIGHT);
-
- m_camera = ::RwCreateCamera(m_cameraMaxWidth, m_cameraMaxHeight, NULL);
- if (m_camera == NULL)
- {
- AfxMessageBox("Could not create the 3D camera", MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- }
- else
- {
- ::RwSetCameraProjection(m_camera, rwPERSPECTIVE);
- ::RwSetCameraViewwindow(m_camera, DEFAULTVIEWWINDOWSIZE, DEFAULTVIEWWINDOWSIZE);
- ::RwSetCameraBackColor(m_camera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
- ::RwVCMoveCamera(m_camera, CREAL(0.0), CREAL(0.0), CREAL(-5.0));
- }
- }
-
- CRwView::~CRwView()
- {
- if (m_camera != NULL)
- {
- ::RwDestroyCamera(m_camera);
- m_camera = NULL;
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CRwView drawing
-
- void CRwView::OnDraw(CDC* pDC)
- {
- CRwDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- if (m_camera != NULL)
- {
- ::RwInvalidateCameraViewport(m_camera);
- ReRenderView(pDC);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CRwView printing
-
- BOOL CRwView::OnPreparePrinting(CPrintInfo* pInfo)
- {
- // default preparation
- return DoPreparePrinting(pInfo);
- }
-
- void CRwView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- // TODO: add extra initialization before printing
- }
-
- void CRwView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- // TODO: add cleanup after printing
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CRwView diagnostics
-
- #ifdef _DEBUG
- void CRwView::AssertValid() const
- {
- CView::AssertValid();
- }
-
- void CRwView::Dump(CDumpContext& dc) const
- {
- CView::Dump(dc);
- }
-
- CRwDoc* CRwView::GetDocument() // non-debug version is inline
- {
- ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CRwDoc)));
- return (CRwDoc*)m_pDocument;
- }
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // CRwView message handlers
-
- void CRwView::OnSize(UINT nType, int cx, int cy)
- {
- CView::OnSize(nType, cx, cy);
-
- if ((m_camera != NULL) && (cx > 0) && (cy > 0))
- {
- RwReal viewWindowWidth;
- RwReal viewWindowHeight;
-
- ::RwSetCameraViewport(m_camera, 0L, 0L, (RwInt32)cx, (RwInt32)cy);
- if (cx > cy)
- {
- viewWindowWidth = DEFAULTVIEWWINDOWSIZE;
- viewWindowHeight = RDiv(RMul(INT2REAL(cy), DEFAULTVIEWWINDOWSIZE), INT2REAL(cx));
- }
- else
- {
- viewWindowWidth = RDiv(RMul(INT2REAL(cx), DEFAULTVIEWWINDOWSIZE), INT2REAL(cy));
- viewWindowHeight = DEFAULTVIEWWINDOWSIZE;
- }
- ::RwSetCameraViewwindow(m_camera, viewWindowWidth, viewWindowHeight);
- }
- }
-
- BOOL CRwView::OnEraseBkgnd(CDC* /* pDC */)
- {
- // RenderWare does all the erasing.
- return TRUE;
- }
-
- void CRwView::OnAppAboutlibrary()
- {
- CAboutLibraryDialog aboutLibraryDialog;
-
- if (aboutLibraryDialog.DoModal() == IDOK)
- {
- // Sometimes causes a crash if I ignore the result
- // of DoModel(). Why? Don't know.
- }
- }
-
- void CRwView::OnLButtonDown(UINT nFlags, CPoint point)
- {
- CRwDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- if (pDoc->m_scene != NULL)
- {
- RwPickRecord pick;
-
- if (::RwPickScene(pDoc->m_scene, point.x, point.y, m_camera, &pick))
- {
- if (pick.type == rwPICKCLUMP)
- {
- /*
- * We have picked a clump.
- */
- if (nFlags & MK_SHIFT)
- m_mouseMode = rwvDRAGOBJECT;
- else
- m_mouseMode = rwvSPINOBJECT;
- m_selectedClump = pick.object.clump.clump;
- m_leftButtonDown = TRUE;
- SetCapture();
- }
-
- m_lastPoint = point;
- }
- }
-
- CView::OnLButtonDown(nFlags, point);
- }
-
- void CRwView::OnMouseMove(UINT nFlags, CPoint point)
- {
- if (m_leftButtonDown)
- {
- RwReal xDelta;
- RwReal yDelta;
- RwReal xAngle;
- RwReal yAngle;
- RwV3d up;
- RwV3d right;
- RwV3d p;
- RwV3d o;
- RwClump* parent;
- RwMatrix4d* tmpMatrix;
- RwMatrix4d* worldToLocal;
-
- CRwDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- switch (m_mouseMode)
- {
- case rwvSPINOBJECT:
- /*
- * Compute the angles of spin (simply derived from the mouse move deltas).
- */
- yAngle = INT2REAL(point.x - m_lastPoint.x);
- xAngle = INT2REAL(point.y - m_lastPoint.y);
-
- /*
- * In RwView, a clump is spun about its own, local coordinate system,
- * origin, rather than the origin of the world coordinate system. There
- * are a number of ways this could be achieved, but the most convenient
- * is to simply apply the rotations to the clump's joint (articulation)
- * transform.
- *
- * A further important point is that the axes of rotation must be the
- * camera's Look Up and Look Right vector rather than simply
- * [CREAL(0.0), CREAL(1.0), CREAL(0.0)] and
- * [CREAL(1.0), CREAL(0.0), CREAL(0.0)]. This ensures that, if the camera
- * has been panned, tilted, revolved or transformed so that it no longer
- * looks down the Z axis, user interaction will still operate correctly,
- * i.e. moving the mouse to the left will spin the clump clockwise etc.
- *
- * Therefore, the first stage is to get the camera's Look Up and
- * Look Right vectors.
- */
- ::RwGetCameraLookUp(m_camera, &up);
- ::RwGetCameraLookRight(m_camera, &right);
-
- /*
- * Unfortunately, rotation about the camera's Look Up and Look Right
- * vectors is complicated if the clump being manipulated is a child
- * clump (i.e. not the root of a clump hierarchy). If this is the
- * case, the camera's vectors have to be transformed into the
- * coordinate space of the parent of the clump being manipulated.
- */
- parent = ::RwGetClumpParent(m_selectedClump);
- if (parent != NULL)
- {
- /*
- * Get a handle to a couple of temporary matrices.
- */
- tmpMatrix = ::RwPushScratchMatrix();
- worldToLocal = ::RwPushScratchMatrix();
-
- /*
- * Get the parent clump's LTM (which maps local coordinates to
- * world space).
- */
- ::RwGetClumpLTM(parent, tmpMatrix);
-
- /*
- * Invert it so that it maps world coordinates to the parent's
- * local coordinate space.
- */
- ::RwInvertMatrix(tmpMatrix, worldToLocal);
-
- /*
- * And transform the camera's vectors into local space.
- */
- ::RwTransformVector(&up, worldToLocal);
- ::RwNormalize(&up);
- ::RwTransformVector(&right, worldToLocal);
- ::RwNormalize(&right);
-
- /*
- * Discard the temporary matrices.
- */
- ::RwPopScratchMatrix();
- ::RwPopScratchMatrix();
- }
-
- ::RwPushScratchMatrix();
-
- /*
- * Apply the rotations.
- */
- ::RwRotateMatrix(::RwScratchMatrix(), up.x, up.y, up.z, yAngle, rwREPLACE);
- ::RwRotateMatrix(::RwScratchMatrix(), right.x, right.y, right.z, xAngle, rwPOSTCONCAT);
-
- /*
- * Apply the resulting, composite transformation to the clump.
- */
- ::RwTransformClumpJoint(m_selectedClump, ::RwScratchMatrix(), rwPOSTCONCAT);
-
- ::RwPopScratchMatrix();
- break;
-
- case rwvDRAGOBJECT:
- GetClumpPositionUnderPointer(m_selectedClump, m_camera, point.x, point.y, &p);
- ::RwGetClumpOrigin(m_selectedClump, &o);
- p.x = RSub(p.x, o.x);
- p.y = RSub(p.y, o.y);
- p.z = RSub(p.z, o.z);
- ::RwPushScratchMatrix();
- ::RwTranslateMatrix(::RwScratchMatrix(), p.x, p.y, p.z, rwREPLACE);
- ::RwTransformClump(m_selectedClump, ::RwScratchMatrix(), rwPOSTCONCAT);
- ::RwPopScratchMatrix();
- break;
- }
-
- m_lastPoint = point;
-
- // Get all views of the document to update. This triggers a rerender. Rather than
- // directly rerendering we let the OnUpdate() message called via this document
- // function to do our rerendering.
- pDoc->UpdateAllViews(NULL);
- }
-
- CView::OnMouseMove(nFlags, point);
- }
-
- void CRwView::OnLButtonUp(UINT nFlags, CPoint point)
- {
- if (m_leftButtonDown)
- {
- switch (m_mouseMode)
- {
- case rwvSPINOBJECT:
- m_mouseMode = rwvNOACTION;
- break;
- }
- m_leftButtonDown = FALSE;
- ReleaseCapture();
- }
-
- CView::OnLButtonUp(nFlags, point);
- }
-
- void CRwView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
- {
- CDC* pDC = GetDC();
- ReRenderView(pDC);
- ReleaseDC(pDC);
- }
-
- void CRwView::ReRenderView(CDC* pDC)
- {
- CRwDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- ::RwBeginCameraUpdate(m_camera, (void *)(DWORD)m_hWnd);
- ::RwClearCameraViewport(m_camera);
- ::RwRenderScene(pDoc->m_scene);
- ::RwEndCameraUpdate(m_camera);
- ::RwShowCameraImage(m_camera, (void*)(DWORD)pDC->m_hDC);
- }
-