Переглянути джерело

Fixed Camera Z rotation bug

Thomas Buck 10 роки тому
джерело
коміт
b4360d62d2
3 змінених файлів з 41 додано та 30 видалено
  1. 2
    0
      ChangeLog.md
  2. 3
    4
      include/Camera.h
  3. 36
    26
      src/Camera.cpp

+ 2
- 0
ChangeLog.md Переглянути файл

@@ -5,6 +5,8 @@
5 5
     [ 20140108 ]
6 6
     * FPS and Camera position now displayed in imgui Overlay
7 7
     * Removed many unnecessary includes
8
+    * Camera now using combination of quaternion and X/Y angle.
9
+        * Fixes strange bug that sometimes rotated Camera on Z Axis.
8 10
 
9 11
     [ 20140107 ]
10 12
     * Fixed problems with FontTTFs Glyph Baseline

+ 3
- 4
include/Camera.h Переглянути файл

@@ -8,7 +8,6 @@
8 8
 #ifndef _CAMERA_H_
9 9
 #define _CAMERA_H_
10 10
 
11
-#include <glm/gtc/quaternion.hpp>
12 11
 #include <glm/gtc/type_precision.hpp>
13 12
 
14 13
 #include "RoomData.h"
@@ -26,9 +25,9 @@ class Camera {
26 25
 
27 26
     //! \fixme The Y axis seems to be the source of all evil?
28 27
     static void setPosition(glm::vec3 p) { pos = glm::vec3(p.x, -p.y, p.z); }
29
-    static glm::vec3 getPosition() { return glm::vec3(pos.x, -pos.y, pos.z); }
28
+    static glm::vec3 getPosition() { return pos; }
30 29
 
31
-    static glm::vec2 getRotation();
30
+    static glm::vec2 getRotation() { return rot; }
32 31
     static glm::mat4 getProjectionMatrix() { return projection; }
33 32
     static glm::mat4 getViewMatrix() { return view; }
34 33
 
@@ -48,7 +47,7 @@ class Camera {
48 47
     static void calculateFrustumPlanes();
49 48
 
50 49
     static glm::vec3 pos;
51
-    static glm::quat quaternion;
50
+    static glm::vec2 rot;
52 51
     static glm::vec3 posSpeed;
53 52
     static glm::vec2 rotSpeed;
54 53
     static glm::mat4 projection;

+ 36
- 26
src/Camera.cpp Переглянути файл

@@ -16,6 +16,7 @@
16 16
 
17 17
 #include <glm/gtc/epsilon.hpp>
18 18
 #include <glm/gtc/matrix_transform.hpp>
19
+#include <glm/gtc/quaternion.hpp>
19 20
 #include <glm/gtx/quaternion.hpp>
20 21
 
21 22
 static bool equal(float a, float b) {
@@ -36,7 +37,7 @@ const static float fov = 45.0f;
36 37
 const static float nearDist = 0.1f;
37 38
 const static float farDist = 75000.0f;
38 39
 const static float maxSpeed = 2048.0f;
39
-const static float controllerViewFactor = 384.0f;
40
+const static float controllerViewFactor = glm::pi<float>();
40 41
 const static float controllerDeadZone = 0.1f;
41 42
 
42 43
 const static glm::vec3 rightUnit(1.0f, 0.0f, 0.0f);
@@ -44,7 +45,7 @@ const static glm::vec3 upUnit(0.0f, 1.0f, 0.0f);
44 45
 const static glm::vec3 dirUnit(0.0f, 0.0f, -1.0f);
45 46
 
46 47
 glm::vec3 Camera::pos(0.0f, 0.0f, 0.0f);
47
-glm::quat Camera::quaternion(glm::vec3(0.0f, 0.0f, 0.0f));
48
+glm::vec2 Camera::rot(glm::pi<float>(), 0.0f);
48 49
 glm::vec3 Camera::posSpeed(0.0f, 0.0f, 0.0f);
49 50
 glm::vec2 Camera::rotSpeed(0.0f, 0.0f);
50 51
 glm::mat4 Camera::projection(1.0f);
@@ -56,7 +57,7 @@ bool Camera::dirty = true;
56 57
 
57 58
 void Camera::reset() {
58 59
     pos = glm::vec3(0.0f, 0.0f, 0.0f);
59
-    quaternion = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f));
60
+    rot = glm::vec2(glm::pi<float>(), 0.0f);
60 61
     posSpeed = glm::vec3(0.0f, 0.0f, 0.0f);
61 62
     rotSpeed = glm::vec2(0.0f, 0.0f);
62 63
     dirty = true;
@@ -96,23 +97,38 @@ void Camera::handleAction(ActionEvents action, bool isFinished) {
96 97
 }
97 98
 
98 99
 void Camera::handleMouseMotion(int x, int y) {
99
-    if (x != 0) {
100
-        quaternion = glm::quat(upUnit * (rotationDeltaX * x)) * quaternion;
100
+    if ((x != 0) || (y != 0))
101 101
         dirty = true;
102
+
103
+    while (x > 0) {
104
+        rot.x += rotationDeltaX;
105
+        x--;
106
+    }
107
+
108
+    while (x < 0) {
109
+        rot.x -= rotationDeltaX;
110
+        x++;
102 111
     }
103 112
 
104
-    if (y != 0) {
105
-        static int lastDir = 0;
106
-        float a = glm::dot(upUnit, quaternion * upUnit);
107
-        if (((lastDir >= 0) && (y < 0)) || ((lastDir <= 0) && (y > 0)) || (a > 0.5f)) {
108
-            quaternion = glm::quat(quaternion * -rightUnit * (rotationDeltaY * y)) * quaternion;
109
-            dirty = true;
113
+    while (y > 0) {
114
+        if (rot.y > -(glm::pi<float>() / 2.0f)) {
115
+            rot.y -= rotationDeltaY;
116
+        }
117
+        y--;
118
+    }
110 119
 
111
-            // TODO find better way to clamp Y rotation axis!
112
-            if (a > 0.5f)
113
-                lastDir = y;
120
+    while (y < 0) {
121
+        if (rot.y < (glm::pi<float>() / 2.0f)) {
122
+            rot.y += rotationDeltaY;
114 123
         }
124
+        y++;
115 125
     }
126
+
127
+    while (rot.x > (glm::pi<float>() * 2.0f))
128
+        rot.x -= glm::pi<float>() * 2.0f;
129
+
130
+    while (rot.x < -(glm::pi<float>() * 2.0f))
131
+        rot.x += glm::pi<float>() * 2.0f;
116 132
 }
117 133
 
118 134
 void Camera::handleControllerAxis(float value, KeyboardButton axis) {
@@ -128,7 +144,7 @@ void Camera::handleControllerAxis(float value, KeyboardButton axis) {
128 144
     } else if (axis == rightXAxis) {
129 145
         rotSpeed.x = controllerViewFactor * value;
130 146
     } else if (axis == rightYAxis) {
131
-        rotSpeed.y = controllerViewFactor * value;
147
+        rotSpeed.y = -controllerViewFactor * value;
132 148
     } else {
133 149
         return;
134 150
     }
@@ -161,13 +177,13 @@ bool Camera::update() {
161 177
         return false;
162 178
 
163 179
     float dT = RunTime::getLastFrameTime();
164
-    pos += quaternion * posSpeed * dT;
180
+    rot += rotSpeed * dT;
165 181
 
166
-    if (glm::epsilonNotEqual(rotSpeed.x, 0.0f, controllerDeadZone))
167
-        quaternion = glm::quat(upUnit * rotationDeltaX * rotSpeed.x * dT) * quaternion;
182
+    glm::quat quatY = glm::angleAxis(rot.x, glm::vec3(0.0f, 1.0f, 0.0f));
183
+    glm::quat quatX = glm::angleAxis(rot.y, glm::vec3(1.0f, 0.0f, 0.0f));
184
+    glm::quat quaternion = quatY * quatX;
168 185
 
169
-    if (glm::epsilonNotEqual(rotSpeed.y, 0.0f, controllerDeadZone))
170
-        quaternion = glm::quat(quaternion * -rightUnit * rotationDeltaY * rotSpeed.y * dT) * quaternion;
186
+    pos += quaternion * posSpeed * dT;
171 187
 
172 188
     glm::mat4 translate = glm::translate(glm::mat4(1.0f), pos);
173 189
     glm::mat4 rotate = glm::toMat4(quaternion);
@@ -180,12 +196,6 @@ bool Camera::update() {
180 196
     return updateViewFrustum;
181 197
 }
182 198
 
183
-glm::vec2 Camera::getRotation() {
184
-    float x = glm::dot(dirUnit, quaternion * dirUnit);
185
-    float y = glm::dot(upUnit, quaternion * upUnit);
186
-    return glm::vec2(x, y);
187
-}
188
-
189 199
 // ----------------------------------------------------------------------------
190 200
 
191 201
 class FrustumPlane {

Завантаження…
Відмінити
Зберегти