Skip to content

Instantly share code, notes, and snippets.

@wkentaro
Last active April 19, 2019 17:02
Show Gist options
  • Save wkentaro/ff4b804df77d8292fdb7043c3e2489f9 to your computer and use it in GitHub Desktop.
Save wkentaro/ff4b804df77d8292fdb7043c3e2489f9 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import pyglet
import glooey
import trimesh
from math import pi
from pyglet.gl import *
class SceneGroup(pyglet.graphics.Group):
def __init__(self, rect, parent=None):
super().__init__(parent)
self.rect = rect
def set_state(self):
glPushAttrib(GL_ENABLE_BIT)
glEnable(GL_SCISSOR_TEST)
glScissor(
int(self.rect.left),
int(self.rect.bottom),
int(self.rect.width),
int(self.rect.height),
)
self._mode = (GLint)()
glGetIntegerv(GL_MATRIX_MODE, self._mode)
self._viewport = (GLint * 4)()
glGetIntegerv(GL_VIEWPORT, self._viewport)
left, bottom = int(self.rect.left), int(self.rect.bottom)
width, height = int(self.rect.width), int(self.rect.height)
glViewport(left, bottom, width, height)
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
gluPerspective(60, width / height, 0.01, 1000.0)
glMatrixMode(GL_MODELVIEW)
self._enable_depth()
self._enable_color_material()
self._enable_blending()
self._enable_smooth_lines()
self._enable_lighting()
self._clear_buffers()
def unset_state(self):
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(self._mode.value)
glViewport(
self._viewport[0],
self._viewport[1],
self._viewport[2],
self._viewport[3],
)
glPopAttrib()
def _enable_depth(self):
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glDepthRange(0.0, 100.0)
glDepthFunc(GL_LEQUAL)
glClearDepth(1.0)
def _enable_color_material(self):
from trimesh.rendering import vector_to_gl as v
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glShadeModel(GL_SMOOTH)
glMaterialfv(GL_FRONT, GL_AMBIENT, v(0.192250, 0.192250, 0.192250))
glMaterialfv(GL_FRONT, GL_DIFFUSE, v(0.507540, 0.507540, 0.507540))
glMaterialfv(GL_FRONT, GL_SPECULAR, v(0.5082730, .5082730, .5082730))
glMaterialf(GL_FRONT, GL_SHININESS, 0.4 * 128.0)
def _enable_blending(self):
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
def _enable_smooth_lines(self):
# Make things generally less ugly.
glEnable(GL_LINE_SMOOTH)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
glLineWidth(1.5)
glPointSize(4)
def _enable_lighting(self):
from trimesh.rendering import vector_to_gl as v
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_AMBIENT, v(0.5, 0.5, 0.5, 1.0))
glLightfv(GL_LIGHT0, GL_DIFFUSE, v(1.0, 1.0, 1.0, 1.0))
glLightfv(GL_LIGHT0, GL_SPECULAR, v(1.0, 1.0, 1.0, 1.0))
glLightfv(GL_LIGHT0, GL_POSITION, v(0.0, 0.0, 0.0, 1.0))
def _clear_buffers(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
class SpinGroup(pyglet.graphics.Group):
# This group just rotates things along the y-axis. It's not really
# necessary, but it was helpful for me when debugging.
def __init__(self, parent=None):
super().__init__(parent)
self.angle_radians = 0
def set_state(self):
from trimesh.rendering import matrix_to_gl
from trimesh.transformations import \
translation_matrix, rotation_matrix, concatenate_matrices
glPushMatrix()
glLoadIdentity()
T = translation_matrix([0, 0, -10])
R = rotation_matrix(self.angle_radians, [0, 1, 0])
M = concatenate_matrices(T, R)
glMultMatrixf(matrix_to_gl(M))
def unset_state(self):
glPopMatrix()
class SceneWidget(glooey.Widget):
# I suppose this should take a scene object rather than a mesh, but I
# couldn't really figure out how to make a scene object.
def __init__(self, mesh):
super().__init__()
self.mesh = mesh
self.vertex_list = None
self.spin_group = None
def do_attach(self):
pyglet.clock.schedule_interval(self.on_update, 1/60)
def do_detach(self):
pyglet.clock.unschedule(self.on_update)
def do_claim(self):
return 0, 0
def do_regroup(self):
if self.vertex_list is not None:
self.spin_group = SpinGroup(
SceneGroup(rect=self.rect, parent=self.group)
)
self.batch.migrate(
self.vertex_list, GL_TRIANGLES,
self.spin_group, self.batch,
)
def do_draw(self):
from trimesh.rendering import mesh_to_vertexlist
# Because the vertex list can't change, we don't need to do anything if
# the vertex list is already set.
if self.vertex_list is None:
self.spin_group = SpinGroup(
SceneGroup(rect=self.rect, parent=self.group)
)
args = mesh_to_vertexlist(self.mesh, group=self.spin_group)
self.vertex_list = self.batch.add_indexed(*args)
def do_undraw(self):
if self.vertex_list is not None:
self.vertex_list.delete()
self.vertex_list = None
def on_update(self, dt):
if self.spin_group:
self.spin_group.angle_radians += (2 * pi / 8) * dt
self._draw()
if __name__ == '__main__':
window = pyglet.window.Window(width=1280, height=480)
gui = glooey.Gui(window)
hbox = glooey.HBox()
# hbox.add(glooey.Placeholder(min_width=640, min_height=480))
mesh = trimesh.creation.annulus(0.2, 1, 0.2)
scene = SceneWidget(mesh)
hbox.add(scene)
mesh = trimesh.creation.axis(0.3)
scene = SceneWidget(mesh)
hbox.add(scene)
# hbox.add(glooey.Placeholder(min_width=640, min_height=480))
gui.add(hbox)
pyglet.app.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment