]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Initial revision
authorGuido van Rossum <guido@python.org>
Mon, 30 Mar 1992 13:18:37 +0000 (13:18 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 30 Mar 1992 13:18:37 +0000 (13:18 +0000)
18 files changed:
Demo/sgi/gl/README [new file with mode: 0644]
Demo/sgi/gl/backface.py [new file with mode: 0755]
Demo/sgi/gl/glstdwin/fontchart.py [new file with mode: 0644]
Demo/sgi/gl/glstdwin/glstdwdraw.py [new file with mode: 0644]
Demo/sgi/gl/glstdwin/glstdwin.py [new file with mode: 0644]
Demo/sgi/gl/glstdwin/glstdwmenu.py [new file with mode: 0644]
Demo/sgi/gl/glstdwin/glstdwwin.py [new file with mode: 0644]
Demo/sgi/gl/glstdwin/stdwingl.py [new file with mode: 0644]
Demo/sgi/gl/glstdwin/tcolor.py [new file with mode: 0644]
Demo/sgi/gl/glstdwin/tglsw.py [new file with mode: 0644]
Demo/sgi/gl/glstdwin/tmenu.py [new file with mode: 0644]
Demo/sgi/gl/kites.py [new file with mode: 0755]
Demo/sgi/gl/kunst.py [new file with mode: 0755]
Demo/sgi/gl/mclock.doc [new file with mode: 0755]
Demo/sgi/gl/mclock.py [new file with mode: 0755]
Demo/sgi/gl/mixing.py [new file with mode: 0755]
Demo/sgi/gl/nurbs.py [new file with mode: 0755]
Demo/sgi/gl/zrgb.py [new file with mode: 0755]

diff --git a/Demo/sgi/gl/README b/Demo/sgi/gl/README
new file mode 100644 (file)
index 0000000..7a8caae
--- /dev/null
@@ -0,0 +1,29 @@
+These demos run only on SGI machines and require the 'gl' built-in module.
+The demonstrate the abilities of SGI's GL library as well as the ease of
+GL programming in Python.  Most demos require the Z-buffer (aka
+24-bitplane) option.  Press ESC to get out of any of them.
+
+backface.py    Demonstrates the 'backface' GL function.
+
+kites.py       Show 3 flying kites.  Demonstrates the rendering speed
+               obtainable by Python programs.
+
+mclock.py      A colorful clock with more options than you can
+               remember.  Works on 8-bit machines, but allows more
+               colors on 24-bit machines.  See mclock.doc for more
+               info.
+
+mixing.py      Demonstrates the effect of color mixing: through
+               frequent color switching it gives the effect of white
+               light.
+
+nurbs.py       A simple demonstration of the 'nurbs' GL functions.
+               Press left mouse button to toggle surface trimming.
+
+zrgb.py                Displays a 3-D Gouraud-shaded figure which can be moved
+               around with the mouse.
+
+glstdwin/      This is quite different: a partial STDWIN emulation
+               using GL!  Requires only small changes to Python
+               programs that use STDWIN.  Some features not yet
+               implemented, e.g., scroll bars.
diff --git a/Demo/sgi/gl/backface.py b/Demo/sgi/gl/backface.py
new file mode 100755 (executable)
index 0000000..594b8ad
--- /dev/null
@@ -0,0 +1,140 @@
+#! /usr/local/python
+
+#   backface
+#
+#   draw a cube that can run with backface() turned on or off.
+#   cube is moved when LEFTMOUSE is pressed and mouse itself is moved.
+
+from gl import *
+from DEVICE import *
+from GL import *
+
+CUBE_SIZE = 200.0
+CUBE_OBJ = 1
+
+def main () :
+       #
+       x = 0
+       y = 0
+       moveit = 0
+       #
+       initialize()
+       #
+       while (1) :
+               #
+               while (qtest()) :
+                       dev, val = qread()
+                       #
+                       if dev == ESCKEY :
+                               backface(0)
+                               return
+                               #
+                       elif dev == REDRAW :
+                               reshapeviewport()
+                               drawcube(x,y)
+                               #
+                       elif dev == LEFTMOUSE :
+                               #
+                               # LEFTMOUSE down
+                               moveit = val
+                               #
+                       elif dev == BKEY :
+                               backface(1)
+                               drawcube(x,y)
+                               #
+                       elif dev == FKEY :
+                               backface(0)
+                               drawcube(x,y)
+                               #
+               if moveit :
+                       x = getvaluator(MOUSEX)
+                       y = getvaluator(MOUSEY)
+                       drawcube(x,y)
+
+
+def initialize () :
+       foreground ()
+       keepaspect (1, 1)
+       gid = winopen('backface')
+       winset(gid)
+       winconstraints()
+       #
+       doublebuffer()
+       gconfig()
+       shademodel(FLAT)
+       #
+       ortho(-1024.0, 1024.0, -1024.0, 1024.0, -1024.0, 1024.0)
+       #
+       qdevice(ESCKEY)
+       qdevice(REDRAW)
+       qdevice(LEFTMOUSE)
+       qdevice(BKEY)
+       qdevice(FKEY)
+       qenter(REDRAW,gid)
+       #
+       backface(1)
+
+#
+# define a cube
+def cube () :
+       #
+       # front face
+       pushmatrix()
+       translate(0.0,0.0,CUBE_SIZE)
+       color(RED)
+       rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+       popmatrix()
+       #
+       # right face
+       pushmatrix()
+       translate(CUBE_SIZE, 0.0, 0.0)
+       rotate(900, 'y')
+       color(GREEN)
+       rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+       popmatrix()
+       #
+       # back face
+       pushmatrix()
+       translate(0.0, 0.0, -CUBE_SIZE)
+       rotate(1800, 'y')
+       color(BLUE)
+       rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+       popmatrix()
+       #
+       # left face
+       pushmatrix()
+       translate(-CUBE_SIZE, 0.0, 0.0)
+       rotate(-900, 'y')
+       color(CYAN)
+       rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+       popmatrix()
+       #
+       # top face
+       pushmatrix()
+       translate(0.0, CUBE_SIZE, 0.0)
+       rotate(-900, 'x')
+       color(MAGENTA)
+       rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+       popmatrix()
+       #
+       # bottom face
+       pushmatrix()
+       translate(0.0, -CUBE_SIZE, 0.0)
+       rotate(900, 'x')
+       color(YELLOW)
+       rectf(-CUBE_SIZE,-CUBE_SIZE,CUBE_SIZE,CUBE_SIZE)
+       popmatrix()
+
+def drawcube(x,y) :
+       #
+       pushmatrix()
+       rotate(2*x, 'x')
+       rotate(2*y, 'y')
+       color(BLACK)
+       clear()
+       cube()        
+       popmatrix()
+       swapbuffers()
+
+
+main ()
diff --git a/Demo/sgi/gl/glstdwin/fontchart.py b/Demo/sgi/gl/glstdwin/fontchart.py
new file mode 100644 (file)
index 0000000..6b58f12
--- /dev/null
@@ -0,0 +1,34 @@
+import stdwingl
+
+import stdwin
+from stdwinevents import *
+
+def main():
+       size = 12
+       w = stdwin.open('Font chart ' + `size`)
+       while 1:
+               type, window, detail = stdwin.getevent()
+               if type == WE_CLOSE:
+                       break
+               if type == WE_DRAW:
+                       width, height = w.getwinsize()
+                       d = w.begindrawing()
+                       d.setsize(size)
+                       h, v = 0, 0
+                       for c in range(32, 256):
+                               ch = chr(c)
+                               chw = d.textwidth(ch)
+                               if h + chw > width:
+                                       v = v + d.lineheight()
+                                       h = 0
+                                       if v >= height:
+                                               break
+                               d.text((h, v), ch)
+                               h = h + chw
+                       del d
+               if type == WE_MOUSE_UP:
+                       size = size + 1
+                       w.settitle('Font chart ' + `size`)
+                       w.change((0, 0), (2000, 2000))
+
+main()
diff --git a/Demo/sgi/gl/glstdwin/glstdwdraw.py b/Demo/sgi/gl/glstdwin/glstdwdraw.py
new file mode 100644 (file)
index 0000000..0092065
--- /dev/null
@@ -0,0 +1,135 @@
+# Define drawing operations for GL stdwin
+
+import gl
+import fm
+from GL import LO_XOR, LO_SRC
+from glstdwin import MASK
+
+class DrawingObject:
+       #
+       def _init(self, win):
+               self.fg = win._fg
+               self.bg = win._bg
+               self.font = win._font
+               self.size = win._size
+               self.width, self.height = win._area[1]
+               gl.winset(win._gid)
+               gl.color(self.fg)
+               return self
+       #
+       def setfont(self, fontname):
+               self.font = fm.findfont(fontname).scalefont(self.size)
+       #
+       def setsize(self, size):
+               ratio = float(size) / float(self.size)
+               self.size = size
+               self.font = self.font.scalefont(ratio)
+       #
+       def setfgcolor(self, color):
+               self.fg = color
+               gl.color(self.fg)
+       #
+       def setbgcolor(self, color):
+               self.bg = color
+       #
+       def cliprect(self, area):
+               #print 'cliprect', area
+               (left, top), (right, bottom) = area
+               gl.scrmask(left, right, self.height-bottom, self.height-top)
+       #
+       def noclip(self):
+               #print 'noclip()'
+               gl.scrmask(0, self.width, 0, self.height)
+       #
+       def paint(self, ((left, top), (right, bottom))):
+               gl.rectf(left, top, right, bottom)
+       #
+       def box(self, ((left, top), (right, bottom))):
+               #print 'box', ((left, top), (right, bottom))
+               gl.rect(left, top, right, bottom)
+       #
+       def circle(self, ((h, v), radius)):
+               gl.circ(h, v, radius)
+       #
+       def elarc(self, (center, (rh, rv), a1, a2)):
+               pass # XXX
+       #
+       def erase(self, ((left, top), (right, bottom))):
+               #print 'erase', ((left, top), (right, bottom))
+               gl.color(self.bg)
+               gl.rectf(left, top, right, bottom)
+               gl.color(self.fg)
+       #
+       def invert(self, ((left, top), (right, bottom))):
+               #print 'invert', ((h0, v0), (h1, v1))
+               gl.logicop(LO_XOR)
+               gl.color(self.bg)
+               gl.rectf(left, top, right, bottom)
+               gl.color(self.fg)
+               gl.logicop(LO_SRC)
+       #
+       def line(self, ((h0, v0), (h1, v1))):
+               #print 'line', ((h0, v0), (h1, v1))
+               gl.bgnline()
+               gl.v2i(h0, v0)
+               gl.v2i(h1, v1)
+               gl.endline()
+       #
+       def xorline(self, ((h0, v0), (h1, v1))):
+               #print 'xorline', ((h0, v0), (h1, v1))
+               gl.logicop(LO_XOR)
+               gl.color(self.bg)
+               gl.bgnline()
+               gl.v2i(h0, v0)
+               gl.v2i(h1, v1)
+               gl.endline()
+               gl.color(self.fg)
+               gl.logicop(LO_SRC)
+       #
+       def point(self, (h, v)):
+               #print 'point', (h, v)
+               gl.bgnpoint()
+               gl.v2i(h, v)
+               gl.endpoint()
+       #
+       def text(self, ((h, v), string)):
+               #print 'text', ((h, v), string)
+               if h < 0:
+                       # If the point is outside the window
+                       # the whole string isn't drawn.
+                       # Skip the beginning of the string.
+                       # XXX What if the font is bigger than 20 pixels?
+                       i, n = 0, len(string)
+                       while h < -MASK and i < n:
+                               h = h + self.font.getstrwidth(string[i])
+                               i = i + 1
+                       string = string[i:]
+               gl.cmov2(h, v + self.baseline())
+               self.font.setfont()
+               fm.prstr(string)
+       #
+       def shade(self, ((h, v), percent)):
+               pass # XXX
+       #
+       def baseline(self):
+               (printermatched, fixed_width, xorig, yorig, xsize, ysize, \
+                       height, nglyphs) = self.font.getfontinfo()
+               return height - yorig
+       #
+       def lineheight(self):
+               (printermatched, fixed_width, xorig, yorig, xsize, ysize, \
+                       height, nglyphs) = self.font.getfontinfo()
+               return height
+       #
+       def textbreak(self, (string, width)):
+               # XXX Slooooow!
+               n = len(string)
+               nwidth = self.textwidth(string[:n])
+               while nwidth > width:
+                       n = n-1
+                       nwidth = self.textwidth(string[:n])
+               return n
+       #
+       def textwidth(self, string):
+               return self.font.getstrwidth(string)
+       #
diff --git a/Demo/sgi/gl/glstdwin/glstdwin.py b/Demo/sgi/gl/glstdwin/glstdwin.py
new file mode 100644 (file)
index 0000000..2228554
--- /dev/null
@@ -0,0 +1,400 @@
+# GL STDWIN
+#
+# See stdwingl for a convenient hack to use this instead of built-in stdwin
+# without modifying your application, except for one line in the main file.
+#
+# Intrinsic differences with built-in stdwin (hard or impossible to fix):
+# - Need to call w.close() to close a window !!!
+# - Need to call m.close() to remove a menu !!!
+# - Doesn't enforce the existence of at most one drawing object
+# - No textedit package
+# - No X11 selections
+#
+# Not yet implemented:
+# - shade drawing
+# - elliptical arc drawing (need to play with transformation)
+# - more than one mouse button
+# - scroll bars (need to redo viewport handling to get this)
+# - partial redraws
+# - dialog boxes
+# - timer events
+# - cursors
+#
+# Extra features:
+# - color (for now, you need to know the colormap index)
+
+
+import gl
+import fm
+from GL import *
+from DEVICE import *
+from stdwinevents import *
+
+
+# Customizable constants
+#
+DEF_FONT = 'Times-Roman'               # Default font
+DEF_SIZE = 12                          # Default font size (points)
+MASK = 20                              # Viewport minus scrmask
+
+
+# A structure to hold global variables
+#
+class Struct: pass
+G = Struct()
+#
+G.queue = []                           # Pending STDWIN events
+G.drawqueue = []                       # Windows that need WE_REDRAW
+G.windowmap = {}                       # Map window id to window object
+G.windowmap['0'] = None                        # For convenience
+G.focus = None                         # Input focus
+G.fg = BLACK                           # Foreground color
+G.bg = WHITE                           # Background color
+G.def_size = 0, 0                      # Default window size
+G.def_pos = 0, 0                       # Default window position
+#
+G.size = DEF_SIZE
+G.font = fm.findfont(DEF_FONT).scalefont(G.size)
+
+
+# Initialize GL
+#
+gl.foreground()
+gl.noport()
+dummygid = gl.winopen('')
+
+# Ask for all sorts of events
+#
+# Both REDRAW (= resize and/or redraw!) and INPUTCHANGE are implicitly queued
+#qdevice(REDRAW)
+#qdevice(INPUTCHANGE)
+#
+# Keyboard
+gl.qdevice(KEYBD)
+gl.qdevice(LEFTARROWKEY)
+gl.qdevice(RIGHTARROWKEY)
+gl.qdevice(UPARROWKEY)
+gl.qdevice(DOWNARROWKEY)
+gl.qdevice(LEFTALTKEY)
+gl.qdevice(RIGHTALTKEY)
+#
+# Mouse
+gl.qdevice(LEFTMOUSE)
+#gl.qdevice(MIDDLEMOUSE)
+gl.qdevice(RIGHTMOUSE)                 # Menu button
+# NB MOUSEX, MOUSEY events are queued on button down
+#
+# Window close requests
+gl.qdevice(WINQUIT)
+gl.qdevice(WINSHUT)
+#
+# These aren't needed
+#gl.qdevice(TIMER0)
+#gl.qdevice(WINFREEZE)
+#gl.qdevice(WINTHAW)
+#gl.qdevice(REDRAWICONIC)
+
+
+# STDWIN: create a new window
+#
+def open(title):
+       h, v = G.def_pos
+       width, height = G.def_size
+       if h > 0 or v > 0:
+               # Choose arbitrary defaults
+               if h < 0: h = 10
+               if v < 0: v = 30
+               if width <= 0: width = 400
+               if height <= 0: height = 300
+               gl.prefposition(h, h+width, 1024-v, 1024-v-height)
+       elif width > 0 or height > 0:
+               if width <= 0: width = 400
+               if height <= 0: height = 300
+               gl.prefsize(width, height)
+       from glstdwwin import WindowObject
+       win = WindowObject()._init(title)
+       G.windowmap[`win._gid`] = win
+       return win
+
+
+# STDWIN: set default initial window position (0 means use default)
+#
+def setdefwinpos(h, v):
+       G.def_pos = h, v
+
+
+# STDWIN: set default window size (0 means use default)
+#
+def setdefwinsize(width, height):
+       G.def_size = width, height
+
+
+# STDWIN: beep or ring the bell
+#
+def fleep():
+       gl.ringbell()
+
+
+# STDWIN: set default foreground color
+#
+def setfgcolor(color):
+       G.fg = color
+
+
+# STDWIN: set default background color
+#
+def setbgcolor(color):
+       G.bg = color
+
+
+# STDWIN: get default foreground color
+#
+def getfgcolor():
+       return G.fgcolor
+
+
+# STDWIN: get default background color
+#
+def getbgcolor():
+       return G.bgcolor
+
+
+# Table mapping characters to key codes
+#
+key2code = key = {}
+key['A'] = AKEY
+key['B'] = BKEY
+key['C'] = CKEY
+key['D'] = DKEY
+key['E'] = EKEY
+key['F'] = FKEY
+key['G'] = GKEY
+key['H'] = HKEY
+key['I'] = IKEY
+key['J'] = JKEY
+key['K'] = KKEY
+key['L'] = LKEY
+key['M'] = MKEY
+key['N'] = NKEY
+key['O'] = OKEY
+key['P'] = PKEY
+key['Q'] = QKEY
+key['R'] = RKEY
+key['S'] = SKEY
+key['T'] = TKEY
+key['U'] = UKEY
+key['V'] = VKEY
+key['W'] = WKEY
+key['X'] = XKEY
+key['Y'] = YKEY
+key['Z'] = ZKEY
+key['0'] = ZEROKEY
+key['1'] = ONEKEY
+key['2'] = TWOKEY
+key['3'] = THREEKEY
+key['4'] = FOURKEY
+key['5'] = FIVEKEY
+key['6'] = SIXKEY
+key['7'] = SEVENKEY
+key['8'] = EIGHTKEY
+key['9'] = NINEKEY
+del key
+#
+code2key = {}
+codelist = []
+for key in key2code.keys():
+       code = key2code[key]
+       code2key[`code`] = key
+       codelist.append(code)
+del key
+
+
+# STDWIN: wait for the next event
+#
+commands = {}
+commands['\r'] = WC_RETURN
+commands['\b'] = WC_BACKSPACE
+commands['\t'] = WC_TAB
+#
+def getevent():
+  while 1:
+       #
+       # Get next event from the processed queue, if any
+       #
+       if G.queue:
+               event = G.queue[0]
+               del G.queue[0]
+               #print 'getevent from queue -->', event
+               return event
+       #
+       # Get next event from the draw queue, if any,
+       # but only if there is nothing in the system queue.
+       #
+       if G.drawqueue and not gl.qtest():
+               win = G.drawqueue[0]
+               del G.drawqueue[0]
+               gl.winset(win._gid)
+               gl.color(win._bg)
+               gl.clear()
+               event = WE_DRAW, win, win._area
+               #print 'getevent from drawqueue -->', event
+               return event
+       #
+       # Get next event from system queue, blocking if necessary
+       # until one is available.
+       # Some cases immediately return the event, others do nothing
+       # or append one or more events to the processed queue.
+       #
+       dev, val = gl.qread()
+       #
+       if dev == REDRAW:
+               win = G.windowmap[`val`]
+               old_area = win._area
+               win._fixviewport()
+               win._needredraw()
+               if old_area <> win._area:
+                       #print 'getevent --> WE_SIZE'
+                       return WE_SIZE, win, None
+       elif dev == KEYBD:
+               if val == 3:
+                       raise KeyboardInterrupt # Control-C in window
+               character = chr(val)
+               if commands.has_key(character):
+                       return WE_COMMAND, G.focus, commands[character]
+               return WE_CHAR, G.focus, character
+       elif dev == LEFTARROWKEY:
+               if val:
+                       return WE_COMMAND, G.focus, WC_LEFT
+       elif dev == RIGHTARROWKEY:
+               if val:
+                       return WE_COMMAND, G.focus, WC_RIGHT
+       elif dev == UPARROWKEY:
+               if val:
+                       return WE_COMMAND, G.focus, WC_UP
+       elif dev == DOWNARROWKEY:
+               if val:
+                       return WE_COMMAND, G.focus, WC_DOWN
+       elif dev in (LEFTALTKEY, RIGHTALTKEY):
+               if val:
+                       for code in codelist:
+                               gl.qdevice(code)
+               else:
+                       for code in codelist:
+                               gl.unqdevice(code)
+       elif dev in codelist:
+               if val:
+                       event = G.focus._doshortcut(code2key[`dev`])
+                       if event:
+                               return event
+       elif dev == LEFTMOUSE:
+               G.mousex = gl.getvaluator(MOUSEX)
+               G.mousey = gl.getvaluator(MOUSEY)
+               if val:
+                       type = WE_MOUSE_DOWN
+                       gl.qdevice(MOUSEX)
+                       gl.qdevice(MOUSEY)
+               else:
+                       type = WE_MOUSE_UP
+                       gl.unqdevice(MOUSEX)
+                       gl.unqdevice(MOUSEY)
+               return _mouseevent(type)
+       elif dev == MOUSEX:
+               G.mousex = val
+               return _mouseevent(WE_MOUSE_MOVE)
+       elif dev == MOUSEY:
+               G.mousey = val
+               return _mouseevent(WE_MOUSE_MOVE)
+       elif dev == RIGHTMOUSE:         # Menu button press/release
+               if val:                 # Press
+                       event = G.focus._domenu()
+                       if event:
+                               return event
+       elif dev == INPUTCHANGE:
+               if G.focus:
+                       G.queue.append(WE_DEACTIVATE, G.focus, None)
+               G.focus = G.windowmap[`val`]
+               if G.focus:
+                       G.queue.append(WE_ACTIVATE, G.focus, None)
+       elif dev in (WINSHUT, WINQUIT):
+               return WE_CLOSE, G.windowmap[`val`], None
+       else:
+               print '*** qread() --> dev:', dev, 'val:', val
+
+# Helper routine to construct a mouse (up, move or down) event
+#
+def _mouseevent(type):
+       gl.winset(G.focus._gid)
+       orgx, orgy = gl.getorigin()
+       sizex, sizey = gl.getsize()
+       x = G.mousex - orgx
+       y = G.mousey - orgy
+       return type, G.focus, ((x, sizey-y), 1, 0, 0)
+
+
+
+
+# STDWIN: text measuring functions
+
+def baseline():
+       (printermatched, fixed_width, xorig, yorig, xsize, ysize, \
+               height, nglyphs) = G.font.getfontinfo()
+       return height - yorig
+
+def lineheight():
+       (printermatched, fixed_width, xorig, yorig, xsize, ysize, \
+                       height, nglyphs) = G.font.getfontinfo()
+       return height
+
+def textbreak(string, width):
+       # XXX Slooooow!
+       n = len(string)
+       nwidth = textwidth(string[:n])
+       while nwidth > width:
+               n = n-1
+               nwidth = textwidth(string[:n])
+       return n
+
+def textwidth(string):
+       return G.font.getstrwidth(string)
+
+
+# STDWIN: set default font and size
+
+def setfont(fontname):
+       G.font = fm.findfont(fontname).scalefont(G.size)
+
+def setsize(size):
+       ratio = float(size) / float(G.size)
+       G.size = size
+       G.font = G.font.scalefont(ratio)
+
+
+# Utility functions
+
+# Exclusive-or of two BYTES
+#
+def xor(x, y):
+       a = bits(x)
+       b = bits(y)
+       c = [0, 0, 0, 0, 0, 0, 0, 0]
+       for i in range(8):
+               c[i] = (a[i] + b[i]) % 2
+       return stib(c)
+
+# Return the bits of a byte as a list of 8 integers
+#
+def bits(x):
+       b = [0, 0, 0, 0, 0, 0, 0, 0]
+       for i in range(8):
+               x, b[i] = divmod(x, 2)
+       return b
+
+# Convert a list of 8 integers (0|1) to a byte
+#
+def stib(b):
+       x = 0
+       shift = 1
+       for i in range(8):
+               x = x + b[i]*shift
+               shift = shift*2
+       return x
diff --git a/Demo/sgi/gl/glstdwin/glstdwmenu.py b/Demo/sgi/gl/glstdwin/glstdwmenu.py
new file mode 100644 (file)
index 0000000..64eb333
--- /dev/null
@@ -0,0 +1,60 @@
+# Define menu operations for GL stdwin
+
+import gl
+from glstdwin import key2code
+
+class MenuObject:
+       #
+       def _init(self, (win, title)):
+               self._win = win
+               self._title = title
+               self._items = []
+               return self
+       #
+       def close(self):
+               self._win.remove(self)
+               del self._win
+       #
+       def additem(self, arg):
+               if type(arg) == type(()):
+                       text, shortcut = arg
+               else:
+                       text, shortcut = arg, None
+               self._items.append([text, shortcut, 1, 0])
+       #
+       def setitem(self, (i, text)):
+               self._items[i][0] = text
+       #
+       def enable(self, (i, flag)):
+               self._items[i][2] = flag
+       #
+       def check(self, (i, flag)):
+               self._items[i][3] = flag
+       #
+       def _makepup(self, firstitem):
+               pup = gl.newpup()
+               if self._title:
+                       gl.addtopup(pup, self._title + '%t', 0)
+               for item in self._items:
+                       text = item[0]
+                       if not item[2]: # Disabled
+                               text = ' ( ' + text + ' )%x-1'
+                       else:
+                               if item[3]: # Check mark
+                                       text = '-> ' + text
+                               else:
+                                       text = '    ' + text
+                               if key2code.has_key(item[1]):
+                                       text = text + '  [Alt-' + item[1] + ']'
+                               text = text + '%x' + `firstitem`
+                       gl.addtopup(pup, text, 0)
+                       firstitem = firstitem + 1
+               return pup
+       #
+       def _checkshortcut(self, char):
+               for i in range(len(self._items)):
+                       item = self._items[i]
+                       if item[2] and item[1] == char:
+                               return i
+               return -1
+       #
diff --git a/Demo/sgi/gl/glstdwin/glstdwwin.py b/Demo/sgi/gl/glstdwin/glstdwwin.py
new file mode 100644 (file)
index 0000000..e024545
--- /dev/null
@@ -0,0 +1,139 @@
+# Define window operations for STDWIN
+
+import gl
+from stdwinevents import *
+from glstdwin import G                 # Global variables
+from glstdwin import MASK              # Tunable constant
+
+class WindowObject:
+       #
+       def _init(self, title):
+               self._docsize = (0, 0)
+               self._fg = G.fg
+               self._bg = G.bg
+               self._title = title
+               self._font = G.font
+               self._size = G.size
+               self._menus = []
+               self._gid = gl.winopen(title)
+               gl.winconstraints() # To remove prefsize() effect
+               self._fixviewport()
+               self._needredraw()
+               return self
+       #
+       def close(self):
+               del G.windowmap[`self._gid`]
+               gl.winclose(self._gid)
+               self._gid = 0
+       #
+       def _needredraw(self):
+               if self in G.drawqueue:
+                       G.drawqueue.remove(self)
+               G.drawqueue.append(self)
+       #
+       def begindrawing(self):
+               from glstdwdraw import DrawingObject
+               return DrawingObject()._init(self)
+       #
+       def change(self, area):
+               self._needredraw()
+               # XXX Should record the area to be drawn?
+       #
+       def gettitle(self):
+               return self._title
+       #
+       def getdocsize(self):
+               return self._docsize
+       #
+       def getorigin(self):
+               return self._area[0]
+       #
+       def getwinsize(self):
+               return self._area[1]
+       #
+       def scroll(self, (area, by)):
+               # XXX ought to use gl.rectcopy()
+               if by <> (0, 0):
+                       self.change(area)
+       #
+       def setdocsize(self, docsize):
+               self._docsize = docsize
+       #
+       def setorigin(self, origin):
+               pass # XXX
+       #
+       def settimer(self, decisecs):
+               pass # XXX
+       #
+       def settitle(self, title):
+               self._title = title
+               gl.wintitle(title)
+       #
+       def show(self, area):
+               pass # XXX
+       #
+       def _fixviewport(self):
+               #
+               # Called after redraw or resize, and initially.
+               #
+               # Fix the coordinate system so that (0, 0) is top left,
+               # units are pixels, and positive axes point right and down.
+               #
+               # Make the viewport slightly larger than the window,
+               # and set the screenmask exactly to the window; this
+               # help fixing character clipping.
+               #
+               # Set self._area to the window rectangle in STDWIN coords.
+               #
+               gl.winset(self._gid)
+               gl.reshapeviewport()
+               x0, x1, y0, y1 = gl.getviewport()
+               width, height = x1-x0, y1-y0
+               gl.viewport(x0-MASK, x1+MASK, y0-MASK, y1+MASK)
+               gl.scrmask(x0, x1, y0, y1)
+               gl.ortho2(-MASK, width+MASK, height+MASK, -MASK)
+               self._area = (0, 0), (width, height)
+       #
+       def menucreate(self, title):
+               from glstdwmenu import MenuObject
+               menu = MenuObject()._init(self, title)
+               self._menus.append(menu)
+               return menu
+       #
+       def _domenu(self):
+               if not self._menus:
+                       return None
+               if len(self._menus) == 1:
+                       pup = self._menus[0]._makepup(0)
+                       val = gl.dopup(pup)
+                       gl.freepup(pup)
+                       if val < 0:
+                               return None
+                       return WE_MENU, self, (self._menus[0], val)
+               #
+               # More than one menu: use nested menus.
+               #
+               pups = []
+               firstitem = 0
+               for menu in self._menus:
+                       pups.append(menu._makepup(firstitem))
+                       firstitem = firstitem + 100
+               pup = gl.newpup()
+               for i in range(len(self._menus)):
+                       gl.addtopup(pup, self._menus[i]._title + '%m', pups[i])
+               val = gl.dopup(pup)
+               gl.freepup(pup)
+               for pup in pups:
+                       gl.freepup(pup)
+               if val < 0:
+                       return None
+               i_menu, i_item = divmod(val, 100)
+               return WE_MENU, self, (self._menus[i_menu], i_item)
+       #
+       def _doshortcut(self, char):
+               for menu in self._menus:
+                       i = menu._checkshortcut(char)
+                       if i >= 0:
+                               return WE_MENU, self, (menu, i)
+               return None
+       #
diff --git a/Demo/sgi/gl/glstdwin/stdwingl.py b/Demo/sgi/gl/glstdwin/stdwingl.py
new file mode 100644 (file)
index 0000000..4427593
--- /dev/null
@@ -0,0 +1,10 @@
+# If you put 'import stdwin_gl' in front of the main program of a program
+# using stdwin (before it has a chance to import the real stdwin!),
+# it will use glstdwin and think it is stdwin.
+
+import sys
+if sys.modules.has_key('stdwin'):
+       raise RuntimeError, 'too late -- stdwin has already been imported'
+
+import glstdwin
+sys.modules['stdwin'] = glstdwin
diff --git a/Demo/sgi/gl/glstdwin/tcolor.py b/Demo/sgi/gl/glstdwin/tcolor.py
new file mode 100644 (file)
index 0000000..cf96158
--- /dev/null
@@ -0,0 +1,43 @@
+# Try colors -- display all 256 possible colors, with their color index
+
+# import stdwingl
+
+import stdwin
+from stdwinevents import *
+
+NROWS = 16
+NCOLS = 16
+
+def main():
+       stdwin.setdefwinsize(NCOLS * stdwin.textwidth('12345'), \
+                               NROWS * stdwin.lineheight() * 3)
+       w = stdwin.open('TestColors')
+       #
+       while 1:
+               type, window, detail = stdwin.getevent()
+               if type == WE_CLOSE:
+                       print 'Bye.'
+                       break
+               elif type == WE_SIZE:
+                       w.change((0,0), (10000, 10000))
+               elif type == WE_DRAW:
+                       width, height = w.getwinsize()
+                       d = w.begindrawing()
+                       for row in range(NROWS):
+                               for col in range(NCOLS):
+                                       color = row*NCOLS + col
+                                       d.setfgcolor(color)
+                                       p = col*width/NCOLS, row*height/NROWS
+                                       q = (col+1)*width/NCOLS, \
+                                               (row+1)*height/NROWS
+                                       d.paint(p, q)
+                                       d.setfgcolor(0)
+                                       d.box(p, q)
+                                       d.text(p, `color`)
+                                       p = p[0] , p[1]+ d.lineheight()
+                                       d.setfgcolor(7)
+                                       d.text(p, `color`)
+                       del d
+       #
+
+main()
diff --git a/Demo/sgi/gl/glstdwin/tglsw.py b/Demo/sgi/gl/glstdwin/tglsw.py
new file mode 100644 (file)
index 0000000..c066c4d
--- /dev/null
@@ -0,0 +1,70 @@
+import sys
+
+if len(sys.argv) < 2:
+       import stdwingl
+       color = 1
+       needclose = 1
+else:
+       color = 0
+       needclose = 0
+
+import stdwin
+import time
+from stdwinevents import *
+from GL import BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE
+
+def main():
+       #
+       stdwin.setdefwinsize(300, 300)
+       stdwin.setdefwinpos(0, 0)
+       if color: stdwin.setbgcolor(YELLOW)
+       w1 = stdwin.open('Hello, world')
+       w1.box = (10, 10), (90, 90)
+       #
+       stdwin.setdefwinsize(0, 0)
+       stdwin.setdefwinpos(50, 50)
+       if color: stdwin.setbgcolor(GREEN)
+       w2 = stdwin.open('Second window')
+       w2.box = (10, 10), (90, 90)
+       #
+       while w1 or w2:
+               type, window, detail = stdwin.getevent()
+               if type == WE_DRAW:
+                       d = window.begindrawing()
+                       if window == w1:
+                               if color: d.setfgcolor(BLACK)
+                               d.box((50, 50), (250, 250))
+                               if color: d.setfgcolor(RED)
+                               d.cliprect((50, 50), (250, 250))
+                               d.paint(w1.box)
+                               d.noclip()
+                               if color: d.setfgcolor(BLUE)
+                               d.line((0, 0), w1.box[0])
+                       elif window == w2:
+                               if color: d.setfgcolor(WHITE)
+                               d.box(w2.box)
+                               if color: d.setfgcolor(BLACK)
+                               d.text(w2.box[0], 'Hello world')
+                       else:
+                               print 'Strange draw???', window, detail
+                       del d
+               elif type == WE_CLOSE:
+                       if needclose: window.close()
+                       if window == w1:
+                               w1 = None
+                       elif window == w2:
+                               w2 = None
+                       else:
+                               print 'weird close event???', window, detail
+               elif type in (WE_MOUSE_DOWN, WE_MOUSE_MOVE, WE_MOUSE_UP):
+                       h, v = detail[0]
+                       window.box = (h, v), (h+80, v+80)
+                       window.change((0,0), (2000, 2000))
+               elif type == WE_CHAR:
+                       print 'character', `detail`
+               else:
+                       print type, window, detail
+       #
+
+main()
+print 'Done.'
diff --git a/Demo/sgi/gl/glstdwin/tmenu.py b/Demo/sgi/gl/glstdwin/tmenu.py
new file mode 100644 (file)
index 0000000..97c6bc6
--- /dev/null
@@ -0,0 +1,44 @@
+# Test menus
+
+import stdwingl
+
+import stdwin
+from stdwinevents import *
+
+def main():
+       w = stdwin.open('TestMenus')
+       #
+       items1 = 'Aap', 'Noot', 'Mies'
+       m1 = w.menucreate('Menu-1')
+       for item in items1:
+               m1.additem(item, item[0])
+       #
+       items2 = 'Wim', 'Zus', 'Jet', 'Teun', 'Vuur'
+       m2 = w.menucreate('Menu-2')
+       for item in items2:
+               m2.additem(item, `len(item)`)
+       #
+       m1.enable(1, 0)
+       m2.check(1, 1)
+       #
+       while 1:
+               type, window, detail = stdwin.getevent()
+               if type == WE_CLOSE:
+                       break
+               elif type == WE_DRAW:
+                       d = w.begindrawing()
+                       d.box((50,50), (100,100))
+                       del d
+               elif type == WE_MENU:
+                       mp, i = detail
+                       if mp == m1:
+                               print 'Choice:', items1[i]
+                       elif mp == m2:
+                               print 'Choice:', items2[i]
+                       else:
+                               print 'Not one of my menus!'
+               elif type == WE_CHAR:
+                       print 'Character', `detail`
+       #
+
+main()
diff --git a/Demo/sgi/gl/kites.py b/Demo/sgi/gl/kites.py
new file mode 100755 (executable)
index 0000000..d986833
--- /dev/null
@@ -0,0 +1,194 @@
+#! /usr/local/python
+
+# *** This only works correctly on a 24 bit-plane machine. ***
+#
+# A simple Python program that tests the some parts of the
+# GL library. It shows the speed that can be obtained when
+# doing simple graphics.
+#
+# The bottleneck in this program is NOT Python but the graphics
+# engine; i.e Python can feed the graphics pipeline fast enough
+# on the 4D/25G.
+#
+# This program show 3 kites flying around the screen. It uses
+#
+#      * bgnpolygon, endpolygon
+#      * v3, n3
+#      * lmdef, lmbind
+#
+# Usage :
+# 
+#      ESC     -> exit program
+#      MOUSE3  -> freeze toggle
+#      MOUSE2  -> one step (use this in freeze state)
+
+from GL import *
+from gl import *
+import DEVICE
+from math import *
+
+#
+# viewobj : sets the rotation, translation and scaling
+# set appropiate material, call drawobject()
+#
+def viewobj (r, s, t, mat) :
+       pushmatrix()
+       rot (r * 10.0, 'X')
+       rot (r * 10.0, 'Y')
+       rot (r * 10.0, 'Z')
+       scale (s[0], s[1], s[2])
+       translate (t[0], t[1], t[2])
+       lmbind(MATERIAL, mat)
+       drawobject()
+       popmatrix()
+
+#
+# makeobj : the contructor of the object
+#
+def mkobj () :
+       v0 = (-5.0 ,0.0, 0.0)
+       v1 = (0.0 ,5.0, 0.0)
+       v2 = (5.0 ,0.0, 0.0)
+       v3 = (0.0 ,2.0, 0.0)
+       n0 = (sqrt(2.0)/2.0, sqrt(2.0)/2.0, 0.0)
+       vn = ((v0, n0), (v1, n0), (v2, n0), (v3, n0))
+       #
+       return vn
+
+#
+# the object itself as an array of vertices and normals
+#
+kite = mkobj ()
+
+#
+# drawobject : draw a triangle. with bgnpolygon
+#
+def drawobject () :
+       #
+       bgnpolygon()
+       vnarray (kite)
+       endpolygon()
+
+#
+# identity matrix
+#
+idmat=[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]
+
+#
+# the rgb-value of light-blue 
+#
+LightBlue = (43,169,255)
+
+#
+# the different materials.
+#
+m1=[SPECULAR,0.0,0.0,0.6,DIFFUSE,0.0,0.0,0.8,SHININESS,20.0,LMNULL]
+m2=[SPECULAR,0.8,0.0,0.1,DIFFUSE,0.8,0.0,0.3,SHININESS,120.0,LMNULL]
+m3=[SPECULAR,0.0,1.0,0.0,DIFFUSE,0.0,0.6,0.0,SHININESS,120.0,LMNULL]
+
+#
+# lightsources
+#
+light1 = [LCOLOR,1.0,1.0,1.0,POSITION,15.0,15.0,0.0,1.0,LMNULL]
+light2 = [LCOLOR,1.0,1.0,1.0,POSITION,-15.0,15.0,0.0,1.0,LMNULL]
+
+#
+# the lightmodel
+#
+model = [AMBIENT,0.2,0.2,0.2,LMNULL]
+
+#
+# initgl : opens the window, configures the pipeline to 2buf and zbuf,
+# sets the viewing, defines and binds the materials
+#
+def initgl () :
+       #
+       # open window
+       #
+       foreground ()
+       keepaspect (1, 1)
+       prefposition (100, 500, 100, 500)
+       w = winopen ('PYTHON lights')
+       keepaspect (1, 1)
+       winconstraints()
+       #
+       # configure pipeline (zbuf, 2buf, GOURAUD and RGBmode)
+       #
+       zbuffer (1)
+       doublebuffer ()
+       shademodel (GOURAUD)
+       RGBmode ()
+       gconfig ()
+       #
+       # define and bind materials (set perspective BEFORE loadmat !)
+       #
+       mmode(MVIEWING)
+       perspective (900, 1.0, 1.0, 20.0)
+       loadmatrix(idmat)
+       lmdef(DEFMATERIAL, 1, m1)
+       lmdef(DEFMATERIAL, 2, m2)
+       lmdef(DEFMATERIAL, 3, m3)
+       lmdef(DEFLIGHT, 1, light1)
+       lmdef(DEFLIGHT, 2, light2)
+       lmdef(DEFLMODEL, 1, model)
+       lmbind(LIGHT0,1)
+       lmbind(LIGHT1,2)
+       lmbind(LMODEL,1)
+       #
+       # set viewing
+       #
+       lookat (0.0, 0.0, 10.0, 0.0, 0.0, 0.0, 0)
+       #
+       # ask for the REDRAW and ESCKEY events
+       #
+       qdevice(DEVICE.MOUSE3)
+       qdevice(DEVICE.MOUSE2)
+       qdevice(DEVICE.REDRAW)
+       qdevice(DEVICE.ESCKEY)
+
+#
+# GoForIT : use 2buf to redraw the object 2n times. index i is used as 
+# the (smoothly changing) rotation angle
+#
+def GoForIt(i) :
+       freeze = 1
+       while 1 :
+               if freeze <> 0 :
+                       i = i + 1
+               #
+               # clear z-buffer and clear background to light-blue
+               #
+               zclear()
+               c3i (LightBlue)
+               clear()
+               #
+               # draw the 3 traiangles scaled above each other.
+               #
+               viewobj(float(i),[1.0,1.0,1.0],[1.0,1.0,1.0],1)
+               viewobj(float(i),[0.75,0.75,0.75],[0.0,2.0,2.0],2)
+               viewobj(float(i),[0.5,0.5,0.5],[0.0,4.0,4.0],3)
+               #
+               swapbuffers()
+               #
+               if qtest() <> 0 :
+                       dev, val = qread()
+                       if dev == DEVICE.ESCKEY :
+                               break
+                       elif dev == DEVICE.REDRAW :
+                               reshapeviewport ()
+                       elif dev == DEVICE.MOUSE3 and val <> 0 :
+                               freeze = 1 - freeze
+                       elif dev == DEVICE.MOUSE2 and val <> 0 :
+                               i = i + 1
+
+
+# the main program
+#
+def main () :
+       initgl ()
+       GoForIt (0)
+
+#
+# exec main
+#
+main  ()
diff --git a/Demo/sgi/gl/kunst.py b/Demo/sgi/gl/kunst.py
new file mode 100755 (executable)
index 0000000..8fb982e
--- /dev/null
@@ -0,0 +1,446 @@
+#!/ufs/guido/bin/sgi/python
+# Simulate the artwork in the hall.
+# Jack Jansen, Feb 91.
+#
+# Please please please don't try to read this code.
+# It is the first GL program I ever wrote, and used to do
+# very different things before it's current function:-)
+from gl import *
+from GL import *
+from math import *
+from DEVICE import *
+import sys
+import __main__
+main_dict = __main__.__dict__
+
+SPOTDIRECTION = 103
+SPOTLIGHT = 104
+
+#
+# Make a cylinder paralel with the Z axis with center (X,Y,0)
+# and radius 1
+def mkcyl(nslice, nparts, docircle):
+       cyl = []
+       step = 2.0 / float(nslice)
+       z = -1.0
+       for i in range(nslice):
+           cyl.append(mkslice(z, z+step, nparts, docircle))
+           z = z + step
+       return drawcylinder(cyl)
+#
+# Make one part of a cylinder
+#
+def mkslice(z1, z2, nparts, docircle):
+       if docircle:
+           w1 = z1
+           w2 = z2
+           w1 = sqrt(1.0-w1*w1)
+           w2 = sqrt(1.0-w2*w2)
+           normalz = 1.0
+       else:
+           w1 = 1.0
+           w2 = 1.0
+           normalz = 0.0
+       slice = []
+       step = (2.0*pi)/float(nparts)
+       angle = 0.0
+       for i in range(nparts+1):
+           vx = cos(angle)
+           vy = sin(angle)
+           slice.append( ((vx*w1,vy*w1,z1), (vx*w1, vy*w1, z1*normalz)) )
+           slice.append( ((vx*w2,vy*w2,z2), (vx*w2, vy*w2, z2*normalz)) )
+           angle = angle + step
+       return slice
+#
+# Drawcylinder : draw the cylinder
+#
+class struct(): pass
+curobj = struct()
+curobj.curobj = 1
+def drawcylinder(cyl):
+       obj = curobj.curobj
+       curobj.curobj = curobj.curobj+1
+       makeobj(obj)
+       for slice in cyl:
+           bgntmesh()
+           vnarray(slice)
+           endtmesh()
+       closeobj()
+       return obj
+#
+def drawnormals(cyl):
+       for slice in cyl:
+           for triang in slice:
+               bgnline()
+               v3f(triang[0])
+               v3f(triang[0][0] + triang[1][0], triang[0][1] + triang[1][1], triang[0][2] + triang[1][2])
+               endline()
+def drawfloors():
+       obj = curobj.curobj
+       curobj.curobj = curobj.curobj+1
+       makeobj(obj)
+       bgnpolygon()
+       v3i(4,6,-6)
+       v3i(-6,6,-6)
+       v3i(-6,-6,-6)
+       v3i(4,-6,-6)
+       endpolygon()
+       for floor in range(3):
+           pos = -1 + 5*floor
+           bgnpolygon()
+           v3i(4,4,pos)
+           v3i(-6,4,pos)
+           v3i(-6,6,pos)
+           v3i(4,6,pos)
+           endpolygon()
+           bgnpolygon()
+           v3i(-4,4,pos)
+           v3i(-4,-4,pos)
+           v3i(-6,-4,pos)
+           v3i(-6,4,pos)
+           endpolygon()
+           bgnpolygon()
+           v3i(-6,-4,pos)
+           v3i(-6,-6,pos)
+           v3i(4,-6,pos)
+           v3i(4,-4,pos)
+           endpolygon()
+       closeobj()
+       return obj
+def drawdoors():
+       obj = curobj.curobj
+       curobj.curobj = curobj.curobj+1
+       makeobj(obj)
+       for floor in range(3):
+           pos = -1+5*floor
+           bgnpolygon()
+           v3i(-2,6,pos)
+           v3i(-2,6,pos+3)
+           v3i(0,6,pos+3)
+           v3i(0,6,pos)
+           endpolygon()
+       closeobj()
+       return obj
+def drawrailing():
+       obj = curobj.curobj
+       curobj.curobj = curobj.curobj+1
+       makeobj(obj)
+       for floor in range(3):
+           pos = -1 + 5*floor
+           bgnpolygon()
+           v3i(4,4,pos)
+           v3i(4,4,pos-1)
+           v3i(-4,4,pos-1)
+           v3i(-4,4,pos)
+           endpolygon()
+           bgnpolygon()
+           v3i(-4,4,pos)
+           v3i(-4,4,pos-1)
+           v3i(-4,-4,pos-1)
+           v3i(-4,-4,pos)
+           endpolygon()
+           bgnpolygon()
+           v3i(-4,-4,pos)
+           v3i(-4,-4,pos-1)
+           v3i(4,-4,pos-1)
+           v3i(4,-4,pos)
+           endpolygon()
+       closeobj()
+       return obj
+def drawwalls():
+       obj = curobj.curobj
+       curobj.curobj = curobj.curobj+1
+       makeobj(obj)
+       bgnpolygon()
+       v3i(4,6,-6)
+       v3i(4,6,18)
+       v3i(-6,6,18)
+       v3i(-6,6,-6)
+       endpolygon()
+       bgnpolygon()
+       v3i(-6,6,-6)
+       v3i(-6,6,18)
+       v3i(-6,-6,18)
+       v3i(-6,-6,-6)
+       endpolygon()
+       bgnpolygon()
+       v3i(-6,-6,-6)
+       v3i(-6,-6,18)
+       v3i(4,-6,18)
+       v3i(4,-6,-6)
+       endpolygon()
+       bgnpolygon()
+       v3i(4,-6,-6)
+       v3i(4,-6,18)
+       v3i(4,4,18)
+       v3i(4,4,-6)
+       endpolygon()
+       closeobj()
+       return obj
+def axis():
+       bgnline()
+       cpack(0xff0000)
+       v3i(-1,0,0)
+       v3i(1,0,0)
+       v3f(1.0, 0.1, 0.1)
+       endline()
+       bgnline()
+       cpack(0xff00)
+       v3i(0,-1,0)
+       v3i(0,1,0)
+       v3f(0.1, 1.0, 0.1)
+       endline()
+       bgnline()
+       cpack(0xff)
+       v3i(0,0,-1)
+       v3i(0,0,1)
+       v3f(0.1,0.1,1.0)
+       endline()
+#
+silver = [ DIFFUSE, 0.3, 0.3, 0.3, SPECULAR, 0.9, 0.9, 0.95, \
+       SHININESS, 40.0, LMNULL]
+floormat = [ AMBIENT, 0.5, 0.25, 0.15, DIFFUSE, 0.5, 0.25, 0.15, SPECULAR, 0.6, 0.3, 0.2, SHININESS, 20.0, LMNULL]
+wallmat = [ DIFFUSE, 0.4, 0.2, 0.1, AMBIENT, 0.4, 0.20, 0.10, SPECULAR, 0.0, 0.0, 0.0, SHININESS, 20.0, LMNULL]
+offwhite = [ DIFFUSE, 0.8, 0.8, 0.6, AMBIENT, 0.8, 0.8, 0.6, SPECULAR, 0.9, 0.9, 0.9, SHININESS, 30.0, LMNULL]
+doormat = [ DIFFUSE, 0.1, 0.2, 0.5, AMBIENT, 0.2, 0.4, 1.0, SPECULAR, 0.2, 0.4, 1.0, SHININESS, 60.0, LMNULL]
+
+toplight = [ LCOLOR, 1.0, 1.0, 0.5, \
+       POSITION, 0.0, 0.0, 11.0, 1.0, LMNULL]
+floor1light = [ LCOLOR, 1.0, 1.0, 1.0, POSITION, 3.9, -3.9, 0.0, 1.0, \
+       SPOTDIRECTION, 1.0, 1.0, 0.0, SPOTLIGHT, 10.0, 90.0, LMNULL]
+
+lmodel = [ AMBIENT, 0.92, 0.8, 0.5, LOCALVIEWER, 1.0, LMNULL]
+#
+def lighting():
+       INDIGO=1        # XXXX Seems indigo only has one light.
+       lmdef(DEFMATERIAL, 2, silver)
+       lmdef(DEFMATERIAL, 3, floormat)
+       lmdef(DEFMATERIAL, 4, wallmat)
+       lmdef(DEFMATERIAL, 5, offwhite)
+       lmdef(DEFMATERIAL, 6, doormat)
+       lmdef(DEFLIGHT, 1, toplight)
+       if not INDIGO:
+           lmdef(DEFLIGHT, 2, floor1light)
+       lmdef(DEFLMODEL, 1, lmodel)
+       lmbind(LIGHT0, 1)
+       if not INDIGO:
+           lmbind(LIGHT1, 2)
+       lmbind(LMODEL, 1)
+IdMat=[1.0,0.0,0.0,0.0, 0.0,1.0,0.0,0.0, 0.0,0.0,1.0,0.0, 0.0,0.0,0.0,1.0]
+#
+wrongrange='Wrong Range'
+def defun(axis):
+       done = 0
+       res = 0.0       # Hack around exec(...)
+       while not done:
+           print 'F'+axis+'(t) = ',
+           s = sys.stdin.readline(100)
+           print
+           try:
+               s = 'def f'+axis+'(t): return '+s
+               exec(s, main_dict)
+               exec('res = f'+axis+'(0.0)\n')
+               if res < -10.0 or res > 10.0:
+                       raise wrongrange
+               exec('res = f'+axis+'(100.0)\n')
+               if res < -10.0 or res > 10.0:
+                       raise wrongrange
+               done = 1
+           except RuntimeError:
+               print 'Sorry, there is a syntax error in your expression'
+           except TypeError:
+               print 'Please remember to use floating point numbers'
+           except wrongrange:
+               print 'Sorry, function values out of range (non-periodic function?)'
+def getfunctions():
+       print 'Welcome to the CWI art simulator. You can now enter X, Y and Z'
+       print 'coordinates as a function of t.'
+       print 'Alternatively, you can specify the name of a python module'
+       print 'defining functions fx(t), fy(t) and fz(t) on the command line'
+       print 'Normal trig functions are available. Please use floating point'
+       print 'values only (so 0.0 for 0). Comments to jack@cwi.nl'
+       defun('x')
+       defun('y')
+       defun('z')
+       print 'Ok, here you go. Use mouse+right button to move up/down,'
+       print 'mouse+middle to speed up/slow down time. type ESC to quit simulation'
+def main():
+       if len(sys.argv) > 1:
+           exec('from '+sys.argv[1]+' import *\n')
+       else:
+           getfunctions()
+       foreground()
+       prefposition(100,600,100,600)
+       void = winopen('cyl')
+       qdevice(ESCKEY)
+       qdevice(MOUSE1)
+       qdevice(MOUSE2)
+       qdevice(PKEY)
+       RGBmode()
+       doublebuffer()
+       gconfig()
+       zbuffer(1)
+       mmode(MVIEWING)
+       perspective(600, 1.0, 0.01, 20.0)
+       loadmatrix(IdMat)
+       vx = 0.0
+       vy = -3.9
+       vz = 0.0
+       lookat(0.0, -3.9, 0.0, 0.0, 0.0, 0.0, 0)
+       lighting()
+       t = -1.0
+       step = 0.2
+       bol = mkcyl(12,24, 1)
+       cable = mkcyl(1, 6, 0)
+       floors = drawfloors()
+       walls = drawwalls()
+       pillar = mkcyl(1,4,0)
+       railing = drawrailing()
+       doors = drawdoors()
+       shademodel(GOURAUD)
+       mousing = -1
+       pausing = 0
+       while 1:
+           #
+           # Check for some user input
+           #
+           if qtest():
+               dev, value = qread()
+               if dev == PKEY and value == 1:
+                       pausing = 1
+               if dev == ESCKEY:
+                   break
+               elif (dev==MOUSE1 or dev==MOUSE2) and value == 1:
+                   if mousing > 0:
+                       vx = 0.0
+                       vy = -3.9
+                       vz = 0.0
+                   mousing = dev
+                   oldx = getvaluator(MOUSEX)
+                   oldy = getvaluator(MOUSEY)
+               elif (dev==MOUSE1 or dev==MOUSE2):
+                   mousing = -1
+           if mousing >= 0:
+               newx = getvaluator(MOUSEX)
+               newy = getvaluator(MOUSEY)
+               if newy <> oldy and mousing==MOUSE1:
+                   vz = vz + float(newy - oldy)/100.0
+                   if vz < -5.99:
+                       vz = -5.99
+                   dist = sqrt(vx*vx + vy*vy + vz*vz)
+                   perspective(600, 1.0, 0.01, dist+16.0)
+                   loadmatrix(IdMat)
+                   if vz < 0.0:
+                       lookat(vx, vy, vz, 0.0, 0.0, 0.0, 1800)
+                   else:
+                       lookat(vx, vy, vz, 0.0, 0.0, 0.0, 0)
+               if newy <> oldy and mousing==MOUSE2:
+                   step = step * exp(float(newy-oldy)/400.0)
+           if getbutton(CTRLKEY) == 0:
+               t = t + step
+           else:
+               t = t - step
+           if getbutton(LEFTSHIFTKEY) == 0:
+               shademodel(GOURAUD)
+           else:
+               shademodel(FLAT)
+           #
+           # Draw background and axis
+           czclear(0x802020,getgdesc(GD_ZMAX))
+           #axis()
+           #
+           # draw the floors
+           #
+           lmbind(MATERIAL, 3)
+           callobj(floors)
+           lmbind(MATERIAL, 4)
+           callobj(walls)
+           lmbind(MATERIAL, 5)
+           pushmatrix()
+           translate(-4.5,4.5,3.0)
+           scale(0.2,0.2,9.0)
+           rotate(450,'z')
+           callobj(pillar)
+           popmatrix()
+           callobj(railing)
+           lmbind(MATERIAL, 6)
+           pushmatrix()
+           translate(0.0, -0.01, 0.0)
+           callobj(doors)
+           popmatrix()
+           #
+           # Draw object
+           #
+           bolx = fx(t)
+           boly = fy(t)
+           bolz = fz(t)
+           err = ''
+           if bolx < -4.0 or bolx > 4.0:
+               err = 'X('+`bolx`+') out of range [-4,4]'
+           if boly < -4.0 or boly > 4.0:
+               err = 'Y('+`boly`+') out of range [-4,4]'
+           if bolz < -4.0 or bolz > 8.0:
+               err = 'Z('+`bolz`+') out of range [-4,8]'
+           if not err:
+               pushmatrix()
+               translate(bolx, boly, bolz)
+               scale(0.3, 0.3, 0.3)
+               lmbind(MATERIAL, 2)
+               blendfunction(BF_ONE, BF_ONE)
+               callobj(bol)
+               blendfunction(BF_ONE, BF_ZERO)
+               popmatrix()
+               #
+               # Draw the cables
+               #
+               bolz = bolz + 0.3
+               pushmatrix()
+               #linesmooth(SML_ON)
+               bgnline()
+               v3i(-4,-4,9)
+               v3f(bolx, boly, bolz)
+               endline()
+               bgnline()
+               v3i(-4,4,9)
+               v3f(bolx, boly, bolz)
+               endline()
+               bgnline()
+               v3i(4,-4,9)
+               v3f(bolx, boly, bolz)
+               endline()
+               bgnline()
+               v3i(4,4,9)
+               v3f(bolx, boly, bolz)
+               endline()
+               popmatrix()
+           if mousing == MOUSE2 or err:
+               cpack(0xff0000)
+               cmov(0.0, 0.0, 0.4)
+               charstr('t='+`t`)
+           if mousing == MOUSE2:
+               cpack(0xff0000)
+               cmov(0.0, 0.0, 0.2)
+               charstr('delta-t='+`step`)
+           if err:
+               cpack(0xff00)
+               cmov(0.0, 0.0, 0.2)
+               charstr(err)
+               pausing = 1
+           if pausing:
+               cpack(0xff00)
+               cmov(0.0, 0.0, 0.0)
+               charstr('Pausing, type P to continue')
+           swapbuffers()
+           if pausing:
+               while 1:
+                   dv=qread()
+                   if dv==(PKEY,1):
+                       break
+                   if dv==(ESCKEY,1):
+                       sys.exit(0)
+               pausing = 0
+#
+try:
+    main()
+except KeyboardInterrupt:
+    sys.exit(1)
diff --git a/Demo/sgi/gl/mclock.doc b/Demo/sgi/gl/mclock.doc
new file mode 100755 (executable)
index 0000000..2208f33
--- /dev/null
@@ -0,0 +1,60 @@
+Newsgroups: cwi.sgi
+Subject: Re: new clock
+Distribution: cwi.sgi
+References: <2246@charon.cwi.nl>
+
+Last week I wrote:
+
+>For your enjoyment I have implemented a colorful clock.
+
+The clock has now been extended with some new facilities: a menu, an
+alarm and a gong.  These may require some explanation beyond what's in
+the usage message.
+
+Menu
+----
+The right mouse button now pops up a menu that allows you to turn the
+seconds hand on or off and to switch the alarm off.
+
+Alarm
+-----
+
+The left and middle buttons set the alarm.  When it is on, the alarm
+time is displayed as a time on a 24 hour clock in the bottom left
+corner.  It is also indicated by two red triangles, corresponding to the
+little (hours) and big (minutes) hand.  These hands can be moved around:
+the left mouse button moves the minutes hand, the middle button moves
+the hourds hand.  Watch out for differences of twelve hours (always
+check the digital display); these can be corrected by dragging the hours
+hand once around the dial.
+
+When the alarm goes off, two things happen: a shell command specified on
+the command line with the -a option is executed (in the background), and
+the clock's colors change every two seconds, for five minutes.  You can
+also turn the alarm off by using the menu accessible through the right
+mouse button.
+
+There is no default command for the -a option; if it is not specified,
+only the changing of the colors happens.  If you have an 8 ohm speaker
+connected to the audio output of your Personal Iris, a suitable command
+would be:
+
+       mclock -a '/ufs/guido/bin/sgi/play /ufs/guido/lib/sounds/alarm'
+
+Gong
+----
+
+Some people like a clock that makes noises every hour, or even more
+often.  This is supported by the -g and -G options.  With -g you specify
+a shell command to be executed to sound the gong; with -G you can
+specify the interval between gong calls, in seconds (default is one hour).
+The shell command is executed in the background.  It is given two
+arguments: the hours (on a 24 hour clock!) and the minutes.  The
+executable Python script /ufs/guido/bin/sgi/chime is a suitable example.
+Again, this only works if you have installed a speaker (I bet 8 ohm
+speakers are going to be in demand!)
+
+--
+Guido van Rossum, Centre for Mathematics and Computer Science (CWI), Amsterdam
+guido@cwi.nl or ..!hp4nl!cwi.nl!guido or guido%cwi.nl@uunet.uu.net
+"A thing of beauty is a joy till sunrise"
diff --git a/Demo/sgi/gl/mclock.py b/Demo/sgi/gl/mclock.py
new file mode 100755 (executable)
index 0000000..5a94dcb
--- /dev/null
@@ -0,0 +1,731 @@
+#! /usr/local/python
+
+#############################################################################
+# NOTA BENE: Before installing, fix TZDIFF to reflect your local time zone! #
+#############################################################################
+
+# "M Clock"
+#
+# An implementation in software of an original design by Rob Juda.
+# Clock implementation: Guido van Rossum.
+# Alarm and Gong features: Sape Mullender.
+#
+# XXX TO DO:
+# add arguments to specify initial window position and size
+# find out local time zone difference automatically
+# add a date indicator
+# allow multiple alarms
+# allow the menu to change more parameters
+
+import sys
+
+from gl import *
+from GL import *
+from DEVICE import *
+import time
+import getopt
+import string
+import os
+from math import pi
+import math
+
+FULLC = 3600           # Full circle in 1/10-ths of a degree
+MIDN = 900             # Angle of the 12 o'clock position
+R, G, B = 0, 1, 2      # Indices of colors in RGB list
+
+HOUR = 3600            # Number of seconds per hour
+MINUTE = 60            # Number of seconds per minute
+
+class struct: pass     # Class to define featureless structures
+Gl = struct()          # Object to hold writable global variables
+
+# Default constants (used in multiple places)
+
+SCREENBG = 127, 156, 191
+NPARTS = 9
+TITLE = 'M Clock'
+TZDIFF = -2*HOUR       # <--- change this to reflect your local time zone
+
+# Default parameters
+
+Gl.foreground = 0      # If set, run in the foreground
+Gl.fullscreen = 0      # If set, run on full screen
+Gl.tzdiff = TZDIFF     # Seconds west of Greenwich (winter time)
+Gl.nparts = NPARTS     # Number of parts each circle is divided in (>= 2)
+Gl.debug = 0           # If set, print debug output
+Gl.doublebuffer = 1    # If set, use double buffering
+Gl.update = 0          # Update interval; seconds hand is suppressed if > 1
+Gl.colorsubset = 0     # If set, display only a subset of the colors
+Gl.cyan = 0            # If set, display cyan overlay (big hand)
+Gl.magenta = 0         # If set, display magenta overlay (little hand)
+Gl.yellow = 0          # If set, display yellow overlay (fixed background)
+Gl.black = 0           # If set, display black overlay (hands)
+Gl.colormap = 0                # If set, use colormap mode instead of RGB mode
+Gl.warnings = 0                # If set, print warnings
+Gl.title = ''          # Window title (default set later)
+Gl.name = 'mclock'     # Window title for resources
+Gl.border = 1          # If set, use a window border (and title)
+Gl.bg = 0, 0, 0                # Background color R, G, B value
+Gl.iconic = 0          # Set in iconic state
+Gl.fg = 255, 0, 0      # Alarm background RGB (either normal or alarm)
+Gl.ox,Gl.oy = 0,0      # Window origin
+Gl.cx,Gl.cy = 0,0      # Window size
+Gl.alarm_set = 0       # Alarm on or off
+Gl.alarm_on = 0                # Alarm is ringing
+Gl.alarm_time = 0      # Alarm time in seconds after midnight
+Gl.alarm_hours = 0     # Alarm hour setting, 24 hour clock
+Gl.alarm_minutes = 0   # Alarm minutes setting
+Gl.alarm_rgb = 0,0,0   # Alarm display RGB colors
+Gl.alarm_cmd = ''      # Command to execute when alarm goes off
+Gl.mouse2down = 0      # Mouse button state
+Gl.mouse3down = 0      # Mouse button state
+Gl.gong_cmd = ''       # Command to execute when chimes go off
+Gl.gong_int = 3600     # Gong interval
+Gl.indices = R, G, B   # Colors (permuted when alarm is on)
+
+def main():
+       #
+       sys.stdout = sys.stderr         # All output is errors/warnings etc.
+       #
+       try:
+               args = getoptions()
+       except string.atoi_error, value:
+               usage(string.atoi_error, value)
+       except getopt.error, msg:
+               usage(getopt.error, msg)
+       #
+       if args:
+               realtime = 0
+               hours = string.atoi(args[0])
+               minutes = seconds = 0
+               if args[1:]: minutes = string.atoi(args[1])
+               if args[2:]: seconds = string.atoi(args[2])
+               localtime = ((hours*60)+minutes)*60+seconds
+       else:
+               realtime = 1
+       #
+       if Gl.title == '':
+               if realtime:
+                       Gl.title = TITLE
+               else:
+                       title = ''
+                       for arg in args: title = title + ' ' + arg
+                       Gl.title = title[1:]
+                       del title
+       #
+       wid = makewindow()
+       Gl.ox,Gl.oy = getorigin()
+       Gl.cx,Gl.cy = getsize()
+       initmenu()
+       clearall()
+       #
+       if not Gl.update:
+               Gl.update = 60
+       #
+       if Gl.update <= 1:
+               Gl.timernoise = 6
+       else:
+               Gl.timernoise = 60
+       noise(TIMER0, Gl.timernoise)
+       #
+       qdevice(WINSHUT)
+       qdevice(WINQUIT)
+       qdevice(ESCKEY)
+       if realtime:
+               qdevice(TIMER0)
+       qdevice(REDRAW)
+       qdevice(WINFREEZE)
+       qdevice(WINTHAW)
+       qdevice(MENUBUTTON)     # MOUSE1
+       qdevice(MOUSE3)         # Left button
+       qdevice(MOUSE2)         # Middle button
+       unqdevice(INPUTCHANGE)
+       #
+       lasttime = 0
+       Gl.change = 1
+       while 1:
+               if realtime:
+                       localtime = time.time() - Gl.tzdiff
+               if Gl.alarm_set:
+                       if localtime%(24*HOUR) == Gl.alarm_time:
+                               # Ring the alarm!
+                               if Gl.debug:
+                                       print 'Rrrringg!'
+                               Gl.alarm_on = 1
+                               if Gl.alarm_cmd <> '':
+                                       d = os.system(Gl.alarm_cmd+' '+`Gl.alarm_time/3600`+' '+`(Gl.alarm_time/60)%60` + ' &')
+                               Gl.change = 1
+                               clearall()
+               if Gl.alarm_on:
+                       if (localtime - Gl.alarm_time) % (24*HOUR) > 300:
+                               # More than 5 minutes away from alarm
+                               Gl.alarm_on = 0
+                               if Gl.debug:
+                                       print 'Alarm turned off'
+                               Gl.change = 1
+                               clearall()
+                               Gl.indices = R, G, B
+                       else:
+                               if localtime % 2 == 0:
+                                 # Permute color indices
+                                 Gl.indices = Gl.indices[2:] + Gl.indices[:2]
+                                 Gl.change = 1
+               if Gl.gong_cmd <> '' and localtime%Gl.gong_int == 0:
+                       d = os.system(Gl.gong_cmd+' '+`(localtime/3600)%24`+' '+`(localtime/60)%60` + ' &')
+               if localtime/Gl.update <> lasttime/Gl.update:
+                       if Gl.debug: print 'new time'
+                       Gl.change = 1
+               if Gl.change:
+                       if Gl.debug: print 'drawing'
+                       doit(localtime)
+                       lasttime = localtime
+                       Gl.change = 0
+               dev, data = qread()
+               if Gl.debug and dev <> TIMER0:
+                       print dev, data
+               if dev == TIMER0:
+                       if Gl.debug > 1:
+                               print dev, data
+               elif dev == MOUSE3:
+                       mousex = getvaluator(MOUSEX)
+                       mousey = getvaluator(MOUSEY)
+                       if mouseclick(3, data, mousex, mousey):
+                               Gl.change = 1
+               elif dev == MOUSE2:
+                       mousex = getvaluator(MOUSEX)
+                       mousey = getvaluator(MOUSEY)
+                       if mouseclick(2, data, mousex, mousey):
+                               Gl.change = 1
+               elif dev == MOUSEX:
+                       mousex = data
+                       if Gl.mouse2down:
+                               mouse2track(mousex, mousey)
+                       if Gl.mouse3down:
+                               mouse3track(mousex, mousey)
+               elif dev == MOUSEY:
+                       mousey = data
+                       if Gl.mouse2down:
+                               mouse2track(mousex, mousey)
+                       if Gl.mouse3down:
+                               mouse3track(mousex, mousey)
+               elif dev == REDRAW or dev == REDRAWICONIC:
+                       if Gl.debug:
+                               if dev == REDRAW: print 'REDRAW'
+                               else: print 'REDRAWICONIC'
+                       reshapeviewport()
+                       Gl.ox,Gl.oy = getorigin()
+                       Gl.cx,Gl.cy = getsize()
+                       Gl.change = 1
+                       clearall()
+               elif dev == MENUBUTTON:
+                       if Gl.debug: print 'MENUBUTTON'
+                       handlemenu()
+               elif dev == WINFREEZE:
+                       if Gl.debug: print 'WINFREEZE'
+                       Gl.iconic = 1
+                       noise(TIMER0, 60*60) # Redraw every 60 seconds only
+               elif dev == WINTHAW:
+                       if Gl.debug: print 'WINTHAW'
+                       Gl.iconic = 0
+                       noise(TIMER0, Gl.timernoise)
+                       Gl.change = 1
+               elif dev == ESCKEY or dev == WINSHUT or dev == WINQUIT:
+                       if Gl.debug: print 'Exit'
+                       sys.exit(0)
+
+def getoptions():
+       optlist, args = getopt.getopt(sys.argv[1:], 'A:a:B:bc:dFfG:g:n:sT:t:u:wCMYK')
+       for optname, optarg in optlist:
+               if optname == '-A':
+                       Gl.fg = eval(optarg)    # Should be (r,g,b)
+               elif optname == '-a':
+                       Gl.alarm_cmd = optarg
+               elif optname == '-B':
+                       Gl.bg = eval(optarg)    # Should be (r,g,b)
+               elif optname == '-b':
+                       Gl.border = 0
+               elif optname == '-c':
+                       Gl.colormap = string.atoi(optarg)
+               elif optname == '-d':
+                       Gl.debug = Gl.debug + 1
+                       Gl.warnings = 1
+               elif optname == '-F':
+                       Gl.foreground = 1
+               elif optname == '-f':
+                       Gl.fullscreen = 1
+               elif optname == '-G':
+                       Gl.gong_int = 60*string.atoi(optarg)
+               elif optname == '-g':
+                       Gl.gong_cmd = optarg
+               elif optname == '-n':
+                       Gl.nparts = string.atoi(optarg)
+               elif optname == '-s':
+                       Gl.doublebuffer = 0
+               elif optname == '-T':
+                       Gl.title = Gl.name = optarg
+               elif optname == '-t':
+                       Gl.tzdiff = string.atoi(optarg)
+               elif optname == '-u':
+                       Gl.update = string.atoi(optarg)
+               elif optname == '-w':
+                       Gl.warnings = 1
+               elif optname == '-C':
+                       Gl.cyan = Gl.colorsubset = 1
+               elif optname == '-M':
+                       Gl.magenta = Gl.colorsubset = 1
+               elif optname == '-Y':
+                       Gl.yellow = Gl.colorsubset = 1
+               elif optname == '-K':
+                       Gl.black = Gl.colorsubset = 1
+               else:
+                       print 'Unsupported option', optname
+       return args
+
+def usage(exc, msg):
+       if sys.argv:
+               progname = os.path.basename(sys.argv[0])
+       else:
+               progname = 'mclock'
+       #
+       print progname + ':',
+       if exc == string.atoi_error:
+               print 'non-numeric argument:',
+       print msg
+       #
+       print 'usage:', progname, '[options] [hh [mm [ss]]]'
+       #
+       print '-A r,g,b  : alarm background red,green,blue [255,0,0]'
+       print '-a cmd    : shell command executed when alarm goes off'
+       print '-B r,g,b  : background red,green,blue [0,0,0]'
+       print '            (-B SCREENBG uses the default screen background)'
+       print '-b        : suppress window border and title'
+       print '-c cmapid : select explicit colormap'
+       print '-d        : more debug output (implies -F, -w)'
+       print '-F        : run in foreground'
+       print '-f        : use full screen'
+       print '-G intrvl : interval between chimes in minutes [60]'
+       print '-g cmd    : shell command executed when chimes go off'
+       print '-s        : single buffer mode'
+       print '-w        : print various warnings'
+       print '-n nparts : number of parts [' + `NPARTS` + ']'
+       print '-T title  : alternate window title [\'' + TITLE + '\']'
+       print '-t tzdiff : time zone difference [' + `TZDIFF` + ']'
+       print '-u update : update interval [60]'
+       print '-CMYK     : Cyan, Magenta, Yellow or blacK overlay only'
+       print 'if hh [mm [ss]] is specified, display that time statically'
+       print 'on machines with < 12 bitplanes, -c and -s are forced on'
+       #
+       sys.exit(2)
+
+def doit(localtime):
+       hands = makehands(localtime)
+       list = makelist(hands)
+       render(list, hands)
+
+def makehands(localtime):
+       localtime = localtime % (12*HOUR)
+       seconds_hand = MIDN + FULLC - (localtime*60) % FULLC
+       big_hand = (MIDN + FULLC - (localtime%HOUR)) % FULLC
+       little_hand = (MIDN + FULLC - ((localtime/12) % HOUR)) % FULLC
+       return little_hand, big_hand, seconds_hand
+
+def makelist(little_hand, big_hand, seconds_hand):
+       total = []
+       if Gl.cyan or not Gl.colorsubset:
+               total = total + makesublist(big_hand, Gl.indices[0])
+       if Gl.magenta or not Gl.colorsubset:
+               total = total + makesublist(little_hand, Gl.indices[1])
+       if Gl.yellow or not Gl.colorsubset:
+               total = total + makesublist(MIDN, Gl.indices[2])
+       total.sort()
+       return total
+
+def makesublist(first, icolor):
+       list = []
+       alpha = FULLC/Gl.nparts
+       a = first - alpha/2
+       for i in range(Gl.nparts):
+               angle = (a + i*alpha + FULLC) % FULLC
+               value = 255*(Gl.nparts-1-i)/(Gl.nparts-1)
+               list.append(angle, icolor, value)
+       list.sort()
+       a, icolor, value = list[0]
+       if a <> 0:
+               a, icolor, value = list[len(list)-1]
+               t = 0, icolor, value
+               list.insert(0, t)
+       return list
+
+def rgb_fg():
+       return Gl.fg
+       # Obsolete code:
+       if Gl.alarm_on:
+               return Gl.bg
+       else:
+               return Gl.fg
+
+def rgb_bg():
+       return Gl.bg
+       # Obsolete code:
+       if Gl.alarm_on:
+               return Gl.fg
+       else:
+               return Gl.bg
+
+def clearall():
+       Gl.c3i(rgb_bg())
+       clear()
+       if Gl.doublebuffer:
+               swapbuffers()
+               clear()
+
+def draw_alarm(color):
+       frontbuffer(TRUE)
+       Gl.c3i(color)
+       pushmatrix()
+       rotate(-((Gl.alarm_time/12)%3600), 'z')
+       bgnpolygon()
+       v2f( 0.00,1.00)
+       v2f( 0.04,1.05)
+       v2f(-0.04,1.05)
+       endpolygon()
+       popmatrix()
+       #
+       pushmatrix()
+       rotate(-((Gl.alarm_time)%3600), 'z')
+       bgnpolygon()
+       v2f( 0.00,1.05)
+       v2f( 0.07,1.10)
+       v2f(-0.07,1.10)
+       endpolygon()
+       popmatrix()
+       #
+       cmov2(-1.06, -1.06)
+       charstr(string.rjust(`Gl.alarm_time/3600`,2))
+       charstr(':')
+       charstr(string.zfill((Gl.alarm_time/60)%60,2))
+       frontbuffer(FALSE)
+
+def render(list, (little_hand, big_hand, seconds_hand)):
+       #
+       if Gl.colormap:
+               resetindex()
+       #
+       if not list:
+               Gl.c3i(255, 255, 255) # White
+               circf(0.0, 0.0, 1.0)
+       else:
+               list.append(3600, 0, 255) # Sentinel
+       #
+       rgb = [255, 255, 255]
+       a_prev = 0
+       for a, icolor, value in list:
+               if a <> a_prev:
+                       [r, g, b] = rgb
+                       if Gl.debug > 1:
+                               print rgb, a_prev, a
+                       Gl.c3i(r, g, b)
+                       arcf(0.0, 0.0, 1.0, a_prev, a)
+               rgb[icolor] = value
+               a_prev = a
+       #
+       if Gl.black or not Gl.colorsubset:
+               #
+               # Draw the hands -- in black
+               #
+               Gl.c3i(0, 0, 0)
+               #
+               if Gl.update == 1 and not Gl.iconic:
+                       # Seconds hand is only drawn if we update every second
+                       pushmatrix()
+                       rotate(seconds_hand, 'z')
+                       bgnline()
+                       v2f(0.0, 0.0)
+                       v2f(1.0, 0.0)
+                       endline()
+                       popmatrix()
+               #
+               pushmatrix()
+               rotate(big_hand, 'z')
+               rectf(0.0, -0.01, 0.97, 0.01)
+               circf(0.0, 0.0, 0.01)
+               circf(0.97, 0.0, 0.01)
+               popmatrix()
+               #
+               pushmatrix()
+               rotate(little_hand, 'z')
+               rectf(0.04, -0.02, 0.63, 0.02)
+               circf(0.04, 0.0, 0.02)
+               circf(0.63, 0.0, 0.02)
+               popmatrix()
+               #
+               # Draw the alarm time, if set or being set
+               #
+               if Gl.alarm_set:
+                       draw_alarm(rgb_fg())
+       #
+       if Gl.doublebuffer: swapbuffers()
+
+def makewindow():
+       #
+       if Gl.debug or Gl.foreground:
+               foreground()
+       #
+       if Gl.fullscreen:
+               scrwidth, scrheight = getgdesc(GD_XPMAX), getgdesc(GD_YPMAX)
+               prefposition(0, scrwidth-1, 0, scrheight-1)
+       else:
+               keepaspect(1, 1)
+               prefsize(100, 100)
+       #
+       if not Gl.border:
+               noborder()
+       wid = winopen(Gl.name)
+       wintitle(Gl.title)
+       #
+       if not Gl.fullscreen:
+               keepaspect(1, 1)
+               minsize(10, 10)
+               maxsize(2000, 2000)
+               iconsize(66, 66)
+               winconstraints()
+       #
+       nplanes = getplanes()
+       nmaps = getgdesc(GD_NMMAPS)
+       if Gl.warnings:
+               print nplanes, 'color planes,', nmaps, 'color maps'
+       #
+       if nplanes < 12 or Gl.colormap:
+               if not Gl.colormap:
+                       Gl.colormap = nmaps - 1
+                       if Gl.warnings:
+                               print 'not enough color planes available',
+                               print 'for RGB mode; forcing colormap mode'
+                               print 'using color map number', Gl.colormap
+               if not Gl.colorsubset:
+                       needed = 3
+               else:
+                       needed = Gl.cyan + Gl.magenta + Gl.yellow
+               needed = needed*Gl.nparts
+               if Gl.bg <> (0, 0, 0):
+                       needed = needed+1
+               if Gl.fg <> (0, 0, 0):
+                       needed = needed+1
+               if Gl.doublebuffer:
+                       if needed > available(nplanes/2):
+                               Gl.doublebuffer = 0
+                               if Gl.warnings:
+                                       print 'not enough colors available',
+                                       print 'for double buffer mode;',
+                                       print 'forcing single buffer mode'
+                       else:
+                               nplanes = nplanes/2
+               if needed > available(nplanes):
+                       # Do this warning always
+                       print 'still not enough colors available;',
+                       print 'parts will be left white'
+                       print '(needed', needed, 'but have only',
+                       print available(nplanes), 'colors available)'
+       #
+       if Gl.doublebuffer:
+               doublebuffer()
+               gconfig()
+       #
+       if Gl.colormap:
+               Gl.c3i = pseudo_c3i
+               fixcolormap()
+       else:
+               Gl.c3i = c3i
+               RGBmode()
+               gconfig()
+       #
+       if Gl.fullscreen:
+               # XXX Should find out true screen size using getgdesc()
+               ortho2(-1.1*1.280, 1.1*1.280, -1.1*1.024, 1.1*1.024)
+       else:
+               ortho2(-1.1, 1.1, -1.1, 1.1)
+       #
+       return wid
+
+def available(nplanes):
+       return pow(2, nplanes) - 1      # Reserve one pixel for black
+
+def fixcolormap():
+       multimap()
+       gconfig()
+       nplanes = getplanes()
+       if Gl.warnings:
+               print 'multimap mode has', nplanes, 'color planes'
+       imap = Gl.colormap
+       Gl.startindex = pow(2, nplanes) - 1
+       Gl.stopindex = 1
+       setmap(imap)
+       mapcolor(0, 0, 0, 0) # Fixed entry for black
+       if Gl.bg <> (0, 0, 0):
+               r, g, b = Gl.bg
+               mapcolor(1, r, g, b) # Fixed entry for Gl.bg
+               Gl.stopindex = 2
+       if Gl.fg <> (0, 0, 0):
+               r, g, b = Gl.fg
+               mapcolor(2, r, g, b) # Fixed entry for Gl.fg
+               Gl.stopindex = 3
+       Gl.overflow_seen = 0
+       resetindex()
+
+def resetindex():
+       Gl.index = Gl.startindex
+
+r0g0b0 = (0, 0, 0)
+
+def pseudo_c3i(rgb):
+       if rgb == r0g0b0:
+               index = 0
+       elif rgb == Gl.bg:
+               index = 1
+       elif rgb == Gl.fg:
+               index = 2
+       else:
+               index = definecolor(rgb)
+       color(index)
+
+def definecolor(rgb):
+       index = Gl.index
+       if index < Gl.stopindex:
+               if Gl.debug: print 'definecolor hard case', rgb
+               # First see if we already have this one...
+               for index in range(Gl.stopindex, Gl.startindex+1):
+                       if rgb == getmcolor(index):
+                               if Gl.debug: print 'return', index
+                               return index
+               # Don't clobber reserverd colormap entries
+               if not Gl.overflow_seen:
+                       # Shouldn't happen any more, hence no Gl.warnings test
+                       print 'mclock: out of colormap entries'
+                       Gl.overflow_seen = 1
+               return Gl.stopindex
+       r, g, b = rgb
+       if Gl.debug > 1: print 'mapcolor', (index, r, g, b)
+       mapcolor(index, r, g, b)
+       Gl.index = index - 1
+       return index
+
+# Compute n**i
+def pow(n, i):
+       x = 1
+       for j in range(i): x = x*n
+       return x
+
+def mouseclick(mouse, updown, x, y):
+       if updown == 1:
+               # mouse button came down, start tracking
+               if Gl.debug:
+                       print 'mouse', mouse, 'down at', x, y
+               if mouse == 2:
+                       Gl.mouse2down = 1
+                       mouse2track(x, y)
+               elif mouse == 3:
+                       Gl.mouse3down = 1
+                       mouse3track(x, y)
+               else:
+                       print 'fatal error'
+               qdevice(MOUSEX)
+               qdevice(MOUSEY)
+               return 0
+       else:
+               # mouse button came up, stop tracking
+               if Gl.debug:
+                       print 'mouse', mouse, 'up at', x, y
+               unqdevice(MOUSEX)
+               unqdevice(MOUSEY)
+               if mouse == 2:
+                       mouse2track(x, y)
+                       Gl.mouse2down = 0
+               elif mouse == 3:
+                       mouse3track(x, y)
+                       Gl.mouse3down = 0
+               else:
+                       print 'fatal error'
+               Gl.alarm_set = 1
+               return 1
+
+def mouse3track(x, y):
+       # first compute polar coordinates from x and y
+       cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
+       x, y = x - cx, y - cy
+       if (x, y) == (0, 0): return     # would cause an exception
+       minutes = int(30.5 + 30.0*math.atan2(float(-x), float(-y))/pi)
+       if minutes == 60: minutes = 0
+       a,b = Gl.alarm_minutes/15, minutes/15
+       if (a,b) == (0,3):
+               # Moved backward through 12 o'clock:
+               Gl.alarm_hours = Gl.alarm_hours - 1
+               if Gl.alarm_hours < 0: Gl.alarm_hours = Gl.alarm_hours + 24
+       if (a,b) == (3,0):
+               # Moved forward through 12 o'clock:
+               Gl.alarm_hours = Gl.alarm_hours + 1
+               if Gl.alarm_hours >= 24: Gl.alarm_hours = Gl.alarm_hours - 24
+       Gl.alarm_minutes = minutes
+       seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
+       if seconds <> Gl.alarm_time:
+               draw_alarm(rgb_bg())
+               Gl.alarm_time = seconds
+               draw_alarm(rgb_fg())
+
+def mouse2track(x, y):
+       # first compute polar coordinates from x and y
+       cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
+       x, y = x - cx, y - cy
+       if (x, y) == (0, 0): return     # would cause an exception
+       hours = int(6.5 - float(Gl.alarm_minutes)/60.0 + 6.0*math.atan2(float(-x), float(-y))/pi)
+       if hours == 12: hours = 0
+       if (Gl.alarm_hours,hours) == (0,11):
+               # Moved backward through midnight:
+               Gl.alarm_hours = 23
+       elif (Gl.alarm_hours,hours) == (12,11):
+               # Moved backward through noon:
+               Gl.alarm_hours = 11
+       elif (Gl.alarm_hours,hours) == (11,0):
+               # Moved forward through noon:
+               Gl.alarm_hours = 12
+       elif (Gl.alarm_hours,hours) == (23,0):
+               # Moved forward through midnight:
+               Gl.alarm_hours = 0
+       elif Gl.alarm_hours < 12:
+               Gl.alarm_hours = hours
+       else:
+               Gl.alarm_hours = hours + 12
+       seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
+       if seconds <> Gl.alarm_time:
+               draw_alarm(rgb_bg())
+               Gl.alarm_time = seconds
+               draw_alarm(rgb_fg())
+
+def initmenu():
+       Gl.pup = pup = newpup()
+       addtopup(pup, 'M Clock%t|Alarm On/Off|Seconds Hand On/Off|Quit', 0)
+
+def handlemenu():
+       item = dopup(Gl.pup)
+       if item == 1:
+               # Toggle alarm
+               if Gl.alarm_set:
+                       Gl.alarm_set = 0
+                       Gl.alarm_on = 0
+               else:
+                       Gl.alarm_set = 1
+               Gl.change = 1
+               clearall()
+       elif item == 2:
+               # Toggle Seconds Hand
+               if Gl.update == 1:
+                       Gl.update = 60
+                       Gl.timernoise = 60
+               else:
+                       Gl.update = 1
+                       Gl.timernoise = 6
+               Gl.change = 1
+       elif item == 3:
+               if Gl.debug: print 'Exit'
+               sys.exit(0)
+
+main()
diff --git a/Demo/sgi/gl/mixing.py b/Demo/sgi/gl/mixing.py
new file mode 100755 (executable)
index 0000000..d6b9ecf
--- /dev/null
@@ -0,0 +1,116 @@
+#! /usr/local/python
+
+# Use Gouraud shading to mix colors.  Requires Z-buffer.
+# It changes the color assignments so fast that you see white.
+# Left button pauses, middle rotates the square.  ESC to quit.
+# Experiment with a larger window (too slow) or smaller window (really white).
+
+from GL import *
+from gl import *
+import DEVICE
+from math import *
+
+#
+#  tekenvlak : draw a square. with bgnpolygon
+#
+def tekenvlak (vc) :
+       bgnpolygon()
+       #vcarray (vc)
+       for i in vc :
+               c3f (i[1])
+               v3f (i[0])
+       endpolygon()
+
+#
+# tekendoos : draw a box
+#
+def tekendoos (col) :
+       v = [(-5.0,0.0,0.0),(0.0,5.0,0.0),(5.0,0.0,0.0),(0.0,-5.0,0.0)]
+       vc = [(v[0],col[0]),(v[1],col[1]),(v[2],col[2]),(v[3],col[1])]
+       tekenvlak (vc)
+
+#
+# initialize gl
+#
+def initgl () :
+       #
+       # open window
+       #
+       foreground ()
+       keepaspect (1, 1)
+       prefposition (100, 500, 100, 500)
+       w = winopen ('PYTHON RGB')
+       keepaspect (1, 1)
+       winconstraints()
+       #
+       # configure pipeline (2buf, GOURAUD and RGBmode)
+       #
+       doublebuffer ()
+       zbuffer (1)
+       shademodel (GOURAUD)
+       RGBmode ()
+       gconfig ()
+       #
+       # set viewing
+       #
+       perspective (900, 1, 1.0, 10.0)
+       polarview (10.0, 0, 0, 0)
+       #
+       # ask for the REDRAW and ESCKEY events
+       #
+       qdevice(DEVICE.MOUSE2)
+       qdevice(DEVICE.MOUSE3)
+       qdevice(DEVICE.REDRAW)
+       qdevice(DEVICE.ESCKEY)
+
+
+#
+# the color black
+#
+black = 0
+#
+# GoForIT : use 2buf to redraw the object 2n times. index i is used as 
+# the (smoothly changing) rotation angle
+#
+def GoForIt(i) :
+       col = [(255.0,0.0,0.0), (0.0,255.0,0.0), (0.0,0.0,255.0)]
+       twist = 0
+       freeze = 1
+       while 1 :
+               if freeze <> 0 :
+                       col[0],col[1],col[2] = col[1],col[2],col[0]
+               #
+               # clear z-buffer and clear background to light-blue
+               #
+               zclear()
+               cpack (black)
+               clear()
+               #
+               tekendoos (col)
+               #
+               swapbuffers()
+               #
+               if qtest() <> 0 :
+                       dev, val = qread()
+                       if dev == DEVICE.ESCKEY :
+                               break
+                       elif dev == DEVICE.REDRAW :
+                               reshapeviewport ()
+                       elif dev == DEVICE.MOUSE2 and val <> 0 :
+                               twist = twist + 30
+                               perspective (900, 1, 1.0, 10.0)
+                               polarview (10.0, 0, 0, twist)
+                       elif dev == DEVICE.MOUSE3 and val <> 0 :
+                               freeze = 1 - freeze
+
+
+# the main program
+#
+def main () :
+       initgl ()
+       GoForIt (0)
+
+#
+# exec main
+#
+main  ()
diff --git a/Demo/sgi/gl/nurbs.py b/Demo/sgi/gl/nurbs.py
new file mode 100755 (executable)
index 0000000..fb76aa9
--- /dev/null
@@ -0,0 +1,171 @@
+#! /usr/local/python
+
+# Rotate a 3D surface created using NURBS.
+#
+# Press left mouse button to toggle surface trimming.
+# Press ESC to quit.
+#
+# See the GL manual for an explanation of NURBS.
+
+from gl import *
+from GL import *
+from DEVICE import *
+
+TRUE = 1
+FALSE = 0
+ORDER = 4
+
+idmat = [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
+
+surfknots = [-1, -1, -1, -1, 1, 1, 1, 1]
+
+def make_ctlpoints():
+       c = []
+       #
+       ci = []
+       ci.append(-2.5,  -3.7,  1.0)
+       ci.append(-1.5,  -3.7,  3.0)
+       ci.append(1.5,  -3.7, -2.5)
+       ci.append(2.5,  -3.7,  -0.75)
+       c.append(ci)
+       #
+       ci = []
+       ci.append(-2.5,  -2.0,  3.0)
+       ci.append(-1.5,  -2.0,  4.0)
+       ci.append(1.5,  -2.0,  -3.0)
+       ci.append(2.5,  -2.0,  0.0)
+       c.append(ci)
+       #
+       ci = []
+       ci.append(-2.5, 2.0,  1.0)
+       ci.append(-1.5, 2.0,  0.0)
+       ci.append(1.5,  2.0,  -1.0)
+       ci.append(2.5,  2.0,  2.0)
+       c.append(ci)
+       #
+       ci = []
+       ci.append(-2.5,  2.7,  1.25)
+       ci.append(-1.5,  2.7,  0.1)
+       ci.append(1.5,  2.7,  -0.6)
+       ci.append(2.5,  2.7,  0.2)
+       c.append(ci)
+       #
+       return c
+
+ctlpoints = make_ctlpoints()
+
+trimknots = [0., 0., 0.,  1., 1.,  2., 2.,  3., 3.,   4., 4., 4.]
+
+def make_trimpoints():
+       c = []
+       c.append(1.0, 0.0, 1.0)
+       c.append(1.0, 1.0, 1.0)
+       c.append(0.0, 2.0, 2.0)
+       c.append(-1.0, 1.0, 1.0)
+       c.append(-1.0, 0.0, 1.0)
+       c.append(-1.0, -1.0, 1.0)
+       c.append(0.0, -2.0, 2.0)
+       c.append(1.0, -1.0, 1.0) 
+       c.append(1.0, 0.0, 1.0)
+       return c
+
+trimpoints = make_trimpoints()
+
+def main():
+       init_windows()
+       setup_queue()
+       make_lights()
+       init_view()
+       #
+       set_scene()
+       setnurbsproperty( N_ERRORCHECKING, 1.0 )
+       setnurbsproperty( N_PIXEL_TOLERANCE, 50.0 )
+       trim_flag = 0
+       draw_trim_surface(trim_flag)
+       #
+       while 1:
+               while qtest():
+                       dev, val = qread()
+                       if dev == ESCKEY:
+                               return
+                       elif dev == WINQUIT:
+                               dglclose(-1)    # this for DGL only
+                               return
+                       elif dev == REDRAW:
+                               reshapeviewport()
+                               set_scene()
+                               draw_trim_surface(trim_flag)
+                       elif dev == LEFTMOUSE:
+                               if val:
+                                       trim_flag = (not trim_flag)
+               set_scene()
+               draw_trim_surface(trim_flag)
+
+def init_windows():
+       foreground()
+       #prefposition(0, 500, 0, 500)
+       wid = winopen('nurbs')
+       wintitle('NURBS Surface')
+       doublebuffer()
+       RGBmode()
+       gconfig()
+       lsetdepth(0x000, 0x7fffff)
+       zbuffer( TRUE )
+
+def setup_queue():
+       qdevice(ESCKEY)
+       qdevice(REDRAW)
+       qdevice(RIGHTMOUSE)
+       qdevice(WINQUIT)
+       qdevice(LEFTMOUSE) #trimming
+
+def init_view():
+       mmode(MPROJECTION)
+       ortho( -4., 4., -4., 4., -4., 4. )
+       #
+       mmode(MVIEWING)
+       loadmatrix(idmat)
+       #
+       lmbind(MATERIAL, 1)
+
+def set_scene():
+       lmbind(MATERIAL, 0)
+       RGBcolor(150,150,150)
+       lmbind(MATERIAL, 1)
+       clear()
+       zclear()
+       #
+       rotate( 100, 'y' )
+       rotate( 100, 'z' )
+
+def draw_trim_surface(trim_flag):
+       bgnsurface()
+       nurbssurface(surfknots, surfknots, ctlpoints, ORDER, ORDER, N_XYZ)
+       if trim_flag:
+               bgntrim()
+               nurbscurve(trimknots, trimpoints, ORDER-1, N_STW)
+               endtrim()
+       endsurface()
+       swapbuffers()
+
+def make_lights():
+       lmdef(DEFLMODEL,1,[])
+       lmdef(DEFLIGHT,1,[])
+       #
+       # define material #1
+       #
+       a = []
+       a = a + [EMISSION, 0.0, 0.0, 0.0]
+       a = a + [AMBIENT,  0.1, 0.1, 0.1]
+       a = a + [DIFFUSE,  0.6, 0.3, 0.3]
+       a = a + [SPECULAR,  0.0, 0.6, 0.0]
+       a = a + [SHININESS, 2.0]
+       a = a + [LMNULL]
+       lmdef(DEFMATERIAL, 1, a)
+       #
+       # turn on lighting
+       #
+       lmbind(LIGHT0, 1)
+       lmbind(LMODEL, 1)
+
+main()
diff --git a/Demo/sgi/gl/zrgb.py b/Demo/sgi/gl/zrgb.py
new file mode 100755 (executable)
index 0000000..fa01840
--- /dev/null
@@ -0,0 +1,168 @@
+#! /usr/local/python
+
+#   zrgb  (Requires Z buffer.)
+#
+# This program demostrates zbuffering 3 intersecting RGB polygons while
+# in doublebuffer mode where, movement of the mouse with the LEFTMOUSE 
+# button depressed will, rotate the 3 polygons. This is done by compound
+# rotations allowing continuous screen-oriented rotations. 
+#
+#    Press the "Esc" key to exit.  
+
+from gl import *
+from GL import *
+from DEVICE import *
+
+
+idmat=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
+
+def main() :
+       #
+       # old and new mouse position
+       #
+       #
+       mode = 0
+       omx = 0
+       mx = 0
+       omy = 0
+       my = 0
+       #
+       objmat=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
+       #
+       initialize ()
+       #
+       draw_scene (objmat)
+       #
+       while (1) :
+               #
+               dev, val = qread()
+               #
+               if dev == ESCKEY :
+                       if val :
+                               break   
+                       # exit when key is going up, not down
+                       # this avoids the scenario where a window 
+                       # underneath this program's window
+                       # would otherwise "eat up" the up-
+                       # event of the Esc key being released
+                       return        
+                       #
+               elif dev == REDRAW :
+                       reshapeviewport()
+                       draw_scene(objmat)
+                       #
+               elif dev == LEFTMOUSE:
+                       omx = mx
+                       omy = my
+                       if val :
+                               mode = 1
+                       else :
+                               mode = 0
+               elif dev == MOUSEX :
+                       omx = mx
+                       mx = val
+                       #print omx, mx
+                       objmat = update_scene(objmat,mx,my,omx,omy,mode)
+                       #
+               elif dev == MOUSEY :
+                       omy = my
+                       my = val
+                       #print omy, my
+                       objmat = update_scene(objmat,mx,my,omx,omy,mode)
+                       #
+
+
+def initialize () :
+       #
+       foreground ()
+       keepaspect(5, 4)
+       w = winopen('Zbuffered RGB')
+       #
+       doublebuffer()
+       RGBmode()
+       gconfig()
+       zbuffer(1)
+       lsetdepth(0x0, 0x7FFFFF)
+       #
+       qdevice(ESCKEY)
+       qdevice(LEFTMOUSE)
+       qdevice(MOUSEX)
+       qdevice(MOUSEY)
+
+def update_scene (mat, mx, my, omx, omy, mode) :
+       #
+       if mode == 1 :
+               mat = orient(mat, mx, my, omx, omy)
+               draw_scene(mat)
+       return mat
+
+def orient (mat, mx, my, omx, omy) :
+       #
+       #
+       pushmatrix()
+       loadmatrix(idmat)
+       #
+       if mx - omx : rot (float (mx - omx), 'y')
+       if omy - my : rot (float (omy - my), 'x')
+       #
+       multmatrix(mat)
+       mat = getmatrix()
+       #
+       popmatrix()
+       #
+       return mat
+
+def draw_scene (mat) :
+       RGBcolor(40, 100, 200)
+       clear()
+       zclear()
+       #
+       perspective(400, 1.25, 30.0, 60.0)
+       translate(0.0, 0.0, -40.0)
+       multmatrix(mat)
+       #
+       # skews original view to show all polygons
+       #
+       rotate(-580, 'y')
+       draw_polys()
+       #
+       swapbuffers()
+
+polygon1 = [(-10.0,-10.0,0.0),(10.0,-10.0,0.0),(-10.0,10.0,0.0)]
+
+polygon2 = [(0.0,-10.0,-10.0),(0.0,-10.0,10.0),(0.0,5.0,-10.0)]
+
+polygon3 = [(-10.0,6.0,4.0),(-10.0,3.0,4.0),(4.0,-9.0,-10.0),(4.0,-6.0,-10.0)]
+
+def draw_polys():
+       bgnpolygon()
+       cpack(0x0)
+       v3f(polygon1[0])
+       cpack(0x007F7F7F)
+       v3f(polygon1[1])
+       cpack(0x00FFFFFF)
+       v3f(polygon1[2])
+       endpolygon()
+       #
+       bgnpolygon()
+       cpack(0x0000FFFF)
+       v3f(polygon2[0])
+       cpack(0x007FFF00)
+       v3f(polygon2[1])
+       cpack(0x00FF0000)
+       v3f(polygon2[2])
+       endpolygon()
+       #
+       bgnpolygon()
+       cpack(0x0000FFFF)
+       v3f(polygon3[0])
+       cpack(0x00FF00FF)
+       v3f(polygon3[1])
+       cpack(0x00FF0000)
+       v3f(polygon3[2])
+       cpack(0x00FF00FF)
+       v3f(polygon3[3])
+       endpolygon()
+
+
+main ()