Package mmLib :: Module OpenGLDriver
[hide private]
[frames] | no frames]

Source Code for Module mmLib.OpenGLDriver

  1  ## Copyright 2002-2010 by PyMMLib Development Group (see AUTHORS file) 
  2  ## This code is part of the PyMMLib distribution and governed by 
  3  ## its license.  Please see the LICENSE file that should have been 
  4  ## included as part of this package. 
  5  """OpenGL rendering classes. 
  6  """ 
  7  import sys 
  8  import copy 
  9  import math 
 10   
 11  try: 
 12      import numpy 
 13      try: 
 14          from numpy.oldnumeric import linear_algebra as linalg 
 15      except ImportError: 
 16          from numpy.linalg import old as linalg 
 17  except ImportError: 
 18      import NumericCompat as numpy 
 19      from NumericCompat import linalg 
 20   
 21  from OpenGL.GL      import * 
 22  from OpenGL.GLU     import * 
 23  from OpenGL.GLUT    import * 
 24   
 25  import ConsoleOutput 
 26  import Gaussian 
 27  import AtomMath 
 28   
 29  try: 
 30      import glaccel 
 31  except ImportError: 
 32      ConsoleOutput.warning("cannot load OpenGL acceloration module glaccel") 
 33      GLACCEL_EXISTS = False 
 34  else: 
 35      GLACCEL_EXISTS = True 
 36   
 37   
