printrun-src/printrun/gl/trackball.py

changeset 15
0bbb006204fc
child 46
cce0af6351f0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/printrun-src/printrun/gl/trackball.py	Fri Jun 03 09:16:07 2016 +0200
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+
+# This file is part of the Printrun suite.
+#
+# Printrun is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Printrun is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Printrun.  If not, see <http://www.gnu.org/licenses/>.
+
+import math
+
+from pyglet.gl import GLdouble
+
+def cross(v1, v2):
+    return [v1[1] * v2[2] - v1[2] * v2[1],
+            v1[2] * v2[0] - v1[0] * v2[2],
+            v1[0] * v2[1] - v1[1] * v2[0]]
+
+def trackball(p1x, p1y, p2x, p2y, r):
+    TRACKBALLSIZE = r
+
+    if p1x == p2x and p1y == p2y:
+        return [0.0, 0.0, 0.0, 1.0]
+
+    p1 = [p1x, p1y, project_to_sphere(TRACKBALLSIZE, p1x, p1y)]
+    p2 = [p2x, p2y, project_to_sphere(TRACKBALLSIZE, p2x, p2y)]
+    a = cross(p2, p1)
+
+    d = map(lambda x, y: x - y, p1, p2)
+    t = math.sqrt(sum(map(lambda x: x * x, d))) / (2.0 * TRACKBALLSIZE)
+
+    if t > 1.0:
+        t = 1.0
+    if t < -1.0:
+        t = -1.0
+    phi = 2.0 * math.asin(t)
+
+    return axis_to_quat(a, phi)
+
+def axis_to_quat(a, phi):
+    lena = math.sqrt(sum(map(lambda x: x * x, a)))
+    q = map(lambda x: x * (1 / lena), a)
+    q = map(lambda x: x * math.sin(phi / 2.0), q)
+    q.append(math.cos(phi / 2.0))
+    return q
+
+def build_rotmatrix(q):
+    m = (GLdouble * 16)()
+    m[0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2])
+    m[1] = 2.0 * (q[0] * q[1] - q[2] * q[3])
+    m[2] = 2.0 * (q[2] * q[0] + q[1] * q[3])
+    m[3] = 0.0
+
+    m[4] = 2.0 * (q[0] * q[1] + q[2] * q[3])
+    m[5] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0])
+    m[6] = 2.0 * (q[1] * q[2] - q[0] * q[3])
+    m[7] = 0.0
+
+    m[8] = 2.0 * (q[2] * q[0] - q[1] * q[3])
+    m[9] = 2.0 * (q[1] * q[2] + q[0] * q[3])
+    m[10] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0])
+    m[11] = 0.0
+
+    m[12] = 0.0
+    m[13] = 0.0
+    m[14] = 0.0
+    m[15] = 1.0
+    return m
+
+
+def project_to_sphere(r, x, y):
+    d = math.sqrt(x * x + y * y)
+    if (d < r * 0.70710678118654752440):
+        return math.sqrt(r * r - d * d)
+    else:
+        t = r / 1.41421356237309504880
+        return t * t / d
+
+
+def mulquat(q1, rq):
+    return [q1[3] * rq[0] + q1[0] * rq[3] + q1[1] * rq[2] - q1[2] * rq[1],
+            q1[3] * rq[1] + q1[1] * rq[3] + q1[2] * rq[0] - q1[0] * rq[2],
+            q1[3] * rq[2] + q1[2] * rq[3] + q1[0] * rq[1] - q1[1] * rq[0],
+            q1[3] * rq[3] - q1[0] * rq[0] - q1[1] * rq[1] - q1[2] * rq[2]]

mercurial