Guido van Rossum | 453bd40 | 1992-03-30 13:18:37 +0000 | [diff] [blame] | 1 | #!/ufs/guido/bin/sgi/python |
| 2 | # Simulate the artwork in the hall. |
| 3 | # Jack Jansen, Feb 91. |
| 4 | # |
| 5 | # Please please please don't try to read this code. |
| 6 | # It is the first GL program I ever wrote, and used to do |
| 7 | # very different things before it's current function:-) |
| 8 | from gl import * |
| 9 | from GL import * |
| 10 | from math import * |
| 11 | from DEVICE import * |
| 12 | import sys |
| 13 | import __main__ |
| 14 | main_dict = __main__.__dict__ |
| 15 | |
| 16 | SPOTDIRECTION = 103 |
| 17 | SPOTLIGHT = 104 |
| 18 | |
| 19 | # |
| 20 | # Make a cylinder paralel with the Z axis with center (X,Y,0) |
| 21 | # and radius 1 |
| 22 | def mkcyl(nslice, nparts, docircle): |
| 23 | cyl = [] |
| 24 | step = 2.0 / float(nslice) |
| 25 | z = -1.0 |
| 26 | for i in range(nslice): |
| 27 | cyl.append(mkslice(z, z+step, nparts, docircle)) |
| 28 | z = z + step |
| 29 | return drawcylinder(cyl) |
| 30 | # |
| 31 | # Make one part of a cylinder |
| 32 | # |
| 33 | def mkslice(z1, z2, nparts, docircle): |
| 34 | if docircle: |
| 35 | w1 = z1 |
| 36 | w2 = z2 |
| 37 | w1 = sqrt(1.0-w1*w1) |
| 38 | w2 = sqrt(1.0-w2*w2) |
| 39 | normalz = 1.0 |
| 40 | else: |
| 41 | w1 = 1.0 |
| 42 | w2 = 1.0 |
| 43 | normalz = 0.0 |
| 44 | slice = [] |
| 45 | step = (2.0*pi)/float(nparts) |
| 46 | angle = 0.0 |
| 47 | for i in range(nparts+1): |
| 48 | vx = cos(angle) |
| 49 | vy = sin(angle) |
| 50 | slice.append( ((vx*w1,vy*w1,z1), (vx*w1, vy*w1, z1*normalz)) ) |
| 51 | slice.append( ((vx*w2,vy*w2,z2), (vx*w2, vy*w2, z2*normalz)) ) |
| 52 | angle = angle + step |
| 53 | return slice |
| 54 | # |
| 55 | # Drawcylinder : draw the cylinder |
| 56 | # |
| 57 | class struct(): pass |
| 58 | curobj = struct() |
| 59 | curobj.curobj = 1 |
| 60 | def drawcylinder(cyl): |
| 61 | obj = curobj.curobj |
| 62 | curobj.curobj = curobj.curobj+1 |
| 63 | makeobj(obj) |
| 64 | for slice in cyl: |
| 65 | bgntmesh() |
| 66 | vnarray(slice) |
| 67 | endtmesh() |
| 68 | closeobj() |
| 69 | return obj |
| 70 | # |
| 71 | def drawnormals(cyl): |
| 72 | for slice in cyl: |
| 73 | for triang in slice: |
| 74 | bgnline() |
| 75 | v3f(triang[0]) |
| 76 | v3f(triang[0][0] + triang[1][0], triang[0][1] + triang[1][1], triang[0][2] + triang[1][2]) |
| 77 | endline() |
| 78 | def drawfloors(): |
| 79 | obj = curobj.curobj |
| 80 | curobj.curobj = curobj.curobj+1 |
| 81 | makeobj(obj) |
| 82 | bgnpolygon() |
| 83 | v3i(4,6,-6) |
| 84 | v3i(-6,6,-6) |
| 85 | v3i(-6,-6,-6) |
| 86 | v3i(4,-6,-6) |
| 87 | endpolygon() |
| 88 | for floor in range(3): |
| 89 | pos = -1 + 5*floor |
| 90 | bgnpolygon() |
| 91 | v3i(4,4,pos) |
| 92 | v3i(-6,4,pos) |
| 93 | v3i(-6,6,pos) |
| 94 | v3i(4,6,pos) |
| 95 | endpolygon() |
| 96 | bgnpolygon() |
| 97 | v3i(-4,4,pos) |
| 98 | v3i(-4,-4,pos) |
| 99 | v3i(-6,-4,pos) |
| 100 | v3i(-6,4,pos) |
| 101 | endpolygon() |
| 102 | bgnpolygon() |
| 103 | v3i(-6,-4,pos) |
| 104 | v3i(-6,-6,pos) |
| 105 | v3i(4,-6,pos) |
| 106 | v3i(4,-4,pos) |
| 107 | endpolygon() |
| 108 | closeobj() |
| 109 | return obj |
| 110 | def drawdoors(): |
| 111 | obj = curobj.curobj |
| 112 | curobj.curobj = curobj.curobj+1 |
| 113 | makeobj(obj) |
| 114 | for floor in range(3): |
| 115 | pos = -1+5*floor |
| 116 | bgnpolygon() |
| 117 | v3i(-2,6,pos) |
| 118 | v3i(-2,6,pos+3) |
| 119 | v3i(0,6,pos+3) |
| 120 | v3i(0,6,pos) |
| 121 | endpolygon() |
| 122 | closeobj() |
| 123 | return obj |
| 124 | def drawrailing(): |
| 125 | obj = curobj.curobj |
| 126 | curobj.curobj = curobj.curobj+1 |
| 127 | makeobj(obj) |
| 128 | for floor in range(3): |
| 129 | pos = -1 + 5*floor |
| 130 | bgnpolygon() |
| 131 | v3i(4,4,pos) |
| 132 | v3i(4,4,pos-1) |
| 133 | v3i(-4,4,pos-1) |
| 134 | v3i(-4,4,pos) |
| 135 | endpolygon() |
| 136 | bgnpolygon() |
| 137 | v3i(-4,4,pos) |
| 138 | v3i(-4,4,pos-1) |
| 139 | v3i(-4,-4,pos-1) |
| 140 | v3i(-4,-4,pos) |
| 141 | endpolygon() |
| 142 | bgnpolygon() |
| 143 | v3i(-4,-4,pos) |
| 144 | v3i(-4,-4,pos-1) |
| 145 | v3i(4,-4,pos-1) |
| 146 | v3i(4,-4,pos) |
| 147 | endpolygon() |
| 148 | closeobj() |
| 149 | return obj |
| 150 | def drawwalls(): |
| 151 | obj = curobj.curobj |
| 152 | curobj.curobj = curobj.curobj+1 |
| 153 | makeobj(obj) |
| 154 | bgnpolygon() |
| 155 | v3i(4,6,-6) |
| 156 | v3i(4,6,18) |
| 157 | v3i(-6,6,18) |
| 158 | v3i(-6,6,-6) |
| 159 | endpolygon() |
| 160 | bgnpolygon() |
| 161 | v3i(-6,6,-6) |
| 162 | v3i(-6,6,18) |
| 163 | v3i(-6,-6,18) |
| 164 | v3i(-6,-6,-6) |
| 165 | endpolygon() |
| 166 | bgnpolygon() |
| 167 | v3i(-6,-6,-6) |
| 168 | v3i(-6,-6,18) |
| 169 | v3i(4,-6,18) |
| 170 | v3i(4,-6,-6) |
| 171 | endpolygon() |
| 172 | bgnpolygon() |
| 173 | v3i(4,-6,-6) |
| 174 | v3i(4,-6,18) |
| 175 | v3i(4,4,18) |
| 176 | v3i(4,4,-6) |
| 177 | endpolygon() |
| 178 | closeobj() |
| 179 | return obj |
| 180 | def axis(): |
| 181 | bgnline() |
| 182 | cpack(0xff0000) |
| 183 | v3i(-1,0,0) |
| 184 | v3i(1,0,0) |
| 185 | v3f(1.0, 0.1, 0.1) |
| 186 | endline() |
| 187 | bgnline() |
| 188 | cpack(0xff00) |
| 189 | v3i(0,-1,0) |
| 190 | v3i(0,1,0) |
| 191 | v3f(0.1, 1.0, 0.1) |
| 192 | endline() |
| 193 | bgnline() |
| 194 | cpack(0xff) |
| 195 | v3i(0,0,-1) |
| 196 | v3i(0,0,1) |
| 197 | v3f(0.1,0.1,1.0) |
| 198 | endline() |
| 199 | # |
| 200 | silver = [ DIFFUSE, 0.3, 0.3, 0.3, SPECULAR, 0.9, 0.9, 0.95, \ |
| 201 | SHININESS, 40.0, LMNULL] |
| 202 | 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] |
| 203 | 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] |
| 204 | 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] |
| 205 | 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] |
| 206 | |
| 207 | toplight = [ LCOLOR, 1.0, 1.0, 0.5, \ |
| 208 | POSITION, 0.0, 0.0, 11.0, 1.0, LMNULL] |
| 209 | floor1light = [ LCOLOR, 1.0, 1.0, 1.0, POSITION, 3.9, -3.9, 0.0, 1.0, \ |
| 210 | SPOTDIRECTION, 1.0, 1.0, 0.0, SPOTLIGHT, 10.0, 90.0, LMNULL] |
| 211 | |
| 212 | lmodel = [ AMBIENT, 0.92, 0.8, 0.5, LOCALVIEWER, 1.0, LMNULL] |
| 213 | # |
| 214 | def lighting(): |
| 215 | INDIGO=1 # XXXX Seems indigo only has one light. |
| 216 | lmdef(DEFMATERIAL, 2, silver) |
| 217 | lmdef(DEFMATERIAL, 3, floormat) |
| 218 | lmdef(DEFMATERIAL, 4, wallmat) |
| 219 | lmdef(DEFMATERIAL, 5, offwhite) |
| 220 | lmdef(DEFMATERIAL, 6, doormat) |
| 221 | lmdef(DEFLIGHT, 1, toplight) |
| 222 | if not INDIGO: |
| 223 | lmdef(DEFLIGHT, 2, floor1light) |
| 224 | lmdef(DEFLMODEL, 1, lmodel) |
| 225 | lmbind(LIGHT0, 1) |
| 226 | if not INDIGO: |
| 227 | lmbind(LIGHT1, 2) |
| 228 | lmbind(LMODEL, 1) |
| 229 | 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] |
| 230 | # |
| 231 | wrongrange='Wrong Range' |
| 232 | def defun(axis): |
| 233 | done = 0 |
| 234 | res = 0.0 # Hack around exec(...) |
| 235 | while not done: |
| 236 | print 'F'+axis+'(t) = ', |
| 237 | s = sys.stdin.readline(100) |
| 238 | print |
| 239 | try: |
| 240 | s = 'def f'+axis+'(t): return '+s |
| 241 | exec(s, main_dict) |
| 242 | exec('res = f'+axis+'(0.0)\n') |
| 243 | if res < -10.0 or res > 10.0: |
| 244 | raise wrongrange |
| 245 | exec('res = f'+axis+'(100.0)\n') |
| 246 | if res < -10.0 or res > 10.0: |
| 247 | raise wrongrange |
| 248 | done = 1 |
| 249 | except RuntimeError: |
| 250 | print 'Sorry, there is a syntax error in your expression' |
| 251 | except TypeError: |
| 252 | print 'Please remember to use floating point numbers' |
| 253 | except wrongrange: |
| 254 | print 'Sorry, function values out of range (non-periodic function?)' |
| 255 | def getfunctions(): |
| 256 | print 'Welcome to the CWI art simulator. You can now enter X, Y and Z' |
| 257 | print 'coordinates as a function of t.' |
| 258 | print 'Alternatively, you can specify the name of a python module' |
| 259 | print 'defining functions fx(t), fy(t) and fz(t) on the command line' |
| 260 | print 'Normal trig functions are available. Please use floating point' |
| 261 | print 'values only (so 0.0 for 0). Comments to jack@cwi.nl' |
| 262 | defun('x') |
| 263 | defun('y') |
| 264 | defun('z') |
| 265 | print 'Ok, here you go. Use mouse+right button to move up/down,' |
| 266 | print 'mouse+middle to speed up/slow down time. type ESC to quit simulation' |
| 267 | def main(): |
| 268 | if len(sys.argv) > 1: |
| 269 | exec('from '+sys.argv[1]+' import *\n') |
| 270 | else: |
| 271 | getfunctions() |
| 272 | foreground() |
| 273 | prefposition(100,600,100,600) |
| 274 | void = winopen('cyl') |
| 275 | qdevice(ESCKEY) |
| 276 | qdevice(MOUSE1) |
| 277 | qdevice(MOUSE2) |
| 278 | qdevice(PKEY) |
| 279 | RGBmode() |
| 280 | doublebuffer() |
| 281 | gconfig() |
| 282 | zbuffer(1) |
| 283 | mmode(MVIEWING) |
| 284 | perspective(600, 1.0, 0.01, 20.0) |
| 285 | loadmatrix(IdMat) |
| 286 | vx = 0.0 |
| 287 | vy = -3.9 |
| 288 | vz = 0.0 |
| 289 | lookat(0.0, -3.9, 0.0, 0.0, 0.0, 0.0, 0) |
| 290 | lighting() |
| 291 | t = -1.0 |
| 292 | step = 0.2 |
| 293 | bol = mkcyl(12,24, 1) |
| 294 | cable = mkcyl(1, 6, 0) |
| 295 | floors = drawfloors() |
| 296 | walls = drawwalls() |
| 297 | pillar = mkcyl(1,4,0) |
| 298 | railing = drawrailing() |
| 299 | doors = drawdoors() |
| 300 | shademodel(GOURAUD) |
| 301 | mousing = -1 |
| 302 | pausing = 0 |
| 303 | while 1: |
| 304 | # |
| 305 | # Check for some user input |
| 306 | # |
| 307 | if qtest(): |
| 308 | dev, value = qread() |
| 309 | if dev == PKEY and value == 1: |
| 310 | pausing = 1 |
| 311 | if dev == ESCKEY: |
| 312 | break |
| 313 | elif (dev==MOUSE1 or dev==MOUSE2) and value == 1: |
| 314 | if mousing > 0: |
| 315 | vx = 0.0 |
| 316 | vy = -3.9 |
| 317 | vz = 0.0 |
| 318 | mousing = dev |
| 319 | oldx = getvaluator(MOUSEX) |
| 320 | oldy = getvaluator(MOUSEY) |
| 321 | elif (dev==MOUSE1 or dev==MOUSE2): |
| 322 | mousing = -1 |
| 323 | if mousing >= 0: |
| 324 | newx = getvaluator(MOUSEX) |
| 325 | newy = getvaluator(MOUSEY) |
| 326 | if newy <> oldy and mousing==MOUSE1: |
| 327 | vz = vz + float(newy - oldy)/100.0 |
| 328 | if vz < -5.99: |
| 329 | vz = -5.99 |
| 330 | dist = sqrt(vx*vx + vy*vy + vz*vz) |
| 331 | perspective(600, 1.0, 0.01, dist+16.0) |
| 332 | loadmatrix(IdMat) |
| 333 | if vz < 0.0: |
| 334 | lookat(vx, vy, vz, 0.0, 0.0, 0.0, 1800) |
| 335 | else: |
| 336 | lookat(vx, vy, vz, 0.0, 0.0, 0.0, 0) |
| 337 | if newy <> oldy and mousing==MOUSE2: |
| 338 | step = step * exp(float(newy-oldy)/400.0) |
| 339 | if getbutton(CTRLKEY) == 0: |
| 340 | t = t + step |
| 341 | else: |
| 342 | t = t - step |
| 343 | if getbutton(LEFTSHIFTKEY) == 0: |
| 344 | shademodel(GOURAUD) |
| 345 | else: |
| 346 | shademodel(FLAT) |
| 347 | # |
| 348 | # Draw background and axis |
| 349 | czclear(0x802020,getgdesc(GD_ZMAX)) |
| 350 | #axis() |
| 351 | # |
| 352 | # draw the floors |
| 353 | # |
| 354 | lmbind(MATERIAL, 3) |
| 355 | callobj(floors) |
| 356 | lmbind(MATERIAL, 4) |
| 357 | callobj(walls) |
| 358 | lmbind(MATERIAL, 5) |
| 359 | pushmatrix() |
| 360 | translate(-4.5,4.5,3.0) |
| 361 | scale(0.2,0.2,9.0) |
| 362 | rotate(450,'z') |
| 363 | callobj(pillar) |
| 364 | popmatrix() |
| 365 | callobj(railing) |
| 366 | lmbind(MATERIAL, 6) |
| 367 | pushmatrix() |
| 368 | translate(0.0, -0.01, 0.0) |
| 369 | callobj(doors) |
| 370 | popmatrix() |
| 371 | # |
| 372 | # Draw object |
| 373 | # |
| 374 | bolx = fx(t) |
| 375 | boly = fy(t) |
| 376 | bolz = fz(t) |
| 377 | err = '' |
| 378 | if bolx < -4.0 or bolx > 4.0: |
| 379 | err = 'X('+`bolx`+') out of range [-4,4]' |
| 380 | if boly < -4.0 or boly > 4.0: |
| 381 | err = 'Y('+`boly`+') out of range [-4,4]' |
| 382 | if bolz < -4.0 or bolz > 8.0: |
| 383 | err = 'Z('+`bolz`+') out of range [-4,8]' |
| 384 | if not err: |
| 385 | pushmatrix() |
| 386 | translate(bolx, boly, bolz) |
| 387 | scale(0.3, 0.3, 0.3) |
| 388 | lmbind(MATERIAL, 2) |
| 389 | blendfunction(BF_ONE, BF_ONE) |
| 390 | callobj(bol) |
| 391 | blendfunction(BF_ONE, BF_ZERO) |
| 392 | popmatrix() |
| 393 | # |
| 394 | # Draw the cables |
| 395 | # |
| 396 | bolz = bolz + 0.3 |
| 397 | pushmatrix() |
| 398 | #linesmooth(SML_ON) |
| 399 | bgnline() |
| 400 | v3i(-4,-4,9) |
| 401 | v3f(bolx, boly, bolz) |
| 402 | endline() |
| 403 | bgnline() |
| 404 | v3i(-4,4,9) |
| 405 | v3f(bolx, boly, bolz) |
| 406 | endline() |
| 407 | bgnline() |
| 408 | v3i(4,-4,9) |
| 409 | v3f(bolx, boly, bolz) |
| 410 | endline() |
| 411 | bgnline() |
| 412 | v3i(4,4,9) |
| 413 | v3f(bolx, boly, bolz) |
| 414 | endline() |
| 415 | popmatrix() |
| 416 | if mousing == MOUSE2 or err: |
| 417 | cpack(0xff0000) |
| 418 | cmov(0.0, 0.0, 0.4) |
| 419 | charstr('t='+`t`) |
| 420 | if mousing == MOUSE2: |
| 421 | cpack(0xff0000) |
| 422 | cmov(0.0, 0.0, 0.2) |
| 423 | charstr('delta-t='+`step`) |
| 424 | if err: |
| 425 | cpack(0xff00) |
| 426 | cmov(0.0, 0.0, 0.2) |
| 427 | charstr(err) |
| 428 | pausing = 1 |
| 429 | if pausing: |
| 430 | cpack(0xff00) |
| 431 | cmov(0.0, 0.0, 0.0) |
| 432 | charstr('Pausing, type P to continue') |
| 433 | swapbuffers() |
| 434 | if pausing: |
| 435 | while 1: |
| 436 | dv=qread() |
| 437 | if dv==(PKEY,1): |
| 438 | break |
| 439 | if dv==(ESCKEY,1): |
| 440 | sys.exit(0) |
| 441 | pausing = 0 |
| 442 | # |
| 443 | try: |
| 444 | main() |
| 445 | except KeyboardInterrupt: |
| 446 | sys.exit(1) |