38 -class OpenGLDriver(object):
39 """OpenGL render driver for Viewer.py 40 """
41 - def __init__(self):
42 object.__init__(self) 43 44 ## some objects have a accelorated C version built in 45 ## src/glaccel.c; if they exist, then use them 46 ## this should really be done by a factory function... 47 if GLACCEL_EXISTS: 48 self.glr_axis = self.glaccel_glr_axis 49 self.glr_tube = self.glaccel_glr_tube 50 self.glr_sphere = self.glaccel_glr_sphere 51 self.glr_Uellipse = self.glaccel_glr_Uellipse 52 self.glr_Urms = self.glaccel_glr_Urms 53 54 self.gl_draw_list_id = {} 55 self.gl_draw_list_expiration_id = {} 56 self.gl_light_model_two_side = False 57 58 self.material_r = 1.0 59 self.material_g = 1.0 60 self.material_b = 1.0 61 self.material_a = 1.0
62
63 - def glr_compile_supported(self):
64 """Returns True if draw compiling is supported by the driver. 65 """ 66 return True
67
68 - def glr_compile_start(self, draw_method):
69 """ 70 """ 71 mid = id(draw_method) 72 expiration_id = draw_method["expiration_id"] 73 assert mid not in self.gl_draw_list_id 74 75 draw_list_id = glGenLists(1) 76 self.gl_draw_list_id[mid] = draw_list_id 77 self.gl_draw_list_expiration_id[mid] = expiration_id 78 glNewList(draw_list_id, GL_COMPILE) 79 80 return mid
81
82 - def glr_compile_end(self):
83 """ 84 """ 85 glEndList()
86
87 - def glr_compile_delete(self, draw_method):
88 """ 89 """ 90 mid = id(draw_method) 91 assert mid in self.gl_draw_list_id 92 93 draw_list_id = self.gl_draw_list_id[mid] 94 glDeleteLists(draw_list_id, 1) 95 del self.gl_draw_list_id[mid] 96 del self.gl_draw_list_expiration_id[mid]
97
98 - def glr_compile_exists(self, draw_method):
99 """ 100 """ 101 mid = id(draw_method) 102 return mid in self.gl_draw_list_id
103
104 - def glr_compile_current(self, draw_method):
105 """ 106 """ 107 mid = id(draw_method) 108 expiration_id = draw_method["expiration_id"] 109 assert mid in self.gl_draw_list_id 110 return self.gl_draw_list_expiration_id[mid]==expiration_id
111
112 - def glr_compile_render(self, draw_method):
113 """ 114 """ 115 mid = id(draw_method) 116 assert mid in self.gl_draw_list_id 117 118 draw_list_id = self.gl_draw_list_id[mid] 119 glCallList(draw_list_id)
120
121 - def glr_render_begin( 122 self, 123 width = 200, 124 height = 100, 125 zoom = 50, 126 near = 0, 127 far = 0, 128 bg_color_rgbf = (0.0, 0.0, 0.0), 129 ambient_light = 1.0, 130 diffuse_light = 1.0, 131 specular_light = 1.0, 132 gl_line_smooth = False, 133 gl_point_smooth = False, 134 gl_polygon_smooth = False, 135 gl_blend = True, 136 gl_fog = False, 137 gl_fog_start = 0.0, 138 gl_fog_end = 0.0, 139 **args):
140 """Sets up lighting and OpenGL options before scene rendering. 141 """ 142 glViewport(0, 0, width, height) 143 144 ## setup perspective matrix 145 glMatrixMode(GL_PROJECTION) 146 glLoadIdentity() 147 148 zoom = zoom / 2.0 149 ratio = float(height) / float(width) 150 depth = near - far 151 152 self.near = near 153 glOrtho(-zoom, zoom, -ratio*zoom, ratio*zoom, 0.0, depth) 154 #glOrtho(-zoom, zoom, -ratio*zoom, ratio*zoom, -near, -far) 155 156 ## reset MODELVIEW matrix 157 glMatrixMode(GL_MODELVIEW) 158 glLoadIdentity() 159 glTranslatef(0.0, 0.0, -near) 160 161 ## OpenGL Features 162 glEnable(GL_NORMALIZE) 163 glShadeModel(GL_SMOOTH) 164 glEnable(GL_DEPTH_TEST) 165 glDepthFunc(GL_LESS) 166 167 ## background color 168 glClearColor(bg_color_rgbf[0], bg_color_rgbf[1], bg_color_rgbf[2], 0.0) 169 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT) 170 171 ## lighting 172 ambient = (ambient_light, ambient_light, ambient_light, 1.0) 173 diffuse = (diffuse_light, diffuse_light, diffuse_light, 1.0) 174 specular = (specular_light, specular_light, specular_light, 1.0) 175 176 ## light 0 177 glEnable(GL_LIGHT0) 178 glLightfv(GL_LIGHT0, GL_AMBIENT, (0.0, 0.0, 0.0, 1.0)) 179 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse) 180 glLightfv(GL_LIGHT0, GL_SPECULAR, specular) 181 glLightfv(GL_LIGHT0, GL_POSITION, (50.0, 50.0, 1000.0, 0.0)) 182 183 ## use model abient light 184 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient) 185 186 ## begin rendering with lighing only one side of all poygons 187 self.glr_light_two_sides_disable() 188 189 ## light 1 190 glDisable(GL_LIGHT1) 191 192 ## ANTI-ALIASING 193 if gl_line_smooth: 194 glEnable(GL_LINE_SMOOTH) 195 else: 196 glDisable(GL_LINE_SMOOTH) 197 198 if gl_point_smooth: 199 glEnable(GL_POINT_SMOOTH) 200 else: 201 glDisable(GL_POINT_SMOOTH) 202 203 if gl_polygon_smooth: 204 glEnable(GL_POLYGON_SMOOTH) 205 else: 206 glDisable(GL_POLYGON_SMOOTH) 207 208 ## ALPHA BLENDING 209 if gl_blend: 210 glEnable(GL_BLEND) 211 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 212 213 ## FOG 214 if gl_fog: 215 glEnable(GL_FOG) 216 glFogf(GL_FOG_MODE, GL_LINEAR) 217 glFogfv(GL_FOG_COLOR, (bg_color_rgbf[0], bg_color_rgbf[1], 218 bg_color_rgbf[2], 0.0)) 219 glFogf(GL_FOG_START, 0.0) 220 glFogf(GL_FOG_END, depth) 221 else: 222 glDisable(GL_FOG) 223 else: 224 glDisable(GL_BLEND)
225
226 - def glr_render_end(self):
227 """ 228 """ 229 glTranslatef(0.0, 0.0, self.near) 230 del self.near
231
232 - def glr_push_matrix(self):
233 """ 234 """ 235 glPushMatrix()
236
237 - def glr_pop_matrix(self):
238 """ 239 """ 240 glPopMatrix()
241
242 - def glr_translate(self, t):
243 """Translates the scene by vector t. 244 """ 245 glTranslatef(*t)
246
247 - def glr_translate3(self, x, y, z):
248 """ 249 """ 250 glTranslatef(x, y, z)
251
252 - def glr_mult_matrix_Rt(self, R, t):
253 """Return the current matrix as a 3x3 rotation matrix R and 3x1 254 translation vector t. 255 """ 256 ## OpenGL wants the matrix in column-major form 257 glMultMatrixf( 258 (R[0,0], R[1,0], R[2,0], 0.0, 259 R[0,1], R[1,1], R[2,1], 0.0, 260 R[0,2], R[1,2], R[2,2], 0.0, 261 t[0], t[1], t[2], 1.0) )
262
263 - def glr_mult_matrix_R(self, R):
264 """Multiplies the current matrix by rotation matrix R and translates 265 by t 266 """ 267 ## OpenGL wants the matrix in column-major form 268 glMultMatrixf( 269 (R[0,0], R[1,0], R[2,0], 0.0, 270 R[0,1], R[1,1], R[2,1], 0.0, 271 R[0,2], R[1,2], R[2,2], 0.0, 272 0.0, 0.0, 0.0, 1.0) )
273
274 - def glr_rotate_axis(self, deg, axis):
275 """ 276 """ 277 glRotatef(deg, *axis)
278
279 - def glr_lighting_enable(self):
280 """ 281 """ 282 glEnable(GL_LIGHTING)
283
284 - def glr_lighting_disable(self):
285 """ 286 """ 287 glDisable(GL_LIGHTING)
288
289 - def glr_set_line_width(self, width):
290 """ 291 """ 292 glLineWidth(width)
293
294 - def glr_begin_lines(self):
295 """ 296 """ 297 glBegin(GL_LINES)
298
299 - def glr_begin_triangles(self):
300 """ 301 """ 302 self.vertex_draw_type = "triangles"
303
304 - def glr_begin_triangle_fan(self):
305 """ 306 """ 307 glBegin(GL_TRIANGLE_FAN)
308
309 - def glr_begin_quads(self):
310 """ 311 """ 312 glBegin(GL_QUADS)
313
314 - def glr_end(self):
315 """ 316 """ 317 glEnd()
318
319 - def glr_normalize_enable(self):
320 """ 321 """ 322 glEnable(GL_NORMALIZE)
323
324 - def glr_normalize_disable(self):
325 """ 326 """ 327 glDisable(GL_NORMALIZE)
328
329 - def glr_normal(self, n):
330 """ 331 """ 332 glNormal3f(*n)
333
334 - def glr_normal3(self, x, y, z):
335 """ 336 """ 337 glNormal3f(x, y, z)
338
340 """ 341 """ 342 self.gl_light_model_two_side = True 343 glDisable(GL_CULL_FACE) 344 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE) 345 self.glr_set_material_rgba( 346 self.material_r, 347 self.material_g, 348 self.material_b, 349 self.material_a)
350
352 """ 353 """ 354 self.gl_light_model_two_side = False 355 glEnable(GL_CULL_FACE) 356 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE) 357 self.glr_set_material_rgba( 358 self.material_r, 359 self.material_g, 360 self.material_b, 361 self.material_a)
362
363 - def glr_set_material_rgb(self, r, g, b):
364 """Creates a stock rendering material colored according to the given 365 RGB values. 366 """ 367 self.material_r = r 368 self.material_g = g 369 self.material_b = b 370 self.material_a = 1.0 371 372 glColor3f(r, g, b) 373 374 ambient = (r, g, b, 1.0) 375 diffuse = (r, g, b, 1.0) 376 specular = (1.0, 1.0, 1.0, 1.0) 377 emission = (0.1*r, 0.1*g, 0.1*b, 1.0) 378 379 if self.gl_light_model_two_side==True: 380 side = GL_FRONT_AND_BACK 381 else: 382 side = GL_FRONT 383 384 glMaterialfv(side, GL_AMBIENT, ambient) 385 glMaterialfv(side, GL_DIFFUSE, diffuse) 386 glMaterialfv(side, GL_SPECULAR, specular) 387 glMaterialfv(side, GL_EMISSION, emission) 388 glMaterialfv(side, GL_SHININESS, 100.0)
389
390 - def glr_set_material_rgba(self, r, g, b, a):
391 """Creates a stock rendering material colored according to the given 392 RGB values. 393 """ 394 self.material_r = r 395 self.material_g = g 396 self.material_b = b 397 self.material_a = a 398 399 glColor3f(r, g, b) 400 401 ambient = (r, g, b, a) 402 diffuse = (r, g, b, a) 403 specular = (1.0, 1.0, 1.0, a) 404 emission = (0.1*r, 0.1*g, 0.1*b, a) 405 406 if self.gl_light_model_two_side==True: 407 side = GL_FRONT_AND_BACK 408 else: 409 side = GL_FRONT 410 411 glMaterialfv(side, GL_AMBIENT, ambient) 412 glMaterialfv(side, GL_DIFFUSE, diffuse) 413 glMaterialfv(side, GL_SPECULAR, specular) 414 glMaterialfv(side, GL_EMISSION, emission) 415 glMaterialfv(side, GL_SHININESS, 100.0)
416
417 - def glr_vertex(self, position):
418 """ 419 """ 420 glVertex3f(*position)
421
422 - def glr_vertex3(self, x, y, z):
423 """ 424 """ 425 glVertex3f(x, y, z)
426
427 - def glr_line(self, position1, position2):
428 """Draws a single line. 429 """ 430 glBegin(GL_LINES) 431 glVertex3f(*position1) 432 glVertex3f(*position2) 433 glEnd()
434
435 - def glr_text(self, text, scale):
436 """Renders a text string. 437 """ 438 glDisable(GL_LIGHTING) 439 glLineWidth(2.0) 440 441 glPushMatrix() 442 443 s = scale / 1000.0 444 glScalef(s, s, s) 445 446 for c in text: 447 glutStrokeCharacter(GLUT_STROKE_ROMAN, ord(c)) 448 449 glPopMatrix()
450
451 - def glr_axis(self, position, axis, radius):
452 """Draw a vector axis using the current set material at position 453 with the given radius. 454 """ 455 ## don't bother redering small axes -- they look like junk 456 if numpy.allclose(AtomMath.length(axis), 0.0): 457 return 458 459 end = position + axis 460 461 l = AtomMath.length(axis) 462 R = AtomMath.rmatrixz(axis) 463 464 glPushMatrix() 465 self.glr_mult_matrix_Rt(R, position) 466 467 glEnable(GL_LIGHTING) 468 469 quad = gluNewQuadric() 470 gluCylindar(quad, radius, radius, l, 10, 1) 471 472 glDisable(GL_LIGHTING) 473 glPopMatrix()
474
475 - def glaccel_glr_axis(self, position, axis, radius):
476 """glaccel optimized version of glr_axis. 477 """ 478 if numpy.allclose(AtomMath.length(axis), 0.0): 479 return 480 end = position + axis 481 glaccel.rod(position[0], position[1], position[2], end[0], end[1], end[2], radius)
482
483 - def glr_tube(self, pos1, pos2, radius):
484 """Draws a hollow tube beginning at pos1, and ending at pos2. 485 """ 486 glDisable(GL_LIGHTING) 487 glLineWidth(1.0) 488 glBegin(GL_LINES) 489 glVertex3f(*pos1) 490 glVertex3f(*pos2) 491 glEnd()
492
493 - def glaccel_glr_tube(self, pos1, pos2, radius):
494 glaccel.tube( 495 pos1[0], pos1[1], pos1[2], 496 pos2[0], pos2[1], pos2[2], 497 radius)
498
499 - def glr_sphere(self, position, radius, quality):
500 """Draws a solid sphere. 501 """ 502 glEnable(GL_LIGHTING) 503 glPushMatrix(); 504 glTranslatef(*position) 505 glutSolidSphere(radius, quality, quality) 506 glPopMatrix()
507
508 - def glaccel_glr_sphere(self, position, radius, quality):
509 glaccel.sphere(position[0], position[1], position[2], radius, quality)
510
511 - def glr_cross(self, position, color, line_width):
512 """Draws atom with a cross of lines. 513 """ 514 glDisable(GL_LIGHTING) 515 glColor3f(*color) 516 glLineWidth(line_width) 517 518 vx = numpy.array([0.25, 0.0, 0.0]) 519 vy = numpy.array([0.0, 0.25, 0.0]) 520 vz = numpy.array([0.0, 0.0, 0.25]) 521 522 glBegin(GL_LINES) 523 524 start = position - vx 525 end = position + vx 526 glVertex3f(*start) 527 glVertex3f(*end) 528 529 start = position - vy 530 end = position + vy 531 glVertex3f(*start) 532 glVertex3f(*end) 533 534 start = position - vz 535 end = position + vz 536 glVertex3f(*start) 537 glVertex3f(*end) 538 539 glEnd()
540
541 - def glr_Uaxes(self, position, U, prob, color, line_width):
542 """Draw the anisotropic axies of the atom at the given probability. 543 """ 544 C = Gaussian.GAUSS3C[prob] 545 eval_U, evec_U = linalg.eignvectors(U) 546 547 try: 548 v0_peak = C * math.sqrt(eval_U[0]) 549 except ValueError: 550 v0_peak = 0.0 551 try: 552 v1_peak = C * math.sqrt(eval_U[1]) 553 except ValueError: 554 v1_peak = 0.0 555 try: 556 v2_peak = C * math.sqrt(eval_U[2]) 557 except ValueError: 558 v2_peak = 0.0 559 560 v0 = evec_U[0] * v0_peak 561 v1 = evec_U[1] * v1_peak 562 v2 = evec_U[2] * v2_peak 563 564 glDisable(GL_LIGHTING) 565 glColor3f(*color) 566 glLineWidth(line_width) 567 568 glPushMatrix() 569 glTranslatef(*position) 570 571 glBegin(GL_LINES) 572 glVertex3f(*-v0) 573 glVertex3f(* v0) 574 glVertex3f(*-v1) 575 glVertex3f(* v1) 576 glVertex3f(*-v2) 577 glVertex3f(* v2) 578 glEnd() 579 580 glPopMatrix()
581
582 - def glr_Uellipse(self, position, U, prob):
583 """Renders the ellipsoid enclosing the given fractional probability 584 given the gaussian variance-covariance matrix U at the given position. 585 C=1.8724 = 68% 586 """ 587 pass
588
589 - def glaccel_glr_Uellipse(self, position, U, prob):
590 """Renders the ellipsoid enclosing the given fractional probability 591 given the gaussian variance-covariance matrix U at the given position. 592 C=1.8724 = 68% 593 """ 594 glaccel.Uellipse( 595 position[0], position[1], position[2], 596 U[0,0], U[1,1], U[2,2], U[0,1], U[0,2], U[1,2], 597 Gaussian.GAUSS3C[prob], 3)
598
599 - def glr_Urms(self, position, U):
600 """Renders the root mean square (one standard deviation) surface of 601 the gaussian variance-covariance matrix U at the given position. This 602 is a peanut-shaped surface. (Note: reference the peanut paper!) 603 """ 604 pass
605
606 - def glaccel_glr_Urms(self, position, U):
607 """Renders the root mean square (one standard deviation) surface of 608 the gaussian variance-covariance matrix U at the given position. This 609 is a peanut-shaped surface. (Note: reference the peanut paper!) 610 """ 611 glaccel.Upeanut( 612 position[0], position[1], position[2], 613 U[0,0], U[1,1], U[2,2], U[0,1], U[0,2], U[1,2], 614 3)
615