|
try: |
|
from ctypes import c_float |
|
except ImportError: |
|
pass |
|
|
|
import pyglet.gl as pgl |
|
from math import sqrt as _sqrt, acos as _acos, pi |
|
|
|
|
|
def cross(a, b): |
|
return (a[1] * b[2] - a[2] * b[1], |
|
a[2] * b[0] - a[0] * b[2], |
|
a[0] * b[1] - a[1] * b[0]) |
|
|
|
|
|
def dot(a, b): |
|
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] |
|
|
|
|
|
def mag(a): |
|
return _sqrt(a[0]**2 + a[1]**2 + a[2]**2) |
|
|
|
|
|
def norm(a): |
|
m = mag(a) |
|
return (a[0] / m, a[1] / m, a[2] / m) |
|
|
|
|
|
def get_sphere_mapping(x, y, width, height): |
|
x = min([max([x, 0]), width]) |
|
y = min([max([y, 0]), height]) |
|
|
|
sr = _sqrt((width/2)**2 + (height/2)**2) |
|
sx = ((x - width / 2) / sr) |
|
sy = ((y - height / 2) / sr) |
|
|
|
sz = 1.0 - sx**2 - sy**2 |
|
|
|
if sz > 0.0: |
|
sz = _sqrt(sz) |
|
return (sx, sy, sz) |
|
else: |
|
sz = 0 |
|
return norm((sx, sy, sz)) |
|
|
|
rad2deg = 180.0 / pi |
|
|
|
|
|
def get_spherical_rotatation(p1, p2, width, height, theta_multiplier): |
|
v1 = get_sphere_mapping(p1[0], p1[1], width, height) |
|
v2 = get_sphere_mapping(p2[0], p2[1], width, height) |
|
|
|
d = min(max([dot(v1, v2), -1]), 1) |
|
|
|
if abs(d - 1.0) < 0.000001: |
|
return None |
|
|
|
raxis = norm( cross(v1, v2) ) |
|
rtheta = theta_multiplier * rad2deg * _acos(d) |
|
|
|
pgl.glPushMatrix() |
|
pgl.glLoadIdentity() |
|
pgl.glRotatef(rtheta, *raxis) |
|
mat = (c_float*16)() |
|
pgl.glGetFloatv(pgl.GL_MODELVIEW_MATRIX, mat) |
|
pgl.glPopMatrix() |
|
|
|
return mat |
|
|