| 1 | /* |
|---|
| 2 | ================================================================================= |
|---|
| 3 | This file is part of Cafu, the open-source game engine and graphics engine |
|---|
| 4 | for multiplayer, cross-platform, real-time 3D action. |
|---|
| 5 | Copyright (C) 2002-2012 Carsten Fuchs Software. |
|---|
| 6 | |
|---|
| 7 | Cafu is free software: you can redistribute it and/or modify it under the terms |
|---|
| 8 | of the GNU General Public License as published by the Free Software Foundation, |
|---|
| 9 | either version 3 of the License, or (at your option) any later version. |
|---|
| 10 | |
|---|
| 11 | Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
|---|
| 12 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
|---|
| 13 | PURPOSE. See the GNU General Public License for more details. |
|---|
| 14 | |
|---|
| 15 | You should have received a copy of the GNU General Public License |
|---|
| 16 | along with Cafu. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 17 | |
|---|
| 18 | For support and more information about Cafu, visit us at <http://www.cafu.de>. |
|---|
| 19 | ================================================================================= |
|---|
| 20 | */ |
|---|
| 21 | |
|---|
| 22 | #ifndef CAFU_GENERIC_3D_WINDOW_HPP_INCLUDED |
|---|
| 23 | #define CAFU_GENERIC_3D_WINDOW_HPP_INCLUDED |
|---|
| 24 | |
|---|
| 25 | #include "Math3D/Plane3.hpp" |
|---|
| 26 | #include "wx/glcanvas.h" |
|---|
| 27 | |
|---|
| 28 | |
|---|
| 29 | class AxesInfoT; |
|---|
| 30 | class CameraT; |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | /// This class implements a generic 3D window. |
|---|
| 34 | /// It provides basic, common 3D window functionality that is independent from any editor. |
|---|
| 35 | class Generic3DWindowT : public wxGLCanvas |
|---|
| 36 | { |
|---|
| 37 | public: |
|---|
| 38 | |
|---|
| 39 | /// This class defines if and how the camera of the associated window is currently being controlled with the mouse. |
|---|
| 40 | class MouseControlT |
|---|
| 41 | { |
|---|
| 42 | public: |
|---|
| 43 | |
|---|
| 44 | enum StateT { NOT_ACTIVE, ACTIVE_NORMAL, ACTIVE_ORBIT }; |
|---|
| 45 | |
|---|
| 46 | MouseControlT(Generic3DWindowT& Win); |
|---|
| 47 | |
|---|
| 48 | /// Activates the mouse control in the given state. |
|---|
| 49 | /// @param NewState The state in which the mouse control should be activated. |
|---|
| 50 | /// @param RefPt The position of the reference point in window coordinates. |
|---|
| 51 | /// Note that if the mouse control is already active, it can not be reactivated in a different ACTIVE_* state but must be deactivated first. |
|---|
| 52 | void Activate(StateT NewState, const wxPoint& RefPt=wxDefaultPosition); |
|---|
| 53 | |
|---|
| 54 | /// Deactivates the mouse control. |
|---|
| 55 | void Deactivate(); |
|---|
| 56 | |
|---|
| 57 | /// Returns the state that the mouse control is currently in. |
|---|
| 58 | StateT GetState() const { return m_State; } |
|---|
| 59 | |
|---|
| 60 | /// Returns whether the mouse control is active; a shortcut for GetState()!=NOT_ACTIVE. |
|---|
| 61 | bool IsActive() const { return m_State!=NOT_ACTIVE; } |
|---|
| 62 | |
|---|
| 63 | /// Return the position of the reference point in window coordinates as set when the mouse control was activated. |
|---|
| 64 | const wxPoint& GetRefPtWin() const { return m_RefPtWin; } |
|---|
| 65 | |
|---|
| 66 | /// Return the position of the reference point in world coordinates as set when the mouse control was activated. |
|---|
| 67 | const Vector3fT& GetRefPtWorld() const { return m_RefPtWorld; } |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | private: |
|---|
| 71 | |
|---|
| 72 | Generic3DWindowT& m_Win; ///< The 3D window that this is the mouse control for. |
|---|
| 73 | StateT m_State; ///< The current state of the mouse control. |
|---|
| 74 | wxPoint m_RefPtWin; ///< The position of the reference point in window coordinates as set when the mouse control was activated. |
|---|
| 75 | Vector3fT m_RefPtWorld; ///< The position of the reference point in world coordinates as set when the mouse control was activated. |
|---|
| 76 | }; |
|---|
| 77 | |
|---|
| 78 | |
|---|
| 79 | /// The constructor. |
|---|
| 80 | Generic3DWindowT(wxWindow* Parent, CameraT* InitialCamera); |
|---|
| 81 | |
|---|
| 82 | /// The destructor. |
|---|
| 83 | ~Generic3DWindowT(); |
|---|
| 84 | |
|---|
| 85 | /// Returns the set of axes that the camera orientation is currently the closest to. |
|---|
| 86 | AxesInfoT GetAxesInfo() const; |
|---|
| 87 | |
|---|
| 88 | /// Returns the camera that is currently associated with this window. |
|---|
| 89 | const CameraT& GetCamera() const { return *m_Camera; } |
|---|
| 90 | |
|---|
| 91 | /// Sets Camera as the new camera to use for this window. |
|---|
| 92 | void SetCamera(CameraT* Camera); |
|---|
| 93 | |
|---|
| 94 | /// Moves the camera that is currently associated with this window to the given new position. |
|---|
| 95 | void MoveCamera(const Vector3fT& NewPos); |
|---|
| 96 | |
|---|
| 97 | /// Processes the user input for the (last) frame with the given duration and updates the camera accordingly. |
|---|
| 98 | void ProcessInput(float FrameTime); |
|---|
| 99 | |
|---|
| 100 | /// Returns the mouse control instance of this window. |
|---|
| 101 | const MouseControlT& GetMouseControl() const { return m_MouseControl; } |
|---|
| 102 | |
|---|
| 103 | /// Returns the view frustum for this window, based on its current window dimensions and camera setting. |
|---|
| 104 | void GetViewFrustum(Plane3fT* Planes, unsigned int NumPlanes=6) const; |
|---|
| 105 | |
|---|
| 106 | /// Transforms (unprojects) the given pixel from window space to the related point in world space. |
|---|
| 107 | /// The returned point is located on the near clipping plane of this windows view pyramid/frustum. |
|---|
| 108 | /// Therefore, "camera rays" are conveniently built through the two points GetCamera().Pos and WindowToWorld(Pixel). |
|---|
| 109 | /// This method is "roughly" the inverse of WorldToWindow(). |
|---|
| 110 | /// @param Pixel The pixel to convert from window to world space. |
|---|
| 111 | /// @returns the pixel in world space coordinates. |
|---|
| 112 | Vector3fT WindowToWorld(const wxPoint& Pixel) const; |
|---|
| 113 | |
|---|
| 114 | /// Transforms (projects) the given point from world space to the related pixel in the 3D window. |
|---|
| 115 | /// The transformation is not always reasonably possible, and therefore, if CheckFrustum is true (recommended), |
|---|
| 116 | /// the method checks whether v is inside the view frustum first and returns (-1, -1) otherwise. |
|---|
| 117 | /// If CheckFrustum is false, no view-frustum check is performed, with the potential negative consequences |
|---|
| 118 | /// that can occur when performing the transformation stubbornly (divisions-by-zero, point behind the |
|---|
| 119 | /// viewer yields valid window coordinates, etc.). This method is "roughly" the inverse of WindowToWorld(). |
|---|
| 120 | /// @param v The point to be transformed from world to window coordinates. |
|---|
| 121 | /// @param CheckFrustum Whether v should be tested against the current view frustum before the transformation. |
|---|
| 122 | /// @returns the transformed point, or (-1, -1) if CheckFrustum was true and the v failed the test. |
|---|
| 123 | wxPoint WorldToWindow(const Vector3fT& v, bool CheckFrustum) const; |
|---|
| 124 | |
|---|
| 125 | |
|---|
| 126 | private: |
|---|
| 127 | |
|---|
| 128 | // Methods that derived classes (cannot call, but) must implement. |
|---|
| 129 | virtual Vector3fT GetRefPtWorld(const wxPoint& RefPtWin) const=0; |
|---|
| 130 | virtual void InfoCameraChanged()=0; |
|---|
| 131 | virtual void InfoRightMouseClick(wxMouseEvent& ME)=0; |
|---|
| 132 | |
|---|
| 133 | enum RightMBStateT { RMB_UP_IDLE, RMB_DOWN_UNDECIDED, RMB_DOWN_DRAGGING }; ///< This enumeration describes the states that the right mouse button can take. |
|---|
| 134 | |
|---|
| 135 | CameraT* m_Camera; ///< Pointer to the camera that is currently used for this 3D window. The actual instance of the camera is kept in and owned by the caller (i.e. the owner of the window instance). |
|---|
| 136 | Vector3fT m_CameraVel; ///< The cameras current velocity, in camera space. Positive values for m_CameraVel.y mean forward movement, etc. |
|---|
| 137 | MouseControlT m_MouseControl; ///< If and how the camera of this window is currently being controlled with the mouse. |
|---|
| 138 | RightMBStateT m_RightMBState; ///< The state of the right mouse button. This is required because the RMB has a dual function: a click can bring up the context menu, or initiate mouse-looking for the 3D window. |
|---|
| 139 | wxPoint m_RDownPosWin; ///< The point where the RMB went down, in window coordinates. |
|---|
| 140 | |
|---|
| 141 | // Event handlers. |
|---|
| 142 | void OnKeyDown (wxKeyEvent& ME); |
|---|
| 143 | void OnKeyUp (wxKeyEvent& ME); |
|---|
| 144 | void OnMouseMiddleDown (wxMouseEvent& ME); ///< We also handle "double-click" events in this method (use ME.ButtonDClick() for distinction). |
|---|
| 145 | void OnMouseMiddleUp (wxMouseEvent& ME); |
|---|
| 146 | void OnMouseRightDown (wxMouseEvent& ME); ///< We also handle "double-click" events in this method (use ME.ButtonDClick() for distinction). |
|---|
| 147 | void OnMouseRightUp (wxMouseEvent& ME); |
|---|
| 148 | void OnMouseWheel (wxMouseEvent& ME); |
|---|
| 149 | void OnMouseMove (wxMouseEvent& ME); |
|---|
| 150 | void OnKillFocus (wxFocusEvent& FE); |
|---|
| 151 | void OnMouseCaptureLost(wxMouseCaptureLostEvent& ME); |
|---|
| 152 | |
|---|
| 153 | DECLARE_EVENT_TABLE() |
|---|
| 154 | }; |
|---|
| 155 | |
|---|
| 156 | #endif |
|---|