home *** CD-ROM | disk | FTP | other *** search
- '------------------------------------------------------------------------------
- ' TITLE: cube3d
- ' DATE: April 19, 1991
- ' AUTHOR: R. Gonzalez
- '
- ' DESCRIPTION: Demonstrates 3D perspective projection of cube. Uses mouse
- ' location to determine rotation amount. Uses a few tricks to accelerate
- ' performance, but note that after compilation the limiting factor is the
- ' Mac's graphics performance.
- '
- ' COMPILING: Remove STATIC declarations, uncomment indicated lines
- ' Check: Include MBPCs & MBLCs, Include runtime code, Make all arrays static,
- ' Use default menu (if available: Generate 68020 & 68881 code).
- '
- ' (MODIFICATION HISTORY)
- ' DATE:
- ' AUTHOR:
- ' DESCRIPTION:
- '------------------------------------------------------------------------------
-
- ' Since mac windows use local coords (origin at top left), simplified formulas
- ' for 2D view transformation are used.
- DEF FNxv%(xw) = (xw-xw1)*(xv2%-xv1%)/(xw2-xw1)
- DEF FNyv%(yw) = (yw-yw1)*(yv2%-yv1%)/(yw2-yw1)
-
- DIM SHARED xw1,xw2,yw1,yw2,xv1%,xv2%,yv1%,yv2%,d,p(4),pprime(4)
- DIM SHARED TRUE%,FALSE%,pi,cube.dist
- DIM SHARED num.points%,num.objects%,x(100),y(100),z(100),xp(100),yp(100)
- DIM SHARED xtemp(100),ytemp(100),ztemp(100)
- DIM SHARED pic1$,pic2$
-
- 'MAIN
-
- DIM rot1(4,4),rot2(4,4),transl(4,4),composite(4,4),temp(4,4),yrot,xrot,junk%,mousex%,mousey%
- DIM omousex%,omousey%
-
- TRUE% = -1
- FALSE% = 0
- pi = 3.14159
- cube.dist = 5
- xrot = 0
- yrot = 0
-
- WINDOW CLOSE 1 'close default window
-
- identity rot1()
- identity rot2()
- 'identity transl()
- set.view
- initialize.world
- omousex% = -1 'initialize with bad value
- omousey% = -1
-
- 'animation loop (uses default QB File menu to quit)
- WHILE TRUE%
- junk% = MENU(0) 'must call menu(0) function to activate default menus
- ' This version doesn't need these operations because the cube remains at
- ' origin until just when it is ready to be drawn.
- 'translate 0!,0!,-cube.dist,transl()
- junk% = MOUSE(0) 'must call mouse(0) to activate mouse functions
- mousex% = MOUSE(1)
- mousey% = MOUSE(2)
- IF mousex% <> omousex% OR mousey% <> omousey% THEN 'don't redraw unless mouse moves
- omousex% = mousex%
- omousey% = mousey%
- IF mousex% > 0 AND mousex% < (xv2%-xv1%) AND mousey% > 0 AND mousey% < (yv2%-yv1%) THEN
- yrot = ((xv2%-xv1%)/2-mousex%)*pi/(xv2%-xv1%)
- xrot = ((yv2%-yv1%)/2-mousey%)*pi/(yv2%-yv1%)
- END IF
- rotate.y yrot,rot1()
- rotate.x xrot,rot2()
- mat.mat rot1(),rot2(),composite()
- 'mat.mat transl(),rot(),composite()
- 'mat.copy temp(),composite()
- 'translate 0!,0!,cube.dist,transl()
- 'mat.mat temp(),transl(),composite()
- transform.temp.world composite()
- 'CLS
- draw.temp.world
- END IF
- WEND
-
- END
-
- '------------------------------------------------------------------------------
- ' transform all points in 3D world
- '------------------------------------------------------------------------------
- SUB transform.temp.world (trans()) STATIC
-
- 'for compiler only:
- ' dim i%
-
- FOR i% = 1 TO num.points%
- p(1) = x(i%)
- p(2) = y(i%)
- p(3) = z(i%)
- p(4) = 1
- vect.mat p(),trans(),pprime()
- xtemp(i%) = pprime(1)
- ytemp(i%) = pprime(2)
- ztemp(i%) = pprime(3)
- NEXT
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' perform 3D projection to projection plane, then 2D view transformation to viewport
- '------------------------------------------------------------------------------
- SUB draw.temp.world STATIC
-
- 'for compiler only:
- ' dim i%
-
- FOR i% = 1 TO num.points%
- xp(i%) = xtemp(i%)*d/(ztemp(i%)+cube.dist)
- yp(i%) = ytemp(i%)*d/(ztemp(i%)+cube.dist)
- NEXT
-
- pic2$ = pic1$
-
- PICTURE ON
- PENMODE 10 'pen mode XOR so it is erased when drawn again
- MOVETO FNxv%(xp(1)),FNyv%(yp(1)) 'must use Toolbox routines for XOR to work
- LINETO FNxv%(xp(2)),FNyv%(yp(2))
- LINETO FNxv%(xp(3)),FNyv%(yp(3))
- LINETO FNxv%(xp(4)),FNyv%(yp(4))
- LINETO FNxv%(xp(5)),FNyv%(yp(5))
- LINETO FNxv%(xp(6)),FNyv%(yp(6))
- LINETO FNxv%(xp(1)),FNyv%(yp(1))
- LINETO FNxv%(xp(7)),FNyv%(yp(7))
- LINETO FNxv%(xp(5)),FNyv%(yp(5))
- MOVETO FNxv%(xp(3)),FNyv%(yp(3))
- LINETO FNxv%(xp(7)),FNyv%(yp(7))
- MOVETO FNxv%(xp(2)),FNyv%(yp(2))
- LINETO FNxv%(xp(8)),FNyv%(yp(8))
- LINETO FNxv%(xp(6)),FNyv%(yp(6))
- MOVETO FNxv%(xp(4)),FNyv%(yp(4))
- LINETO FNxv%(xp(8)),FNyv%(yp(8))
- PICTURE OFF
- pic1$ = PICTURE$
-
- 'erase previous cube:
- PICTURE ,pic2$
-
- 'draw cube object:
- PICTURE ,pic1$
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' set parameters for 3D view transformation
- '------------------------------------------------------------------------------
- SUB set.view STATIC
-
- 'distance from origin to projection plane:
- d = 2
-
- 'wwindow coordinates (on projection plane):
- xw1 = -1
- xw2 = 1
- yw1 = 1
- yw2 = -1
-
- 'viewport coordinates:
- xv1% = 30
- yv1% = 30
- xv2% = 330
- yv2% = 330
-
- WINDOW 1,,(xv1%,yv1%)-(xv2%,yv2%),3
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' initialize global objects
- '------------------------------------------------------------------------------
- SUB initialize.world STATIC
-
- 'for compiler only:
- ' dim i%
-
- num.objects% = 1
- num.points% = 8
-
- x(1) = 1
- y(1) = 1
- z(1) = 1
- x(2) = 1
- y(2) = 1
- z(2) = -1
- x(3) = 1
- y(3) = -1
- z(3) = -1
- x(4) = -1
- y(4) = -1
- z(4) = -1
- x(5) = -1
- y(5) = -1
- z(5) = 1
- x(6) = -1
- y(6) = 1
- z(6) = 1
- x(7) = 1
- y(7) = -1
- z(7) = 1
- x(8) = -1
- y(8) = 1
- z(8) = -1
-
- 'FOR i% = 1 TO num.points%
- ' z(i%) = z(i%) + cube.dist 'move object away from origin/eye location
- 'NEXT
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' multiply two 4x4 matrices - produces a 4x4 matrix
- '------------------------------------------------------------------------------
- SUB mat.mat (a(),b(),mresult()) STATIC
-
- 'for compiler only:
- ' dim r%,c%
-
- FOR r% = 1 TO 4
- FOR c% = 1 TO 4
- mresult(r%,c%) = a(r%,1)*b(1,c%)+a(r%,2)*b(2,c%)+a(r%,3)*b(3,c%)+a(r%,4)*b(4,c%)
- NEXT
- NEXT
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' copy a 4x4 matrix
- '------------------------------------------------------------------------------
- SUB mat.copy (a(),b()) STATIC
-
- 'for compiler only:
- ' dim r%,c%
-
- FOR r% = 1 TO 4
- FOR c% = 1 TO 4
- a(r%,c%) = b(r%,c%)
- NEXT
- NEXT
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' multiply 4-vector by 4x4 matrix - produces a 4-vector
- '------------------------------------------------------------------------------
- SUB vect.mat (v(),m(),vresult()) STATIC
-
- 'for compiler only:
- ' dim c%
-
- FOR c% = 1 TO 4
- vresult(c%) = v(1)*m(1,c%)+v(2)*m(2,c%)+v(3)*m(3,c%)+v(4)*m(4,c%)
- NEXT
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' create 4x4 identity matrix
- '------------------------------------------------------------------------------
- SUB identity (m()) STATIC
-
- 'for compiler only:
- ' dim r%,c%
-
- FOR r% = 1 TO 4
- FOR c% = 1 TO 4
- IF r% = c% THEN
- m(r%,c%) = 1
- ELSE
- m(r%,c%) = 0
- END IF
- NEXT
- NEXT
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' create 4x4 transformation matrix for rotation about x axis
- ' (assumes m is initially the identity matrix or a former rotate.x matrix)
- '------------------------------------------------------------------------------
- SUB rotate.x (theta,m()) STATIC
-
- 'for compiler only:
- ' dim ct,st
-
- 'calculate these only once for efficiency:
- ct = COS(theta)
- st = SIN(theta)
-
- m(2,2) = ct
- m(2,3) = st
- m(3,2) = -st
- m(3,3) = ct
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' create 4x4 transformation matrix for rotation about y axis
- ' (assumes m is initially the identity matrix or a former rotate.y matrix)
- '------------------------------------------------------------------------------
- SUB rotate.y (theta,m()) STATIC
-
- 'for compiler only:
- ' dim ct,st
-
- 'calculate these only once for efficiency:
- ct = COS(theta)
- st = SIN(theta)
-
- m(1,1) = ct
- m(1,3) = -st
- m(3,1) = st
- m(3,3) = ct
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' create 4x4 transformation matrix for rotation about z axis
- ' (assumes m is initially the identity matrix or a former rotate.z matrix)
- '------------------------------------------------------------------------------
- SUB rotate.z (theta,m()) STATIC
-
- 'for compiler only:
- ' dim ct,st
-
- 'calculate these only once for efficiency:
- ct = COS(theta)
- st = SIN(theta)
-
- m(1,1) = ct
- m(1,2) = st
- m(2,1) = -st
- m(2,2) = ct
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' create 4x4 transformation matrix for translation
- ' (assumes m is initially the identity matrix or a former translation matrix)
- '------------------------------------------------------------------------------
- SUB translate (tx,ty,tz,m()) STATIC
-
- m(4,1) = tx
- m(4,2) = ty
- m(4,3) = tz
-
- END SUB
-
- '------------------------------------------------------------------------------
- ' create 4x4 transformation matrix for scaling
- ' (assumes m is initially the identity matrix or a former scaling matrix)
- '------------------------------------------------------------------------------
- SUB scale (sx,sy,sz,m()) STATIC
-
- m(1,1) = sx
- m(2,2) = sy
- m(3,3) = sz
-
- END SUB
-
-
-