Statistics
| Revision:

root / PyOpenGL-Demo / NeHe / lesson13.py @ 1

History | View | Annotate | Download (7.5 kB)

1
#! /usr/bin/env python
2

    
3

    
4
#
5
# Ported to PyOpenGL 2.0 by Brian Leair 18 Jan 2004
6
#
7
# This code was created by Jeff Molofee 2000
8
#
9
# The port was based on the PyOpenGL tutorial and from the PyOpenGLContext (tests/glprint.py)
10
#
11
# If you've found this code useful, please let me know (email Brian Leair at telcom_sage@yahoo.com).
12
#
13
# See original source and C based tutorial at http://nehe.gamedev.net
14
#
15
# Note:
16
# -----
17
# This code is not a good example of Python and using OO techniques.  It is a simple and direct
18
# exposition of how to use the Open GL API in Python via the PyOpenGL package.  It also uses GLUT,
19
# which in my opinion is a high quality library in that it makes my work simpler.  Due to using
20
# these APIs, this code is more like a C program using function based programming (which Python
21
# is in fact based upon, note the use of closures and lambda) than a "good" OO program.
22
#
23
# To run this code get and install OpenGL, GLUT, PyOpenGL (see http://www.python.org), and PyNumeric.
24
# Installing PyNumeric means having a C compiler that is configured properly, or so I found.  For 
25
# Win32 this assumes VC++, I poked through the setup.py for Numeric, and chased through disutils code
26
# and noticed what seemed to be hard coded preferences for VC++ in the case of a Win32 OS.
27
#
28
#
29
from OpenGL.GL import *
30
from OpenGL.GLUT import *
31
from OpenGL.GLU import *
32
from OpenGL.WGL import *        # wglUseFontBitmaps (), wglGetCurrentDC ()
33
import win32ui                                # CreateFont (), CreateDCFromHandle ()
34
from math import cos, sin
35
import sys, time
36

    
37

    
38
# *********************** Globals *********************** 
39
# Python 2.2 defines these directly
40
try:
41
        True
42
except NameError:
43
        True = 1==1
44
        False = 1==0
45

    
46

    
47
# Some api in the chain is translating the keystrokes to this octal string
48
# so instead of saying: ESCAPE = 27, we use the following.
49
ESCAPE = '\033'
50

    
51
# Number of the glut window.
52
window = 0
53
base = None
54
import struct
55
def pointer_as_int( p ):
56
        if hasattr(p,'value'):
57
                p = p.value
58
        return struct.unpack( 'i',struct.pack( 'I',p ))[0]
59

    
60
def BuildFont ():
61
        global base
62
        # TODO: figure out why ctypes doesn't return a c_void_p, has been
63
        # known since at least 2006, still presenting in Python 2.5 win32
64
        wgldc = wglGetCurrentDC ()
65
        hDC = win32ui.CreateDCFromHandle (pointer_as_int(wgldc))
66

    
67

    
68
        base = glGenLists(32+96);                                        # // Storage For 96 Characters, plus 32 at the start...
69

    
70
        # CreateFont () takes a python dictionary to specify the requested font properties. 
71
        font_properties = { "name" : "Courier New",
72
                                                "width" : 0 ,
73
                                                "height" : -24,
74
                                                "weight" : 800
75
                                                }
76
        font = win32ui.CreateFont (font_properties)
77
        # // Selects The Font We Want
78
        oldfont = hDC.SelectObject (font)
79
        # // Builds 96 Characters Starting At Character 32
80
        wglUseFontBitmapsA(wgldc, 32, 96, base+32)
81
        # // reset the font
82
        hDC.SelectObject (oldfont)
83
        # // Delete The Font (python will cleanup font for us...)
84
        return
85

    
86
def KillFont ():
87
        """ // Delete The Font List
88
        """
89
        global        base
90
        # // Delete All 96 Characters
91
        glDeleteLists (base, 32+96)
92
        return
93

    
94

    
95
def glPrint (str):
96
        """ // Custom GL "Print" Routine
97
        """
98
        global base
99
        # // If THere's No Text Do Nothing
100
        if (str == None):
101
                return
102
        if (str == ""):
103
                return
104
        glPushAttrib(GL_LIST_BIT);                                                        # // Pushes The Display List Bits
105
        try:
106
                glListBase(base);                                                                # // Sets The Base Character to 32
107
                glCallLists(str)                                                                        # // Draws The Display List Text
108
        finally:
109
                glPopAttrib();                                                                                # // Pops The Display List Bits
110
        return
111

    
112

    
113
# A general OpenGL initialization function.  Sets all of the initial parameters. 
114
def InitGL(Width, Height):                                # We call this right after our OpenGL window is created.
115
        glShadeModel(GL_SMOOTH)                                # Enables Smooth Color Shading
