189 lines
4.5 KiB
Python
189 lines
4.5 KiB
Python
try:
|
|
from ctypes import c_float, c_int, c_double
|
|
except ImportError:
|
|
pass
|
|
|
|
import pyglet.gl as pgl
|
|
from sympy.core import S
|
|
|
|
|
|
def get_model_matrix(array_type=c_float, glGetMethod=pgl.glGetFloatv):
|
|
"""
|
|
Returns the current modelview matrix.
|
|
"""
|
|
m = (array_type*16)()
|
|
glGetMethod(pgl.GL_MODELVIEW_MATRIX, m)
|
|
return m
|
|
|
|
|
|
def get_projection_matrix(array_type=c_float, glGetMethod=pgl.glGetFloatv):
|
|
"""
|
|
Returns the current modelview matrix.
|
|
"""
|
|
m = (array_type*16)()
|
|
glGetMethod(pgl.GL_PROJECTION_MATRIX, m)
|
|
return m
|
|
|
|
|
|
def get_viewport():
|
|
"""
|
|
Returns the current viewport.
|
|
"""
|
|
m = (c_int*4)()
|
|
pgl.glGetIntegerv(pgl.GL_VIEWPORT, m)
|
|
return m
|
|
|
|
|
|
def get_direction_vectors():
|
|
m = get_model_matrix()
|
|
return ((m[0], m[4], m[8]),
|
|
(m[1], m[5], m[9]),
|
|
(m[2], m[6], m[10]))
|
|
|
|
|
|
def get_view_direction_vectors():
|
|
m = get_model_matrix()
|
|
return ((m[0], m[1], m[2]),
|
|
(m[4], m[5], m[6]),
|
|
(m[8], m[9], m[10]))
|
|
|
|
|
|
def get_basis_vectors():
|
|
return ((1, 0, 0), (0, 1, 0), (0, 0, 1))
|
|
|
|
|
|
def screen_to_model(x, y, z):
|
|
m = get_model_matrix(c_double, pgl.glGetDoublev)
|
|
p = get_projection_matrix(c_double, pgl.glGetDoublev)
|
|
w = get_viewport()
|
|
mx, my, mz = c_double(), c_double(), c_double()
|
|
pgl.gluUnProject(x, y, z, m, p, w, mx, my, mz)
|
|
return float(mx.value), float(my.value), float(mz.value)
|
|
|
|
|
|
def model_to_screen(x, y, z):
|
|
m = get_model_matrix(c_double, pgl.glGetDoublev)
|
|
p = get_projection_matrix(c_double, pgl.glGetDoublev)
|
|
w = get_viewport()
|
|
mx, my, mz = c_double(), c_double(), c_double()
|
|
pgl.gluProject(x, y, z, m, p, w, mx, my, mz)
|
|
return float(mx.value), float(my.value), float(mz.value)
|
|
|
|
|
|
def vec_subs(a, b):
|
|
return tuple(a[i] - b[i] for i in range(len(a)))
|
|
|
|
|
|
def billboard_matrix():
|
|
"""
|
|
Removes rotational components of
|
|
current matrix so that primitives
|
|
are always drawn facing the viewer.
|
|
|
|
|1|0|0|x|
|
|
|0|1|0|x|
|
|
|0|0|1|x| (x means left unchanged)
|
|
|x|x|x|x|
|
|
"""
|
|
m = get_model_matrix()
|
|
# XXX: for i in range(11): m[i] = i ?
|
|
m[0] = 1
|
|
m[1] = 0
|
|
m[2] = 0
|
|
m[4] = 0
|
|
m[5] = 1
|
|
m[6] = 0
|
|
m[8] = 0
|
|
m[9] = 0
|
|
m[10] = 1
|
|
pgl.glLoadMatrixf(m)
|
|
|
|
|
|
def create_bounds():
|
|
return [[S.Infinity, S.NegativeInfinity, 0],
|
|
[S.Infinity, S.NegativeInfinity, 0],
|
|
[S.Infinity, S.NegativeInfinity, 0]]
|
|
|
|
|
|
def update_bounds(b, v):
|
|
if v is None:
|
|
return
|
|
for axis in range(3):
|
|
b[axis][0] = min([b[axis][0], v[axis]])
|
|
b[axis][1] = max([b[axis][1], v[axis]])
|
|
|
|
|
|
def interpolate(a_min, a_max, a_ratio):
|
|
return a_min + a_ratio * (a_max - a_min)
|
|
|
|
|
|
def rinterpolate(a_min, a_max, a_value):
|
|
a_range = a_max - a_min
|
|
if a_max == a_min:
|
|
a_range = 1.0
|
|
return (a_value - a_min) / float(a_range)
|
|
|
|
|
|
def interpolate_color(color1, color2, ratio):
|
|
return tuple(interpolate(color1[i], color2[i], ratio) for i in range(3))
|
|
|
|
|
|
def scale_value(v, v_min, v_len):
|
|
return (v - v_min) / v_len
|
|
|
|
|
|
def scale_value_list(flist):
|
|
v_min, v_max = min(flist), max(flist)
|
|
v_len = v_max - v_min
|
|
return [scale_value(f, v_min, v_len) for f in flist]
|
|
|
|
|
|
def strided_range(r_min, r_max, stride, max_steps=50):
|
|
o_min, o_max = r_min, r_max
|
|
if abs(r_min - r_max) < 0.001:
|
|
return []
|
|
try:
|
|
range(int(r_min - r_max))
|
|
except (TypeError, OverflowError):
|
|
return []
|
|
if r_min > r_max:
|
|
raise ValueError("r_min cannot be greater than r_max")
|
|
r_min_s = (r_min % stride)
|
|
r_max_s = stride - (r_max % stride)
|
|
if abs(r_max_s - stride) < 0.001:
|
|
r_max_s = 0.0
|
|
r_min -= r_min_s
|
|
r_max += r_max_s
|
|
r_steps = int((r_max - r_min)/stride)
|
|
if max_steps and r_steps > max_steps:
|
|
return strided_range(o_min, o_max, stride*2)
|
|
return [r_min] + [r_min + e*stride for e in range(1, r_steps + 1)] + [r_max]
|
|
|
|
|
|
def parse_option_string(s):
|
|
if not isinstance(s, str):
|
|
return None
|
|
options = {}
|
|
for token in s.split(';'):
|
|
pieces = token.split('=')
|
|
if len(pieces) == 1:
|
|
option, value = pieces[0], ""
|
|
elif len(pieces) == 2:
|
|
option, value = pieces
|
|
else:
|
|
raise ValueError("Plot option string '%s' is malformed." % (s))
|
|
options[option.strip()] = value.strip()
|
|
return options
|
|
|
|
|
|
def dot_product(v1, v2):
|
|
return sum(v1[i]*v2[i] for i in range(3))
|
|
|
|
|
|
def vec_sub(v1, v2):
|
|
return tuple(v1[i] - v2[i] for i in range(3))
|
|
|
|
|
|
def vec_mag(v):
|
|
return sum(v[i]**2 for i in range(3))**(0.5)
|