def ringsearch(self): '''find best seam for a mesh around input pivot vec the width of each ring is 1.35 times longest input mesh edge:edgestep call find closestedge to limit the ring span use findbestseam to position the seam in the limited span''' result = [] fl, fr, segs = self.buildsearchfrustums() for i in range(segs): visible = [] for f in (fl, fr): edgerange = self.findclosestedge( i / float(segs), f ) visible.append( edgerange ) if visible[0] is None or visible[1] is None: continue seam = self.findbestseam( visible ) if seam is not None: score, dummy, pivot, hi, vis = seam pole = self.mesh.points[hi] mid = self.mesh.points[pivot] f = Frustum() f.ctw = num.vecspace2( pole, mid ) result.append( (score, vis, f) ) return result
def __init__(self, engine_ref): super().__init__() self.engine = engine_ref self.frustum = Frustum() self.inverse_matrix = matrix4.Matrix4() self.perspective_matrix = matrix4.Matrix4() self.inv_perspective_matrix = matrix4.Matrix4() self.fov = 0 self.inverse_matrix.set_identity() self.perspective_matrix.set_identity()
def randfrustums( n, scl, solver, squish=None, seedstart=0 ): 'randomly distributed view frustums' mindimension = solver.mesh.edgestats()[2] result = [] for i in xrange(n): f = Frustum.rand( scl, i + seedstart, mindimension, squish) result.append( f ) return result
def buildsearchfrustums( self ): ''' left and right hand ortho views that approximate a half circle of verts input mesh edges are not aligned to view so add some tolerance: top/bottom edges make a frustrum 1.5 times bigger wrt longest edge outer edge is beyond the edge of the sphere inner edge is just slightly overlapping to capture the center point ''' hi = self.mesh.edgestats()[2] near = .9 far = 3.1 right = 1.1 left = hi * self.slicetolerance_end top = hi * self.slicetolerance_halfwidth fl = Frustum().lrtbnf( ( -right, left, -top, top, near, far ) ) fr = Frustum().lrtbnf( ( left, right, -top, top, near, far ) ) fl.orthographic() fr.orthographic() edgestep = hi * 1.35 segs = int(math.ceil((math.pi)/edgestep)) return fl, fr, segs
class Logger: events = [ ('container-start', 'info', 'Container {} is executing'), ('container-end', 'info', 'Container {} has finished executing'), ('story-start', 'info', 'Start processing story "{}" with id {}'), ('story-save', 'info', 'Saved results of story "{}"'), ('story-end', 'info', 'Finished processing story "{}" with id {}'), ('container-volume', 'debug', 'Created volume {}'), ('lexicon-if', 'debug', 'Processing line {} with "if" method against context {}'), ('story-execution', 'debug', 'Received line "{}" from handler'), ('story-resolve', 'debug', 'Resolved "{}" to "{}"'), ('lexicon-unless', 'debug', 'Processing line {} with "unless" method against context {}'), ('service-init', 'info', 'Starting Asyncy version {}'), ('http-init', 'info', 'HTTP server bound to port {}'), ('http-request-run-story', 'debug', 'Received run request for story {} via HTTP'), ] def __init__(self, config): self.frustum = Frustum(config.LOGGER_NAME, config.LOGGER_LEVEL) def adapter(self, app_id, version): return Adapter(self.frustum.logger, { 'app_id': app_id, 'version': version }) def start(self): for event in self.events: self.frustum.register_event(event[0], event[1], event[2]) self.frustum.start_logger() if log_json: self.set_json_formatter() def set_json_formatter(self): log_handler = StreamHandler() formatter = JSONFormatter() log_handler.setFormatter(formatter) self.frustum.logger.addHandler(log_handler) self.frustum.logger.propagate = False def adapt(self, app_id, version): self.frustum.logger = self.adapter(app_id, version) def log(self, event, *args): self.frustum.log(event, *args) def info(self, message): getattr(self.frustum.logger, 'info')(message) def debug(self, message): getattr(self.frustum.logger, 'debug')(message) def error(self, message, exc=None): getattr(self.frustum.logger, 'error')(message, exc_info=exc) def warn(self, message): getattr(self.frustum.logger, 'warning')(message)
def __init__(self, config): self.frustum = Frustum(config.LOGGER_NAME, config.LOGGER_LEVEL)
class Camera(Transform): def __init__(self, engine_ref): super().__init__() self.engine = engine_ref self.frustum = Frustum() self.inverse_matrix = matrix4.Matrix4() self.perspective_matrix = matrix4.Matrix4() self.inv_perspective_matrix = matrix4.Matrix4() self.fov = 0 self.inverse_matrix.set_identity() self.perspective_matrix.set_identity() #derived from transform, needs to be adjusted def rebuild_matrix(self): self.result_matrix = self.rotation_matrix * self.position_matrix self.inverse_matrix = self.result_matrix.get_rt_inverse_matrix() self.need_update = False self.frustum.extract_frustum_planes(self.perspective_matrix * self.result_matrix) if self.parent != None: self.result_matrix = self.parent.get_transformation_matrix( ) * self.result_matrix for child in self.childs: child.rebuild_matrix() #derived from transform, needs to be adjusted def set_local_position(self, position): self.position = position self.position_matrix.set_translation(-position.x, -position.y, -position.z) self.need_update = True def get_parent_matrix(self): return self.inverse_matrix def get_frustum(self): return self.frustum # https://antongerdelan.net/opengl/raycasting.html def get_mouse_direction(self): mx, my = self.key_mapper.get_mouse_position() width, height = self.engine.get_size() nx = mx / width ny = my / height nx = nx * 2.0 - 1.0 ny = ny * 2.0 - 1.0 ray_clip = vector3.Vector3(nx, ny, -1.0) ray_eye = self.inv_perspective_matrix.mul_vec3(ray_clip, 1.0) ray_eye.z = -1.0 ray_world = self.inverse_matrix.mul_vec3(ray_eye, 0.0) return ray_world def set_perspective_matrix(self, fov, aspect, near_plane, far_plane): self.fov = fov self.perspective_matrix.set_perspective_matrix(fov, aspect, near_plane, far_plane) self.inv_perspective_matrix = self.perspective_matrix.get_inverse() def get_perspective_matrix(self): return self.perspective_matrix
def __init__(self ): 'init gl context ui elements, calls setup to be a gl mesh to draw' config = pyglet.gl.Config(sample_buffers=1, samples=4, depth_size=24, double_buffer=True, red_size=8, blue_size=8, green_size=8, alpha_size=8 ) try: pyglet.window.Window.__init__(self, caption='seam', visible=False, resizable=True, config=config) except: pyglet.window.Window.__init__(self, caption='seam', visible=False, resizable=True) self.solverkindbutton = controls.TextButton(self) self.solverkindbutton.on_press = self.togglesolverkind self.squishscaleslider = controls.Slider(self) self.squishscaleslider.value = .1 self.squishscaleslider.min = 0 self.squishscaleslider.max = 1 self.squishscaleslider.on_change = self.squishscalescroll self.seedslider = controls.Slider(self) self.seedslider.value = 0 self.seedslider.min = 0 self.seedslider.max = 10000 self.seedslider.on_change = self.seedscroll self.unwrapslider = controls.Slider(self) self.unwrapslider.value = 100 self.unwrapslider.min = 0 self.unwrapslider.max = 100 self.unwrapslider.on_change = self.scroll self.fillemodebutton = controls.TextButton(self) self.fillemodebutton.on_press = self.togglefillmode self.showaxisbutton = controls.TextButton(self) self.showaxisbutton.on_press = self.toggleaxis self.cutseambutton = controls.TextButton(self) self.cutseambutton.on_press = self.toggleseam self.cutseambutton.text = 'cut' self.runbutton = controls.TextButton(self) self.runbutton.on_press = self.run self.runbutton.text = 'run' #self.fps_display = pyglet.clock.ClockDisplay() self.controls = [ self.unwrapslider ,self.fillemodebutton ,self.showaxisbutton ,self.cutseambutton ,self.seedslider ,self.squishscaleslider ,self.runbutton ,self.solverkindbutton ] for i, control in enumerate(self.controls): control.width = self.BUTTON_WIDTH control.height = self.BUTTON_HEIGHT control.x = self.PADDING control.y = self.PADDING * (i+1) + self.BUTTON_HEIGHT * i self.manipstate = None self.manipstart = None self.viewtransform = TransformGL() self.viewtransform.sx = .5 self.viewtransform.sy = .5 self.viewtransform.sz = .5 self.viewtransform.tx = .8 self.viewtransform.ty = -.2 self.manipviewtransform = None self.mousescreen = vecutil.vec3() self.mouseworld = vecutil.vec3() self.pole = vecutil.vec3(0, 0, 1) self.manippole = None self.spin = vecutil.vec3(-1, 0, 0) self.manipspin = None self.mesh = None self.solver = None self.solverdirty = True self.view = Frustum().rtnf(( 1, 1, -5, 5 )).orthographic() self.view.ctw = vecutil.mat4() self.zup = TransformGL() self.zup._order = ( self.zup.kscale ,self.zup.kxrotate ,self.zup.kyrotate ,self.zup.kzrotate ,self.zup.ktranslate ) self.zup.ry = math.radians( -90 ) self.zup.rx = math.radians( -90 ) self.solverkind = 0 self.solverkinds = SeamSolver.kzup, SeamSolver.kplane, SeamSolver.kfree self.solverkindnames = 'zup', 'plane', 'free' self.solverkindbutton.text = self.solverkindnames[self.solverkind] self.fillmode = 1 self.fillmodes = gl.GL_LINE, gl.GL_FILL, gl.GL_POINT self.fillmodenames = 'lines', 'solid', 'pnts' self.fillemodebutton.text = self.fillmodenames[self.fillmode] self.showaxis = False self.showaxisnames = '!xyz','xyz' self.showaxisbutton.text = self.showaxisnames[ self.showaxis ] self.setup()
class ViewerWindow(pyglet.window.Window): 'viewer window handles all ui events and most drawing' PADDING = 4 BUTTON_HEIGHT = 16 BUTTON_WIDTH = 45 _width = 640 _height = 480 kpan = 'kpan' kzoom = 'kzoom' korbit = 'korbit' kpolemanip = 'kpolemanip' kspinmanip = 'kspinmanip' def __init__(self ): 'init gl context ui elements, calls setup to be a gl mesh to draw' config = pyglet.gl.Config(sample_buffers=1, samples=4, depth_size=24, double_buffer=True, red_size=8, blue_size=8, green_size=8, alpha_size=8 ) try: pyglet.window.Window.__init__(self, caption='seam', visible=False, resizable=True, config=config) except: pyglet.window.Window.__init__(self, caption='seam', visible=False, resizable=True) self.solverkindbutton = controls.TextButton(self) self.solverkindbutton.on_press = self.togglesolverkind self.squishscaleslider = controls.Slider(self) self.squishscaleslider.value = .1 self.squishscaleslider.min = 0 self.squishscaleslider.max = 1 self.squishscaleslider.on_change = self.squishscalescroll self.seedslider = controls.Slider(self) self.seedslider.value = 0 self.seedslider.min = 0 self.seedslider.max = 10000 self.seedslider.on_change = self.seedscroll self.unwrapslider = controls.Slider(self) self.unwrapslider.value = 100 self.unwrapslider.min = 0 self.unwrapslider.max = 100 self.unwrapslider.on_change = self.scroll self.fillemodebutton = controls.TextButton(self) self.fillemodebutton.on_press = self.togglefillmode self.showaxisbutton = controls.TextButton(self) self.showaxisbutton.on_press = self.toggleaxis self.cutseambutton = controls.TextButton(self) self.cutseambutton.on_press = self.toggleseam self.cutseambutton.text = 'cut' self.runbutton = controls.TextButton(self) self.runbutton.on_press = self.run self.runbutton.text = 'run' #self.fps_display = pyglet.clock.ClockDisplay() self.controls = [ self.unwrapslider ,self.fillemodebutton ,self.showaxisbutton ,self.cutseambutton ,self.seedslider ,self.squishscaleslider ,self.runbutton ,self.solverkindbutton ] for i, control in enumerate(self.controls): control.width = self.BUTTON_WIDTH control.height = self.BUTTON_HEIGHT control.x = self.PADDING control.y = self.PADDING * (i+1) + self.BUTTON_HEIGHT * i self.manipstate = None self.manipstart = None self.viewtransform = TransformGL() self.viewtransform.sx = .5 self.viewtransform.sy = .5 self.viewtransform.sz = .5 self.viewtransform.tx = .8 self.viewtransform.ty = -.2 self.manipviewtransform = None self.mousescreen = vecutil.vec3() self.mouseworld = vecutil.vec3() self.pole = vecutil.vec3(0, 0, 1) self.manippole = None self.spin = vecutil.vec3(-1, 0, 0) self.manipspin = None self.mesh = None self.solver = None self.solverdirty = True self.view = Frustum().rtnf(( 1, 1, -5, 5 )).orthographic() self.view.ctw = vecutil.mat4() self.zup = TransformGL() self.zup._order = ( self.zup.kscale ,self.zup.kxrotate ,self.zup.kyrotate ,self.zup.kzrotate ,self.zup.ktranslate ) self.zup.ry = math.radians( -90 ) self.zup.rx = math.radians( -90 ) self.solverkind = 0 self.solverkinds = SeamSolver.kzup, SeamSolver.kplane, SeamSolver.kfree self.solverkindnames = 'zup', 'plane', 'free' self.solverkindbutton.text = self.solverkindnames[self.solverkind] self.fillmode = 1 self.fillmodes = gl.GL_LINE, gl.GL_FILL, gl.GL_POINT self.fillmodenames = 'lines', 'solid', 'pnts' self.fillemodebutton.text = self.fillmodenames[self.fillmode] self.showaxis = False self.showaxisnames = '!xyz','xyz' self.showaxisbutton.text = self.showaxisnames[ self.showaxis ] self.setup() def setup(self): '''called from event loop, will regen a solver whenever dirty the number and extent of frustums is not currently set from ui creates random views distributed in a possibly squished sphere sets up the solver to find the best seam for the random views ''' if self.solverdirty: levels = 5 nfrustums = 25 frustumscale = .4 squishscale = self.squishscaleslider.value solver_kind = self.solverkinds[self.solverkind] seed = self.seedslider.value if not self.solver or ( self.solver.levels != levels or \ self.solver.kind != solver_kind ): self.solver = SeamSolver( levels, solver_kind ) squish = numpy.identity(4) if solver_kind == SeamSolver.kplane: squishvec = vecutil.randunitpt( seed ) squish = vecutil.vecspace( squishvec ) if solver_kind in (SeamSolver.kzup, SeamSolver.kplane): squish[2, :] *= squishscale def randfrustums( n, scl, solver, squish=None, seedstart=0 ): 'randomly distributed view frustums' mindimension = solver.mesh.edgestats()[2] result = [] for i in xrange(n): f = Frustum.rand( scl, i + seedstart, mindimension, squish) result.append( f ) return result frustums = randfrustums( nfrustums, frustumscale, self.solver, squish, seed ) self.solver.markfrustums(frustums) colors = numpy.zeros( self.solver.mesh.points.shape, constants.DTYPE ) colors[:, 0] = 1 - self.solver.vertweight colors[:, 1] = colors[:, 0] colors[:, 2] = colors[:, 0] # colors += .1 # colors[:, 1] = 0 colors[self.solver.vertvis] = 0.1 self.mesh = TriMeshGL( self.solver.mesh, colors=colors, ui=self ) self.solverdirty = False def run(self): '''computes frustum/mesh intersection and other stuff build a pyramid, build frustums and find seams''' seams = self.solver.run() if seams: dummy, vis, f = seams[0] self.pole = f.ctw[2, 0:3] self.spin = -1 * f.ctw[0, 0:3] #self.mesh.colors[vis] = 1, 1, 0 def getpole(self): 'gets current pole vector: may be during a mouse drag' if self.manippole is not None: return self.manippole return self.pole def getspin(self): 'gets current spin vector: may be during a mouse drag' if self.manipspin is not None: return self.manipspin return self.spin def pixel2screen(self, x, y, z=0.0): 'transforms pixel coordinates to normalized device coords' sx = x / float(self._width) sy = y / float(self._height) sy = 1.0 - sy rangex = self.view.right - self.view.left rangey = self.view.bottom - self.view.top xmin = self.view.left ymin = self.view.top cx = (sx*rangex)+xmin cy = (sy*rangey)+ymin return vecutil.vec3(cx, cy, z) def pixel2world_yup(self, x, y, z=0.0): 'pixel projected to world space without swapping y/z' screenpos = self.pixel2screen( x, y, z) return vecutil.pointmatrixmult( screenpos, self.viewtransform.wto )[0] def pixel2world_zup(self, x, y, z=0.0): 'pixel projected to world space with swapping y/z' screenpos = self.pixel2screen( x, y, z) yuppos = vecutil.pointmatrixmult( screenpos, self.viewtransform.wto )[0] return vecutil.pointmatrixmult( yuppos, self.zup.wto )[0] def world2screen_zup(self, pt ): 'transform world coordinate to screen space' yup = vecutil.pointmatrixmult( pt, self.zup.otw )[0] camera = vecutil.pointmatrixmult( yup, self.viewtransform.otw )[0] return vecutil.pointmatrixmult( camera, self.view.cts )[0] def on_mouse_press(self, x, y, button, modifiers): 'hit test controls, possibly start direct manip' controlfound = False for control in self.controls: if control.hit_test(x, y): controlfound = True control.on_mouse_press(x, y, button, modifiers) if not controlfound: self.manipstart = vecutil.vec3(x, y) self.mousescreen = self.pixel2screen(x, y) self.mouseworld = self.pixel2world_yup( x, y) self.manippole = self.pole.copy() self.manipspin = self.spin.copy() polescreen = self.world2screen_zup( self.pole ) spinscreen = self.world2screen_zup( self.spin ) aspect = self._height/float(self._width) polescreen[1] *= aspect spinscreen[1] *= aspect polescreen[2] = 0 spinscreen[2] = 0 orbit = bool( modifiers & pyglet.window.key.MOD_ALT ) zoom = bool( modifiers & pyglet.window.key.MOD_SHIFT ) poledist = vecutil.vlength( polescreen - self.mousescreen ) pole = poledist < .02 spindist = vecutil.vlength( spinscreen - self.mousescreen ) spin = spindist < .02 states = [ orbit, zoom, pole, spin ] states += [ not any(states) ] states = zip( states, (self.korbit ,self.kzoom ,self.kpolemanip ,self.kspinmanip ,self.kpan )) for value, state in states: if value: self.manipstate = state return else: self.manipstart = None def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): 'orbit, zoom or pan view' if self.manipstart is None: return current = vecutil.vec3(x, y) delta = current - self.manipstart self.manipviewtransform = TransformGL(self.viewtransform) if self.manipstate == self.korbit: self.manipviewtransform.ry += delta[0] * .01 self.manipviewtransform.rx += delta[1] * -.01 elif self.manipstate == self.kzoom: current = self.pixel2screen(x, y) zoom = vecutil.vlength(current) / vecutil.vlength(self.mousescreen) eps = .00001 self.manipviewtransform.sx *= zoom self.manipviewtransform.sy *= zoom self.manipviewtransform.sz *= zoom self.manipviewtransform.sx = max( self.manipviewtransform.sx, eps) self.manipviewtransform.sy = max( self.manipviewtransform.sy, eps) self.manipviewtransform.sz = max( self.manipviewtransform.sz, eps) elif self.manipstate == self.kpan: delta = self.pixel2world_yup( x, y ) - self.mouseworld self.manipviewtransform.tx += delta[0] self.manipviewtransform.ty += delta[1] self.manipviewtransform.tz += delta[2] if self.manipstate in (self.kpolemanip, self.kspinmanip): p0 = self.pixel2world_zup( x, y, 10 ) p1 = self.pixel2world_zup( x, y, -10 ) hits = vecutil.sphere_line_intersection( p0, p1, vecutil.vec3(), 1.0 ) hit = hits[-1] if hit is None: hit = hits[0] if hit is not None: if self.manipstate == self.kpolemanip: self.manippole = vecutil.vec3( hit[0], hit[1], hit[2] ) elif self.manipstate == self.kspinmanip: self.manipspin = vecutil.vec3( hit[0], hit[1], hit[2] ) def on_mouse_release(self, x, y, button, modifiers): 'commits any manipulations and runs setup to update solver' if self.manipviewtransform: self.viewtransform = self.manipviewtransform if self.manippole is not None: self.pole = self.manippole if self.manipspin is not None: self.spin = self.manipspin self.manipviewtransform = None self.manippole = None self.manipspin = None self.setup() def on_key_press(self, symbol, modifiers): 'escape closes window -- any hotkeys would go here' if symbol == pyglet.window.key.SPACE: pass elif symbol == pyglet.window.key.ESCAPE: self.dispatch_event('on_close') def scroll( self, value ): 'unwrap slider callback' self.unwrapslider.value = value def seedscroll( self, value ): 'seed slider callback' self.seedslider.value = value self.solverdirty = True def squishscalescroll( self, value ): 'squish slider callback' self.squishscaleslider.value = value self.solverdirty = True def togglesolverkind(self): 'toggle through zup plane and free solver modes' self.solverkind = ( self.solverkind + 1 ) % len( self.solverkinds ) self.solverkindbutton.text = self.solverkindnames[self.solverkind] self.solverdirty = True def togglefillmode(self): 'toggle through wireframe point and solid poly fill modes' self.fillmode = ( self.fillmode + 1 ) % len( self.fillmodes ) self.fillemodebutton.text = self.fillmodenames[self.fillmode] def toggleaxis(self): 'show x y z axis in view' self.showaxis = not self.showaxis self.showaxisbutton.text = self.showaxisnames[self.showaxis] def toggleseam(self): 'toggle seam cutting for each mesh draw' self.mesh.toggleseamcut() def drawlines( self, verts, colors, idxs ): 'helper to draw lines from numpy arrays of verts/colors/indexes' vptr = vecutil.numpy2pointer(verts) iptr = vecutil.numpy2pointer(idxs) if colors is not None: cptr = vecutil.numpy2pointer(colors) gl.glEnableClientState(gl.GL_COLOR_ARRAY) gl.glColorPointer(3, gl.GL_FLOAT, 0, cptr) gl.glEnableClientState(gl.GL_VERTEX_ARRAY) gl.glVertexPointer(3, gl.GL_FLOAT, 0, vptr) gl.glDrawElements(gl.GL_LINES, len(idxs), gl.GL_UNSIGNED_INT, iptr) gl.glDisableClientState(gl.GL_VERTEX_ARRAY) gl.glDisableClientState(gl.GL_COLOR_ARRAY) def draw_axes(self): 'draw x y z axis in r g b with text labels' gl.glPushMatrix() gl.glScalef( 1.1, 1.1, 1.1) o = 0, 0, 0 x = 1, 0, 0 y = 0, 1, 0 z = 0, 0, 1 verts = numpy.array([ o, x, o, y, o, z], dtype=constants.DTYPE ) colors = numpy.array([ x, x, y, y, z, z], dtype=constants.DTYPE ) idxs = numpy.cast[constants.INTDTYPE]( numpy.mgrid[:6] ) self.drawlines( verts, colors, idxs) def draw_axis_label( name, xyz): 'draw a single label' gl.glPushMatrix() gl.glTranslatef( xyz[0], xyz[1], xyz[2] ) gl.glScalef( .01, .01, .01 ) gl.glRotatef( 90, 0, 1, 0 ) gl.glRotatef( 90, 0, 0, 1 ) pyglet.text.Label(name).draw() gl.glPopMatrix() draw_axis_label( 'x', x) draw_axis_label( 'y', y) draw_axis_label( 'z', z) gl.glPopMatrix() def drawseam( self ): 'draw manip and dotted line for the seam' pole = self.getpole() spin = self.getspin() def drawpoint( pt ): 'draw a single point with white outline and black interior' gl.glPointSize( 6 ) gl.glBegin( gl.GL_POINTS ) gl.glColor3f( 1, 1, 1) gl.glVertex3d( pt[0], pt[1], pt[2] ) gl.glEnd() gl.glPointSize( 4 ) gl.glBegin( gl.GL_POINTS ) gl.glColor3f( 0, 0, 0) gl.glVertex3d( pt[0], pt[1], pt[2] ) gl.glEnd() gl.glPointSize( 3 ) n = 60 idxs = numpy.cast[constants.INTDTYPE]( numpy.mgrid[:n] ) hcircle = numpy.cast[constants.DTYPE]( numpy.mgrid[:n] ) hcircle /= n hcircle -= .5 hcircle *= math.pi circlepts = numpy.zeros( (n, 3), dtype = constants.DTYPE) circlepts[:, 0] = -numpy.cos( hcircle ) circlepts[:, 2] = numpy.sin( hcircle ) gl.glPushMatrix() polemx = vecutil.vecspace2( pole, spin ) glmultmatrix( polemx ) gl.glLineWidth( 5 ) gl.glColor3f( 0, 0, 0) self.drawlines( circlepts, None, idxs ) gl.glLineWidth( 1 ) gl.glColor3f( 1, 1, 0) self.drawlines( circlepts, None, idxs ) gl.glPopMatrix() gl.glColor3f( 1, 1, 1) drawpoint( pole ) drawpoint( spin ) def on_draw(self): 'draw all controls, manips and meshes' gl.glClearColor( .2, .2, .2, 0.) self.clear() aspect = self._height/float(self._width) gl.glMatrixMode(gl.GL_PROJECTION) self.view.rtnf(( 1, aspect, -5, 5 )).orthographic() glloadmatrix( self.view.wts.transpose() ) gl.glMatrixMode(gl.GL_MODELVIEW ) #mat_pro = (gl.GLdouble * 16)() #gl.glGetDoublev(gl.GL_PROJECTION_MATRIX, mat_pro) #m = numpy.array( mat_pro ) #m = m.reshape((4,4)) #print( numpy.allclose( m, self.view.wts )) gl.glHint( gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST ) gl.glEnable(gl.GL_CULL_FACE) gl.glPushMatrix() xform = self.viewtransform if self.manipviewtransform: xform = self.manipviewtransform gl.glLoadIdentity() xform.glmultmatrix() self.zup.glmultmatrix() slider = self.unwrapslider t = ( slider.value - slider.min ) / ( slider.max - slider.min ) t = max( t, .06) self.mesh.draw( t ) if self.showaxis: self.draw_axes() self.drawseam() gl.glPopMatrix() gl.glLoadIdentity() gl.glPushMatrix() gl.glTranslatef( -1, aspect, 0) gl.glScalef( .5, .5, .5) gl.glTranslatef( 1.0, -.5, 0) gl.glScalef( 1.0/math.pi, 1.0/math.pi, 1) self.zup.glmultmatrix() self.mesh.draw( 0.06, False ) gl.glPopMatrix() gl.glMatrixMode(gl.GL_PROJECTION) gl.glLoadIdentity() gl.glOrtho(0, self._width, 0, self._height, -1, 1) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glColor3f( 1, 1, 1) for control in self.controls: control.draw() #gl.glTranslatef( self._width - 200, self._height - 50, 0 ) #self.fps_display.draw() gl.glLoadIdentity() def on_resize(self, width, height): 'keep track of width and hight, let pyglet do the rest of the work' self._width = width self._height = height return pyglet.window.Window.on_resize(self, width, height)