1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
'''
This example creates two callback objects which render a moving wave.
One is a static multi-state object, the other is a dynamic single-state
object which updates coordinates every frame.
'''
import numpy
import time
from OpenGL.GL import *
from pymol.callback import Callback
from pymol import cmd
# define a callback object
class myCallback(Callback):
'''
Static callback object. Can be loaded into a multistate object
'''
def __init__(self, b=0):
N = 126
self.vert = numpy.zeros([N, 3], float)
self.norm = numpy.zeros([N, 3], float)
# setup x,z for vertices
self.vert[0::2, 0] = \
self.vert[1::2, 0] = numpy.arange(N / 2, dtype=float) / 10.0
self.vert[1::2, 2] = 1.0
self.update(b)
def update(self, b):
'''
update y for vertices and x,y for normals
'''
a = self.vert[0::2, 0]
x = a + b / 10.0
# vertices y
self.vert[0::2, 1] = \
self.vert[1::2, 1] = numpy.sin(x)
# normals x,y
dydx = -numpy.cos(x) * (numpy.sqrt(2.0) / 2.0)
self.norm[0::2, 0] = dydx
self.norm[0::2, 1] = numpy.sqrt(1.0 - dydx**2)
self.norm[1::2] = self.norm[0::2]
def renderDrawArrays(self):
'''
Render with glDrawArrays.
This should be faster than renderImmediate.
'''
glEnableClientState(GL_VERTEX_ARRAY)
glEnableClientState(GL_NORMAL_ARRAY)
glDisableClientState(GL_COLOR_ARRAY)
glColor3f(1.0, 1.0, 1.0)
glVertexPointer(3, GL_FLOAT, 0, self.vert)
glNormalPointer(GL_FLOAT, 0, self.norm)
glDrawArrays(GL_TRIANGLE_STRIP, 0, len(self.vert))
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_NORMAL_ARRAY)
def renderImmediate(self):
'''
Render in immediate mode
'''
glBegin(GL_TRIANGLE_STRIP)
glColor3f(1.0, 1.0, 1.0)
for v, n in zip(self.vert, self.norm):
glNormal3fv(n)
glVertex3fv(v)
glEnd()
__call__ = renderImmediate
def get_extent(self):
return [
self.vert.min(0).tolist(),
self.vert.max(0).tolist(),
]
class myCallbackDynamic(myCallback):
'''
Dynamic object which updates vertex coordinates every frame
'''
def __call__(self):
self.update(cmd.get_frame() * 2)
myCallback.__call__(self)
# load it into PyMOL
for b in range(0, 63):
cmd.load_callback(myCallback(b), 'gl03', b + 1)
cmd.load_callback(myCallbackDynamic(), 'gl03dyn', 1)
# give us a nice view
cmd.turn('z',20)
cmd.turn('y',20)
cmd.turn('x',20)
cmd.mset('1-62')
cmd.mplay()
time.sleep(3)
cmd.mstop()
|