You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
4.5 KiB

5 months ago
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)