116
        glClearColor(0.0, 0.0, 0.0, 0.5)        # This Will Clear The Background Color To Black
117
        glClearDepth(1.0)                                        # Enables Clearing Of The Depth Buffer
118
        glEnable(GL_DEPTH_TEST)                                # Enables Depth Testing
119
        glDepthFunc(GL_LEQUAL)                                # The Type Of Depth Test To Do
120
        glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) # Really Nice Perspective Calculations
121

    
122
        BuildFont ()
123
        return True
124
        
125

    
126
# The function called when our window is resized (which shouldn't happen if you enable fullscreen, below)
127
def ReSizeGLScene(Width, Height):
128
        if Height == 0:                                                # Prevent A Divide By Zero If The Window Is Too Small 
129
                Height = 1
130

    
131
        glViewport(0, 0, Width, Height)                # Reset The Current Viewport And Perspective Transformation
132
        glMatrixMode(GL_PROJECTION)
133
        glLoadIdentity()
134
        # // field of view, aspect ratio, near and far
135
        # This will squash and stretch our objects as the window is resized.
136
        gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
137

    
138
        glMatrixMode(GL_MODELVIEW)
139
        glLoadIdentity()
140

    
141

    
142

    
143
cnt1 = 0
144
cnt2 = 0
145
# The main drawing function. 
146
def DrawGLScene():
147
        global cnt1,cnt2
148

    
149
        # // Clear The Screen And The Depth Buffer
150
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
151
        
152
        glLoadIdentity()                                        # // Reset The Current Modelview Matrix
153
        glTranslatef (0.0, 0.0, -1.0)                # // Move One Unit Into The Screen
154

    
155
        # // Pulsing Colors Based On Text Position
156
        glColor3f (1.0 * cos (cnt1), 1.0 * sin (cnt2), 1.0 -0.5 * cos (cnt1+cnt2))
157
        # // Position The Text On The Screen
158
        glRasterPos2f(-0.45+0.05* cos(cnt1), 0.32*sin(cnt2));
159
        glPrint("Active OpenGL Text With NeHe - %7.2f" %(cnt1));        # // Print GL Text To The Screen
160
        cnt1+=0.051;                                                                                # // Increase The First Counter
161
        cnt2+=0.005;                                                                                # // Increase The First Counter
162
        glutSwapBuffers()
163
        return True
164

    
165

    
166
# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)  
167
def keyPressed(*args):
168
        global window
169
        # If escape is pressed, kill everything.
170
        if args[0] == ESCAPE:
171
                KillFont ()
172
                sys.exit ()
173

    
174
def main():
175
        global window
176
        # pass arguments to init
177
        glutInit(sys.argv)
178

    
179
        # Select type of Display mode:   
180
        #  Double buffer 
181
        #  RGBA color
182
        # Alpha components supported 
183
        # Depth buffer
184
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
185
        
186
        # get a 640 x 480 window 
187
        glutInitWindowSize(640, 480)
188
        
189
        # the window starts at the upper left corner of the screen 
190
        glutInitWindowPosition(0, 0)
191
        
192
        # Okay, like the C version we retain the window id to use when closing, but for those of you new
193
        # to Python, remember this assignment would make the variable local and not global
194
        # if it weren't for the global declaration at the start of main.
195
        window = glutCreateWindow("NeHe's Bitmap Font Tutorial")
196

    
197
           # Register the drawing function with glut, BUT in Python land, at least using PyOpenGL, we need to
198
        # set the function pointer and invoke a function to actually register the callback, otherwise it
199
        # would be very much like the C version of the code.        
200
        glutDisplayFunc(DrawGLScene)
201
        
202
        # Uncomment this line to get full screen.
203
        #glutFullScreen()
204

    
205
        # When we are doing nothing, redraw the scene.
206
        glutIdleFunc(DrawGLScene)
207
        
208
        # Register the function called when our window is resized.
209
        glutReshapeFunc(ReSizeGLScene)
210
        
211
        # Register the function called when the keyboard is pressed.  
212
        glutKeyboardFunc(keyPressed)
213

    
214
        # We've told Glut the type of window we want, and we've told glut about
215
        # various functions that we want invoked (idle, resizing, keyboard events).
216
        # Glut has done the hard work of building up thw windows DC context and 
217
        # tying in a rendering context, so we are ready to start making immediate mode
218
        # GL calls.
219
        # Call to perform inital GL setup (the clear colors, enabling modes, and most releveant -
220
        # consturct the displays lists for the bitmap font.
221
        InitGL(640, 480)
222

    
223
        # Start Event Processing Engine        
224
        glutMainLoop()
225

    
226
# Print message to console, and kick off the main to get it rolling.
227
if __name__ == "__main__":
228
        print "Hit ESC key to quit."
229
        main()
230