1 /* 2 Copyright (C) 2010-2014 Kristian Duske 3 4 This file is part of TrenchBroom. 5 6 TrenchBroom is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 TrenchBroom is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "CameraTool3D.h" 21 22 #include "Preferences.h" 23 #include "PreferenceManager.h" 24 #include "Model/Brush.h" 25 #include "Model/Entity.h" 26 #include "Model/Group.h" 27 #include "Model/Hit.h" 28 #include "Model/HitAdapter.h" 29 #include "Model/HitQuery.h" 30 #include "Model/PickResult.h" 31 #include "View/InputState.h" 32 #include "View/MapDocument.h" 33 #include "Renderer/PerspectiveCamera.h" 34 35 #include <iostream> 36 37 namespace TrenchBroom { 38 namespace View { CameraTool3D(MapDocumentWPtr document,Renderer::PerspectiveCamera & camera)39 CameraTool3D::CameraTool3D(MapDocumentWPtr document, Renderer::PerspectiveCamera& camera) : 40 ToolControllerBase(), 41 Tool(true), 42 m_document(document), 43 m_camera(camera), 44 m_orbit(false) {} 45 fly(int dx,int dy,const bool forward,const bool backward,const bool left,const bool right,const unsigned int time)46 void CameraTool3D::fly(int dx, int dy, const bool forward, const bool backward, const bool left, const bool right, const unsigned int time) { 47 48 static const float speed = 256.0f / 1000.0f; // 64 units per second 49 const float dist = speed * time; 50 51 Vec3 delta; 52 if (forward) 53 delta += m_camera.direction() * dist; 54 if (backward) 55 delta -= m_camera.direction() * dist; 56 if (left) 57 delta -= m_camera.right() * dist; 58 if (right) 59 delta += m_camera.right() * dist; 60 m_camera.moveBy(delta); 61 62 const float hAngle = static_cast<float>(dx) * lookSpeedH(); 63 const float vAngle = static_cast<float>(dy) * lookSpeedV(); 64 m_camera.rotate(hAngle, vAngle); 65 } 66 doGetTool()67 Tool* CameraTool3D::doGetTool() { 68 return this; 69 } 70 doMouseScroll(const InputState & inputState)71 void CameraTool3D::doMouseScroll(const InputState& inputState) { 72 const float factor = pref(Preferences::CameraMouseWheelInvert) ? -1.0f : 1.0f;; 73 if (m_orbit) { 74 const Plane3f orbitPlane(m_orbitCenter, m_camera.direction()); 75 const float maxDistance = std::max(orbitPlane.intersectWithRay(m_camera.viewRay()) - 32.0f, 0.0f); 76 const float distance = std::min(factor * inputState.scrollY() * moveSpeed(false), maxDistance); 77 m_camera.moveBy(distance * m_camera.direction()); 78 } else if (move(inputState)) { 79 const Vec3f moveDirection = pref(Preferences::CameraMoveInCursorDir) ? Vec3f(inputState.pickRay().direction) : m_camera.direction(); 80 const float distance = inputState.scrollY() * moveSpeed(false); 81 m_camera.moveBy(factor * distance * moveDirection); 82 } 83 } 84 doStartMouseDrag(const InputState & inputState)85 bool CameraTool3D::doStartMouseDrag(const InputState& inputState) { 86 if (orbit(inputState)) { 87 const Model::Hit& hit = inputState.pickResult().query().pickable().type(Model::Brush::BrushHit | Model::Entity::EntityHit | Model::Group::GroupHit).occluded().minDistance(3.0).first(); 88 if (hit.isMatch()) 89 m_orbitCenter = hit.hitPoint(); 90 else 91 m_orbitCenter = inputState.camera().defaultPoint(inputState.pickRay()); 92 m_orbit = true; 93 return true; 94 } else if (look(inputState)) { 95 return true; 96 } else if (pan(inputState)) { 97 return true; 98 } 99 return false; 100 } 101 doMouseDrag(const InputState & inputState)102 bool CameraTool3D::doMouseDrag(const InputState& inputState) { 103 if (m_orbit) { 104 const float hAngle = inputState.mouseDX() * lookSpeedH(); 105 const float vAngle = inputState.mouseDY() * lookSpeedV(); 106 m_camera.orbit(m_orbitCenter, hAngle, vAngle); 107 return true; 108 } else if (look(inputState)) { 109 const float hAngle = inputState.mouseDX() * lookSpeedH(); 110 const float vAngle = inputState.mouseDY() * lookSpeedV(); 111 m_camera.rotate(hAngle, vAngle); 112 return true; 113 } else if (pan(inputState)) { 114 const bool altMove = pref(Preferences::CameraEnableAltMove); 115 Vec3f delta; 116 if (altMove && inputState.modifierKeysPressed(ModifierKeys::MKAlt)) { 117 delta += inputState.mouseDX() * panSpeedH() * m_camera.right(); 118 delta += inputState.mouseDY() * -moveSpeed(altMove) * m_camera.direction(); 119 } else { 120 delta += inputState.mouseDX() * panSpeedH() * m_camera.right(); 121 delta += inputState.mouseDY() * panSpeedV() * m_camera.up(); 122 } 123 m_camera.moveBy(delta); 124 return true; 125 } 126 return false; 127 } 128 doEndMouseDrag(const InputState & inputState)129 void CameraTool3D::doEndMouseDrag(const InputState& inputState) { 130 m_orbit = false; 131 } 132 doCancelMouseDrag()133 void CameraTool3D::doCancelMouseDrag() { 134 m_orbit = false; 135 } 136 move(const InputState & inputState) const137 bool CameraTool3D::move(const InputState& inputState) const { 138 return ((inputState.mouseButtonsPressed(MouseButtons::MBNone) || 139 inputState.mouseButtonsPressed(MouseButtons::MBRight)) && 140 inputState.checkModifierKeys(MK_No, MK_No, MK_No)); 141 } 142 look(const InputState & inputState) const143 bool CameraTool3D::look(const InputState& inputState) const { 144 return (inputState.mouseButtonsPressed(MouseButtons::MBRight) && 145 inputState.modifierKeysPressed(ModifierKeys::MKNone)); 146 } 147 pan(const InputState & inputState) const148 bool CameraTool3D::pan(const InputState& inputState) const { 149 return (inputState.mouseButtonsPressed(MouseButtons::MBMiddle) && 150 (inputState.modifierKeysPressed(ModifierKeys::MKNone) || 151 inputState.modifierKeysPressed(ModifierKeys::MKAlt))); 152 } 153 orbit(const InputState & inputState) const154 bool CameraTool3D::orbit(const InputState& inputState) const { 155 return (inputState.mouseButtonsPressed(MouseButtons::MBRight) && 156 inputState.modifierKeysPressed(ModifierKeys::MKAlt)); 157 } 158 lookSpeedH() const159 float CameraTool3D::lookSpeedH() const { 160 float speed = pref(Preferences::CameraLookSpeed) / -50.0f; 161 if (pref(Preferences::CameraLookInvertH)) 162 speed *= -1.0f; 163 return speed; 164 } 165 lookSpeedV() const166 float CameraTool3D::lookSpeedV() const { 167 float speed = pref(Preferences::CameraLookSpeed) / -50.0f; 168 if (pref(Preferences::CameraLookInvertV)) 169 speed *= -1.0f; 170 return speed; 171 } 172 panSpeedH() const173 float CameraTool3D::panSpeedH() const { 174 float speed = pref(Preferences::CameraPanSpeed); 175 if (pref(Preferences::CameraPanInvertH)) 176 speed *= -1.0f; 177 return speed; 178 } 179 panSpeedV() const180 float CameraTool3D::panSpeedV() const { 181 float speed = pref(Preferences::CameraPanSpeed); 182 if (pref(Preferences::CameraPanInvertV)) 183 speed *= -1.0f; 184 return speed; 185 } 186 moveSpeed(const bool altMode) const187 float CameraTool3D::moveSpeed(const bool altMode) const { 188 float speed = pref(Preferences::CameraMoveSpeed) * 20.0f; 189 // if (slow) 190 // speed /= 10.0f; 191 if (altMode && pref(Preferences::CameraAltMoveInvert)) 192 speed *= -1.0f; 193 return speed; 194 } 195 doCancel()196 bool CameraTool3D::doCancel() { 197 return false; 198 } 199 } 200 } 201