/gl/renderer.py
Python | 442 lines | 356 code | 49 blank | 37 comment | 49 complexity | 6db8c260f83febc8ed04a1455c8377fd MD5 | raw file
- # Copyright (c) 2010 Galen Clark Haynes
- # 2010 Dexteris Robotics, LLC
- # All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions are met:
- #
- # * Redistributions of source code must retain the above copyright
- # notice, this list of conditions and the following disclaimer.
- # * Redistributions in binary form must reproduce the above copyright
- # notice, this list of conditions and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- # * Neither the name of Dexteris Robotics, LLC nor the names of its
- # contributors may be used to endorse or promote products derived from
- # this software without specific prior written permission.
- #
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- # POSSIBILITY OF SUCH DAMAGE.
- from OpenGL.GL import *
- from OpenGL.GLU import *
- from OpenGL.GLUT import *
- import math
- import time
- from forma.common import Forma
- class GLRenderer(object):
-
- def __init__(self, viewport):
- self.viewport = viewport
- glEnable(GL_NORMALIZE)
- glEnable(GL_DEPTH_TEST)
- glDepthFunc(GL_LEQUAL);
- glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
- #glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
- glEnable(GL_BLEND)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
- glShadeModel(GL_SMOOTH)
- LightAmbient= [0.5, 0.5, 0.5, 1.0]
- LightDiffuse = [1.0, 1.0, 1.0, 1.0]
- LightSpecular = [0.5, 0.5, 0.5, 1.0]
- LightSpecular = LightDiffuse
- LightPosition = [1.5, -1.5, 1.0, 1.0]
- glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
- glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
- glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular);
- glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
- glEnable(GL_LIGHT1);
- glEnable(GL_LIGHTING);
- glClearColor(0.2,0.2,0.2,1.0)
- MatAmbientDiffuse = [0.5, 0.5, 0.5, 1.0]
- MatSpecular = [0.5,0.5,0.5,1.0]
- MatEmission = [0.05,0.05,0.05,1.0]
- MatShininess = 25
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, MatAmbientDiffuse);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpecular)
- glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, MatEmission);
- glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess);
- self.do_grid = False
- self.grid_spacing = [1.0,1.0,0.1]
- self.grid_span = [5.0,5.0,1.5]
- self.top_text = 'Forma by Dexteris Robotics'
-
- def enable_grid(self):
- self.do_grid = True
-
- def disable_grid(self):
- self.do_grid = False
-
- def do_render(self,fobj):
- self.pre_render(fobj)
- for f in fobj.attachments:
- self.do_render(f)
- self.post_render(fobj)
-
- def pre_render(self,fobj):
- try:
- glPushMatrix()
- except GLerror, error:
- print error
- sys.exit(-1)
- #super(type(self),self).pre_render(fobj)
- if not hasattr(fobj,'_glforma'):
- create_glforma(fobj)
- fobj._glforma.pre_render()
-
- def post_render(self,fobj):
- #super(type(self),self).post_render(fobj)
- fobj._glforma.post_render()
- glPopMatrix()
-
-
- def render(self, scene):
- self.do_perspective()
- glLoadIdentity()
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
- if self.do_grid:
- self.draw_grid(self.grid_spacing,self.grid_span)
- if self.top_text != None:
- self.draw_text(0,10,self.top_text)
- try:
- glPushMatrix()
- except Exception, error:
- print error
- sys.exit(-1)
- try:
- self.do_render(scene)
- except Exception, e:
- import traceback
- traceback.print_tb(sys.exc_info()[2])
- print e
- sys.exit(-1)
- glPopMatrix()
- def draw_text(self,*args):
- glPushMatrix()
- if len(args) > 3:
- glRasterPos3d(args[0],args[1],args[2])
- else:
- self.do_orthographic()
- glRasterPos2d(args[0],args[1])
- text = args[-1]
- for c in text:
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10,ord(c))
- glPopMatrix()
- if len(args) == 3:
- self.do_perspective()
- def do_orthographic(self):
- glMatrixMode(GL_PROJECTION)
- glLoadIdentity()
- gluOrtho2D(0,self.viewport.width,0,self.viewport.height)
- glScalef(1,-1,1)
- glTranslatef(0,-self.viewport.height,0)
- glMatrixMode(GL_MODELVIEW)
-
- def do_perspective(self):
- glMatrixMode(GL_PROJECTION)
- glLoadIdentity()
- gluPerspective(70,float(self.viewport.width)/float(self.viewport.height),0.01,100)
- deg2rad = math.pi / 180.
- global lookAt
- upVec = [0,0,1]
- eyePos = self.viewport.controller.eye()
- lookAt = self.viewport.controller.center
- gluLookAt(eyePos[0],eyePos[1],eyePos[2],lookAt[0],lookAt[1],lookAt[2],upVec[0],upVec[1],upVec[2])
- glMatrixMode(GL_MODELVIEW)
- def draw_grid(self,spacing,span):
- global lookAt
- x = span[0] / 2.0
- xs = spacing[0]
- y = span[1] / 2.0
- ys = spacing[1]
- z = span[2] / 2.0
- zs = spacing[2] # draw single line in Z direction
- glBegin(GL_LINES)
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, [0.5,0.5,0.5,1.0]);
- glVertex(lookAt[0],lookAt[1],lookAt[2]-z)
- glVertex(lookAt[0],lookAt[1],lookAt[2]+z)
- notchpos = math.ceil((lookAt[2]-z) / zs) * zs;
- while notchpos < lookAt[2]+z:
- glVertex(lookAt[0]-spacing[0]/20.0,lookAt[1],notchpos)
- glVertex(lookAt[0]+spacing[0]/20.0,lookAt[1],notchpos)
- glVertex(lookAt[0],lookAt[1]-spacing[0]/20.0,notchpos)
- glVertex(lookAt[0],lookAt[1]+spacing[0]/20.0,notchpos)
- notchpos += zs
- minx = math.ceil((lookAt[0]-x) / xs) * xs
- miny = math.ceil((lookAt[1]-y) / ys) * ys
- maxx = math.floor((lookAt[0]+x) / xs) * xs
- maxy = math.ceil((lookAt[1]+y) / ys) * ys
- notchpos = minx
- while notchpos <= maxx:
- glVertex(notchpos,miny,lookAt[2])
- glVertex(notchpos,maxy,lookAt[2])
- notchpos += xs
- notchpos = miny
- while notchpos <= maxy:
- glVertex(minx,notchpos,lookAt[2])
- glVertex(maxx,notchpos,lookAt[2])
- notchpos += ys
- glEnd()
- notchpos = math.ceil((lookAt[2]-z) / zs) * zs
- while notchpos < lookAt[2]+z:
- self.draw_text(lookAt[0],lookAt[1],notchpos,'%.1f' % notchpos)
- notchpos += zs
-
- def create_glforma(fobj):
- """
- Switchyard function
- """
- fobj_type = type(fobj).__name__
- # fixme, there should be a way to do this by adding 'GL' to fobj_type
- if fobj_type is 'Box':
- globj = GLBox(fobj)
- elif fobj_type is 'Cylinder':
- globj = GLCylinder(fobj)
- elif fobj_type is 'Polygon':
- globj = GLPolygon(fobj)
- elif fobj_type is 'Circle':
- globj = GLCircle(fobj)
- elif fobj_type is 'Sphere':
- globj = GLSphere(fobj)
- elif fobj_type is 'Cone':
- globj = GLCone(fobj)
- elif fobj_type is 'Transformation':
- globj = GLTransformation(fobj)
- elif fobj_type is 'Translation':
- globj = GLTranslation(fobj)
- elif fobj_type is 'Rotation':
- globj = GLRotation(fobj)
- elif fobj_type is 'LineTrace':
- globj = GLLineTrace(fobj)
- elif fobj_type is 'Label':
- globj = GLLabel(fobj)
- else:
- #print 'object %s not known, using default GLForma' % fobj_type
- globj = GLForma(fobj)
- class GLForma(object):
- def __init__(self,fobj):
- #print 'CREATED GL OBJECT: %s' % type(fobj).__name__
- self._forma = fobj
- fobj._glforma = self
- def pre_render(self):
- pass
- def post_render(self):
- pass
-
- def set_color(self):
- if hasattr(self._forma,'color'):
- if len(self._forma.color) == 3:
- self._forma.color = [self._forma.color[0],self._forma.color[1],self._forma.color[2],1.0]
- color = self._forma.color
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
- else:
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, [0.5,0.5,0.5,1.0]);
- class GLTransformation(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
-
- def pre_render(self):
- glPushMatrix()
- # glMultMatrix wants column major. Numpy by default will use row-major when flattening, so do it manually
- glMultMatrixf(self._forma.transmat.flatten('F'))
-
- def post_render(self):
- glPopMatrix()
-
-
- class GLTranslation(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
-
- def pre_render(self):
- glPushMatrix()
- x,y,z = self._forma.x, self._forma.y, self._forma.z
- glTranslatef(x,y,z)
-
- def post_render(self):
- glPopMatrix()
- class GLRotation(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
-
- def pre_render(self):
- import numpy
- rotmat = self._forma.rotmat
- x,y,z = self._forma.x, self._forma.y, self._forma.z
- x *= 180./math.pi
- y *= 180./math.pi
- z *= 180./math.pi
- glPushMatrix()
- if (x != 0.0 or y != 0.0 or z != 0.0):
- glRotatef(x,1.,0.,0.)
- glRotatef(y,0.,1.,0.)
- glRotatef(z,0.,0.,1.)
- else:
- t = numpy.eye(4)
- t[0:3,0:3] = rotmat
- glMultMatrixf(t.flatten('F'))
- def post_render(self):
- glPopMatrix()
- class GLPolygon(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
-
- def pre_render(self):
- points = self._forma.points
- normal = self._forma.normal
- self.set_color()
- glBegin(GL_POLYGON)
- glNormal3fv(normal)
- for i in xrange(points.shape[1]):
- glVertex3f(points[0,i],points[1,i],points[2,i])
- glVertex3f(points[0,0],points[1,0],points[2,i])
- glEnd()
- class GLCircle(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
-
- def pre_render(self):
- import numpy
- arc = self._forma.arc
- radius = self._forma.radius
- self.set_color()
- subdiv = 30
- subdiv = int(subdiv * arc / (2.0*math.pi))
- if subdiv < 4:
- subdiv = 4
- angleset = numpy.linspace(0,arc,subdiv)
- glBegin(GL_POLYGON)
- glNormal3f(0.0,0.0,1.0)
- for a in angleset:
- glVertex3f(radius*math.cos(a),radius*math.sin(a),0.0)
- glEnd()
- class GLSphere(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
- def pre_render(self):
- r = self._forma.radius
- self.set_color()
- glutSolidSphere(r,30,30)
-
- class GLCone(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
- def pre_render(self):
- r = self._forma.radius
- h = self._forma.height
- if (r != self._forma.c.radius):
- self._forma.c.radius = r
- self.set_color()
- glutSolidCone(r,h,30,5)
-
- class GLBox(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
-
- def pre_render(self):
- w = self._forma.width
- h = self._forma.height
- l = self._forma.length
- self.set_color()
- glBegin(GL_QUADS)
- for side in [-w/2,w/2]:
- glNormal3f(side/(w/2),0,0)
- glVertex3f(side,l/2,h/2)
- glVertex3f(side,-l/2,h/2)
- glVertex3f(side,-l/2,-h/2)
- glVertex3f(side,l/2,-h/2)
- for height in [-h/2,h/2]:
- glNormal3f(0,0,height/(h/2));
- glVertex3f(w/2,l/2,height)
- glVertex3f(-w/2,l/2,height)
- glVertex3f(-w/2,-l/2,height)
- glVertex3f(w/2,-l/2,height)
- for length in [-l/2, l/2]:
- glNormal3f(0,length/(l/2),0);
- glVertex3f(w/2,length,h/2)
- glVertex3f(w/2,length,-h/2)
- glVertex3f(-w/2,length,-h/2)
- glVertex3f(-w/2,length,h/2)
- glEnd()
- class GLCylinder(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
-
- def pre_render(self):
- import numpy
- radius = self._forma.radius
- height = self._forma.height
- arc = self._forma.arc
- self.set_color()
- subdiv = 30
- subdiv = int(subdiv * arc / (2.0*math.pi))
- if subdiv < 4:
- subdiv = 4
- angleset = numpy.linspace(0,arc,subdiv)
- glBegin(GL_QUAD_STRIP)
- count = 0
- for a in angleset:
- normal_angle = angleset[count]
- glNormal3f(math.cos(normal_angle),math.sin(normal_angle),0.0)
- for s in [-height/2,height/2]:
- glVertex3f(radius*math.cos(a),radius*math.sin(a),s)
- count += 1
- glEnd()
- class GLLineTrace(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
-
- def pre_render(self):
- x_trace = self._forma.x_trace
- y_trace = self._forma.y_trace
- z_trace = self._forma.z_trace
- self.set_color()
- glBegin(GL_LINE_STRIP)
- for i in range(len(x_trace)):
- glVertex3f(x_trace[i],y_trace[i],z_trace[i])
- glEnd()
- class GLLabel(GLForma):
- def __init__(self,fobj):
- super(type(self),self).__init__(fobj)
- def pre_render(self):
- x = self._forma.x
- y = self._forma.y
- z = self._forma.z
- label = self._forma.label
- self.set_color()
- glPushMatrix()
- glRasterPos3d(x,y,z)
- for c in label:
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10,ord(c))
- glPopMatrix()