home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8707 / 53 < prev    next >
Encoding:
Internet Message Format  |  1990-07-13  |  34.5 KB

  1. From: vandys@lindy.stanford.edu (Andy Valencia)
  2. Newsgroups: comp.sources.misc
  3. Subject: 3d Graphics System in Forth
  4. Message-ID: <2932@ncoast.UUCP>
  5. Date: 18 Jul 87 00:30:07 GMT
  6. Sender: allbery@ncoast.UUCP
  7. Lines: 1460
  8. Approved: allbery@ncoast.UUCP
  9. X-Archive: comp.sources.misc/8707/53
  10.  
  11.     I don't know if this is of interest.  It's a 3D graphics system
  12. written in Forth.  Problem is, it assumes that the Forth has 32-bit integers
  13. and 32-bit floating-point numbers.  I put vforth (a VAX forth) into the
  14. public domain to run this sucker, but that was back when a VAX was one of
  15. the only games in town.  Perhaps someone could hack up cforth to be 32-bit,
  16. and then it could go out hand-in-hand with this?  Tell me what you think.
  17.  
  18.             Thanks,
  19.             Andy Valencia
  20.             vandys@lindy.stanford.edu
  21.  
  22. #!/bin/sh-----cut here-----cut here-----cut here-----cut here-----
  23. #    This is a shell archive.
  24. #    Run the following text with /bin/sh to extract.
  25.  
  26. mkdir doc
  27. mkdir figs
  28. mkdir terms
  29. cat - << \Funky!Stuff! > load_grafix
  30.  
  31. " grafix.fth" fload
  32. " matutil.fth" fload
  33. " transform.fth" fload
  34. " plot.fth" fload
  35. " object.fth" fload
  36. " turtle.fth" fload
  37.  
  38. Funky!Stuff!
  39. cat - << \Funky!Stuff! > load_hp
  40. input terms/hp.fth
  41. input matutil.fth
  42. input transform.fth
  43. input plot.fth
  44. input object.fth
  45. input turtle.fth
  46. Funky!Stuff!
  47. cat - << \Funky!Stuff! > load_hp150
  48. input terms/hp150.fth
  49. input matutil.fth
  50. input transform.fth
  51. input plot.fth
  52. input object.fth
  53. input turtle.fth
  54. Funky!Stuff!
  55. cat - << \Funky!Stuff! > matutil.fth
  56.  
  57. ( utility words for dealing with 4x4 matrices )
  58.  
  59.     ( Check top two stack items for range [0..3] )
  60. : rngchk
  61.     dup 0 < swap 3 > or
  62.     swap dup 0 < swap 3 > or or
  63.     if
  64.         ." Range error" cr abort
  65.     endif
  66. ;
  67.  
  68. : @elem  ( v r c --- n ) ( fetches floating point value n from element )
  69.              (   [r,c] of floating point array v )
  70.     2dup rngchk
  71.     4 * swap 16 * + + @ ;
  72.  
  73. : !elem  ( n v r c --- ) ( stores floating point value n in )
  74.              (   element [r,c] of array v )
  75.     2dup rngchk
  76.     4 * swap 16 * + + ! ;
  77.  
  78.     ( Clear a matrix to 0's )
  79. : clrmat
  80.     64 0 fill
  81. ;
  82.  
  83.     ( set up 4x4 matrix to be the identity matrix )
  84. : ident   ( v --- )
  85.  
  86.     dup clrmat   ( clear matrix to all zeros )
  87.     4 0 do
  88.         1.0 1 pick i i !elem
  89.     loop
  90.     drop
  91. ;
  92.  
  93.     ( Print out a matrix )
  94. : .mat
  95.     4 0 do
  96.         4 0 do
  97.             dup j i @elem f. 9 emit
  98.         loop cr
  99.     loop
  100.     drop
  101. ;
  102.  
  103.     ( Allocate a matrix )
  104. : matvar
  105.     variable
  106.     62 allot
  107. ;
  108.  
  109.     ( matcpy--copy one matrix into another )
  110. : matcpy ( src dst -- )
  111.     swap
  112.     16 0 do
  113.         dup @ swap 4 + swap rot dup 4 + -rot !
  114.     loop
  115. ;
  116.  
  117. variable mat1    ( Temporary storage for matrix addresses )
  118. variable mat2
  119. matvar tmpmat    ( And a temporary matrix )
  120. variable tmpw    ( Temp storage for a word quantity )
  121.  
  122. : mat*    ( S T --- )   ( 4x4 matrix multply: T = T * S )
  123.     mat2 !                        ( store addr of matices )
  124.     mat1 !
  125.  
  126.     4 0 do                        ( Which row of mat1 we're on )
  127.         4 0 do                    ( Which column of mat2 )
  128.             0.0 4 0 do            ( For that r & c, loop through & sum )
  129.                 mat1 @ k i @elem
  130.                 mat2 @ i j @elem
  131.                 f* f+
  132.             loop
  133.             tmpmat j i !elem    ( Save the result )
  134.         loop
  135.     loop
  136.  
  137.     tmpmat mat2 @ matcpy            ( copy result to destination )
  138. ;
  139. Funky!Stuff!
  140. cat - << \Funky!Stuff! > object.fth
  141.  
  142. ( Implementation of graphical objects )
  143.  
  144.     ( To keep a linked list of all objects )
  145. variable lstobj 0 lstobj !
  146.  
  147.     ( Intrinsic to create an object )
  148. : newobj
  149.     variable
  150.     -4 allot
  151.  
  152.         ( Add this object to our list )
  153.     here lstobj dup @ , !
  154.  
  155.         ( Initially, each object is displayed )
  156.     true ,
  157.  
  158.         ( And initially, the object has no members )
  159.     0 ,
  160. ;
  161.  
  162.     ( Internal routine to add words to dictionary space )
  163. : (addside) ( xf yf zf -- )
  164.  
  165.         ( They come in the wrong order, so reverse it & store )
  166.     >r
  167.  
  168.         ( Store the three elements of a 3D point )
  169.     here ! 4 allot
  170.     r> here ! 4 allot
  171. ;
  172.  
  173.     ( Add a side to our most current object )
  174. : addside ( x1f y1f z1f x2f y2f z2f -- )
  175.  
  176.         ( Increment the side counter )
  177.     lstobj @ dup if
  178.         8 + dup @ 1 + swap !
  179.     else
  180.         ." No current object" cr abort
  181.     endif
  182.  
  183.         ( We just call our routine once for each point )
  184.     (addside) (addside)
  185. ;
  186.  
  187.     ( Hide & show an object )
  188. : hide ( a -- )
  189.     4 + false swap !
  190. ;
  191. : show ( a -- )
  192.     4 + true swap !
  193. ;
  194.  
  195.     ( Draw an object )
  196. : dr-obj ( a -- )
  197.  
  198.     dup 4 + @ if
  199.  
  200.             ( Don't drop into the do loop if there are no sides )
  201.         dup 8 + @ if
  202.                 ( Repeat for each side... )
  203.             dup 12 + swap 8 + @ 0 do
  204.  
  205.                     ( Stash current address on return stack )
  206.                 dup >r
  207.  
  208.                     ( Get the two points, increment pointer )
  209.                 3d@ r> 12 +
  210.  
  211.                     ( Repeat process for next point, draw line )
  212.                 dup >r 3d@ 3dline r> 12 +
  213.             loop
  214.         endif
  215.     endif
  216.     drop
  217. ;
  218.  
  219.     ( Draw all objects )
  220. : draw
  221.  
  222.         ( Get start of list )
  223.     lstobj @
  224.  
  225.         ( While not at end of list, do an object )
  226.     begin
  227.         dup
  228.     while
  229.         dup @ swap dr-obj
  230.     repeat
  231.     drop
  232. ;
  233.  
  234.     ( These are the words which execute transformations upon objects )
  235.  
  236.     ( This is the matrix which takes on successive transformations )
  237. matvar curxfm
  238.  
  239.     ( xfm--sets up everything, get ready to describe a sequence )
  240.     (  of transformations )
  241. : xfm
  242.     curxfm ident
  243. ;
  244.  
  245.     ( x,y,z rot--do rotations about the various axis )
  246. : xrot ( d -- )
  247.     curxfm (xrot) ;
  248. : yrot ( d -- )
  249.     curxfm (yrot) ;
  250. : zrot ( d -- )
  251.     curxfm (zrot) ;
  252.  
  253. 3dpt tmppt
  254.     ( Reverse the order of the top three 2-word elements )
  255. : revarg ( xf yf zf -- zf yf xf )
  256.     tmppt 3d! tmppt z@ tmppt y@ tmppt x@ ;
  257.  
  258.     ( trans--do a translation )
  259. : trans ( xf yf zf -- )
  260.  
  261.         ( The internal routine wants them the other way around )
  262.     revarg
  263.  
  264.     curxfm (trans) ;
  265.  
  266.     ( scale--do a scaling operation )
  267. : scale ( xf yf zf -- )
  268.     revarg curxfm (scale) ;
  269.  
  270.     ( doxfm--implement all the transformations on the named object )
  271. : doxfm ( a -- )
  272.  
  273.         ( For each point... )
  274.     dup 12 + swap 8 + @ 2 * 0 do
  275.  
  276.             ( Fetch the current point, advance to next )
  277.         dup 12 + swap
  278.  
  279.             ( Hold the current point's address in tmpw )
  280.         tmpw !
  281.  
  282.             ( For each column of the transformation matrix... )
  283.         3 0 do
  284.  
  285.                 ( Do a matrix multiplication )
  286.             tmpw @ x@ curxfm 0 i @elem f*
  287.             tmpw @ y@ curxfm 1 i @elem f*
  288.             tmpw @ z@ curxfm 2 i @elem f*
  289.                       curxfm 3 i @elem
  290.             f+ f+ f+
  291.         loop
  292.             ( Now store the new point, which has been build on the stack, )
  293.             (  back into the current point )
  294.         tmpw @ 3d!
  295.  
  296.     loop drop
  297. ;
  298.  
  299.     ( .obj--print the sides making up an object )
  300. : .obj ( a -- )
  301.  
  302.         ( For each pair of points... )
  303.     dup 12 + swap 8 + @ 0 do
  304.  
  305.             ( Fetch the current point, advance to next )
  306.         dup 12 + swap
  307.         ." (" dup x@ f. 32 emit dup y@ f. 32 emit z@ f. ." ) to ("
  308.         dup 12 + swap
  309.         dup x@ f. 32 emit dup y@ f. 32 emit z@ f. ." )" cr
  310.  
  311.     loop drop
  312. ;
  313.  
  314.     ( Routines for centering & uncentering an object around the origin )
  315.  
  316.     ( Holds the current sum of X,Y,Z values, and # of sides )
  317. 3dpt centmp
  318. variable cencnt
  319.  
  320.     ( Clear the summing temporary variable "centmp" )
  321. : cenclr
  322.     0.0 dup dup centmp 3d! ;
  323.  
  324.     ( Add a transformation which will move the object's center to the )
  325.     (  origin, or move it back from the origin )
  326. : center ( a -- )
  327.  
  328.     cenclr
  329.     dup 8 + @ if
  330.             ( Repeat for each side... )
  331.         dup 12 + swap 8 + @ dup negate i->f cencnt ! 0 do
  332.  
  333.                 ( Add current point's X,Y,Z to centmp )
  334.             dup x@ centmp x@ f+ centmp x!
  335.             dup y@ centmp y@ f+ centmp y!
  336.             dup z@ centmp z@ f+ centmp z!
  337.  
  338.                 ( Advance to next point )
  339.             12 +
  340.         loop
  341.         drop
  342.  
  343.             ( Divide by # of points, negate all coordinates )
  344.         centmp x@ cencnt @ f/
  345.         centmp y@ cencnt @ f/
  346.         centmp z@ cencnt @ f/
  347.         trans
  348.  
  349.     endif
  350. ;
  351. : uncenter
  352.  
  353.         ( Just change the sign of our previous work )
  354.     cencnt @ fnegate cencnt !
  355.  
  356.         ( Divide by # of points )
  357.     centmp x@ cencnt @ f/
  358.     centmp y@ cencnt @ f/
  359.     centmp z@ cencnt @ f/
  360.     trans
  361. ;
  362.  
  363. Funky!Stuff!
  364. cat - << \Funky!Stuff! > plot.fth
  365.  
  366. ( Routines to do plotting of a 3-D line into our 2-D viewing plane )
  367.  
  368.     ( Our center of projection for perspective projection viewing )
  369.     (    Since these are variables, they may be dynamically altered )
  370.     (    interactively. )
  371. variable xc 0.5 xc !
  372. variable yc 0.5 yc !
  373. variable zc -1.0 zc !
  374.  
  375.     ( Intrinsics for handling 3D points )
  376.  
  377.     ( Create a storage cell for a point )
  378. : 3dpt
  379.     variable
  380.     8 allot
  381. ;
  382.  
  383.     ( Fetch/store elements of a point )
  384. : x!    ( xf a -- )
  385.     ! ;
  386. : x@    ( a -- xf )
  387.     @ ;
  388. : y!    ( yf a -- )
  389.     4 + ! ;
  390. : y@    ( a -- yf )
  391.     4 + @ ;
  392. : z!    ( zf a -- )
  393.     8 + ! ;
  394. : z@    ( a -- zf )
  395.     8 + @ ;
  396.  
  397.     ( Point store & fetch primitives )
  398. : 3d! ( xf yf zf a -- )
  399.     dup >r z!
  400.     r> dup >r y!
  401.     r> x!
  402. ;
  403. : 3d@ ( a -- xf yf zf )
  404.     dup >r x@
  405.     r> dup >r y@
  406.     r> z@
  407. ;
  408.  
  409.     ( Print a 3D point )
  410. : 3d.
  411.     ." (" dup x@ f. 32 emit dup y@ f. 32 emit z@ f. ." )"
  412. ;
  413.  
  414.     ( Hold the two points we're clipping against )
  415.     (   and an indicator as to whether any of it is displayable )
  416. 3dpt cp1
  417. 3dpt cp2
  418. variable canshow
  419.  
  420.     ( The clipping words, one for each side of the window )
  421. : cright
  422.     cp1 x@ 0.0 f< cp2 x@ 0.0 f< and if false canshow !
  423.     else
  424.         cp1 x@ 0.0 f< if
  425.             cp1 y@ cp1 x@ cp2 y@ f* cp1 x@ cp1 y@ f* f-
  426.             cp2 x@ cp1 x@ f- f/ f-
  427.             cp1 y! 0.0 cp1 x!
  428.         else
  429.             cp2 x@ 0.0 f< if
  430.                 cp1 y@ cp1 x@ cp2 y@ f* cp1 x@ cp1 y@ f* f-
  431.                 cp2 x@ cp1 x@ f- f/ f-
  432.                 cp2 y! 0.0 cp2 x!
  433.             endif
  434.         endif
  435.     endif
  436. ;
  437. : cleft
  438.     cp1 x@ 1.0 f> cp2 x@ 1.0 f> and if false canshow !
  439.     else
  440.         cp1 x@ 1.0 f> if
  441.             1.0 cp1 x@ f- cp2 x@ cp1 x@ f- f/
  442.             cp2 y@ cp1 y@ f- f* cp1 y@ f+
  443.             cp1 y! 1.0 cp1 x!
  444.         else
  445.             cp2 x@ 1.0 f> if
  446.                 1.0 cp1 x@ f- cp2 x@ cp1 x@ f- f/
  447.                 cp2 y@ cp1 y@ f- f* cp1 y@ f+
  448.                 cp2 y! 1.0 cp2 x!
  449.             endif
  450.         endif
  451.     endif
  452. ;
  453. : cbot
  454.     cp1 y@ 0.0 f< cp2 y@ 0.0 f< and if false canshow !
  455.     else
  456.         cp1 y@ 0.0 f< if
  457.             cp1 x@ cp1 y@ cp2 x@ f* cp1 y@ cp1 x@ f* f-
  458.             cp2 y@ cp1 y@ f- f/ f-
  459.             cp1 x! 0.0 cp1 y!
  460.         else
  461.             cp2 y@ 0.0 f< if
  462.                 cp1 x@ cp1 y@ cp2 x@ f* cp1 y@ cp1 x@ f* f-
  463.                 cp2 y@ cp1 y@ f- f/ f-
  464.                 cp2 x! 0.0 cp2 y!
  465.             endif
  466.         endif
  467.     endif
  468. ;
  469. : ctop
  470.     cp1 y@ 1.0 f> cp2 y@ 1.0 f> and if false canshow !
  471.     else
  472.         cp1 y@ 1.0 f> if
  473.             1.0 cp1 y@ f- cp2 y@ cp1 y@ f- f/
  474.             cp2 x@ cp1 x@ f- f* cp1 x@ f+
  475.             cp1 x! 1.0 cp1 y!
  476.         else
  477.             cp2 y@ 1.0 f> if
  478.                 1.0 cp1 y@ f- cp2 y@ cp1 y@ f- f/
  479.                 cp2 x@ cp1 x@ f- f* cp1 x@ f+
  480.                 cp2 x! 1.0 cp2 y!
  481.             endif
  482.         endif
  483.     endif
  484. ;
  485.  
  486.     ( 2D clipping onto window of <0..1,0..1> )
  487. : 2dline ( x1f y1f x2f y2f -- )
  488.  
  489.         ( Set up our local work variables )
  490.     0.0 cp2 3d! 0.0 cp1 3d! true canshow !
  491.  
  492.         ( Now successively clip left,right,bottom,top )
  493.     cright
  494.     canshow @ if cleft endif
  495.     canshow @ if cbot endif
  496.     canshow @ if ctop endif
  497.  
  498.         ( Finally, get back the clipped endpoints )
  499.     canshow @ if cp1 3d@ drop cp2 3d@ drop line endif
  500. ;
  501.  
  502.     ( Temporary storage for 3D points )
  503. 3dpt t1
  504. 3dpt t2
  505. variable tmp1
  506. variable tmp2
  507.  
  508.     ( intersect--Project t1f onto the plane z=0 against t2f )
  509. : intersect ( t1f t2f -- )
  510.  
  511.         ( Stash their addresses away )
  512.     tmp2 ! tmp1 !
  513.  
  514.         ( Do the perspective projection for x )
  515.     tmp1 @ z@ tmp2 @ x@ f* tmp1 @ x@ tmp2 @ z@ f* f-
  516.     tmp1 @ z@ tmp2 @ z@ f- f/
  517.  
  518.         ( Do the perspective projection for y )
  519.     tmp1 @ z@ tmp2 @ y@ f* tmp1 @ y@ tmp2 @ z@ f* f-
  520.     tmp1 @ z@ tmp2 @ z@ f- f/
  521.  
  522.         ( Replace the old values of t1f with these new ones )
  523.     0.0 tmp1 @ z!
  524.     tmp1 @ y!
  525.     tmp1 @ x!
  526. ;
  527.  
  528.     ( 3line--plot a 3-D line )
  529. : 3dline ( x1f y1f z1f x2f y2f z2f -- )
  530.  
  531.         ( Save the two points )
  532.     t2 3d! t1 3d!
  533.  
  534.         ( Trivial rejection test: if both points are behind our )
  535.         (  view plane, don't plot them. )
  536.     t1 z@ 0.0 f< t2 z@ 0.0 f< and 0 = if
  537.  
  538.             ( We DO have something to plot. If we have a point behind )
  539.             (  the viewing plane, then interpolate it to its intersection )
  540.             (  with the viewing plane. )
  541.         t1 z@ 0.0 f< if t1 t2 intersect
  542.         else
  543.             t2 z@ 0.0 f< if t2 t1 intersect endif
  544.         endif
  545.  
  546.             ( Now do a simple perspective projection, hand the result to )
  547.             (  our 2D plot routine. Note that clipping is done in the 2D )
  548.             (  plot routine, not here. )
  549.         xc @ t1 z@ f* t1 x@ zc @ f* f- t1 z@ zc @ f- f/
  550.         yc @ t1 z@ f* t1 y@ zc @ f* f- t1 z@ zc @ f- f/
  551.         xc @ t2 z@ f* t2 x@ zc @ f* f- t2 z@ zc @ f- f/
  552.         yc @ t2 z@ f* t2 y@ zc @ f* f- t2 z@ zc @ f- f/
  553.         2dline
  554.  
  555.     endif
  556. ;
  557.  
  558. Funky!Stuff!
  559. cat - << \Funky!Stuff! > transform.fth
  560.  
  561.     ( Set up matrix V to do scaling on X, Y, and Z )
  562. : (scale)  ( z y x v --- )
  563.  
  564.         ( Save its address )
  565.     tmpw !
  566.  
  567.         ( Work our way through the elements on the stack, into 0,0, 1,1, ... )
  568.     3 0 do
  569.         tmpw @ i i @elem
  570.         f*
  571.         tmpw @ i i !elem
  572.     loop
  573. ;
  574.  
  575.     ( set up matrix v to do translation )
  576. : (trans) ( z y x v --- )
  577.  
  578.         ( Save address of V into tmpw )
  579.     tmpw !
  580.  
  581.         ( For each element on stack, add it on to current translation )
  582.     3 0 do
  583.         tmpw @ 3 i @elem
  584.         f+
  585.         tmpw @ 3 i !elem
  586.     loop
  587. ;
  588.  
  589.     ( Hold SIN & COS of current angle )
  590. variable sintmp
  591. variable costmp
  592.  
  593.     ( Generate sin & cos for top item on stack, put into sintmp, costmp )
  594. : gentrig ( af -- )
  595.  
  596.         ( Set sintmp, costmp to hold the sin & cosin values of D )
  597.     dup
  598.     fsin sintmp !
  599.     fcos costmp !
  600. ;
  601.  
  602.     ( Make V do a rotation of D radians around x, turning y into z )
  603. : (xrot) ( df v --- )
  604.  
  605.         ( Get our trig values )
  606.     swap gentrig
  607.  
  608.         ( Save matrix address in tmpw )
  609.     tmpw !
  610.  
  611.         ( Loop through the rows )
  612.     4 0 do
  613.  
  614.             ( Calculate an intermediate value, keep it on the stack )
  615.         tmpw @ i 1 @elem costmp @ f*
  616.         tmpw @ i 2 @elem sintmp @ f* f-
  617.  
  618.             ( Now change tmatrix[i,2] )
  619.         tmpw @ i 1 @elem sintmp @ f*
  620.         tmpw @ i 2 @elem costmp @ f* f+
  621.         tmpw @ i 2 !elem
  622.  
  623.             ( Put temporary into tmatrix[i,1] )
  624.         tmpw @ i 1 !elem
  625.  
  626.     loop
  627. ;
  628.  
  629.     ( Make V do a rotation of D radians around y, turning z into x )
  630. : (yrot) ( df v --- )
  631.  
  632.         ( Get our trig values )
  633.     swap gentrig
  634.  
  635.         ( Save matrix address in tmpw )
  636.     tmpw !
  637.  
  638.         ( Loop through the rows )
  639.     4 0 do
  640.  
  641.             ( Calculate an intermediate value, keep it on the stack )
  642.         tmpw @ i 0 @elem costmp @ f*
  643.         tmpw @ i 2 @elem sintmp @ f* f+
  644.  
  645.             ( Now change tmatrix[i,2] )
  646.         tmpw @ i 2 @elem costmp @ f*
  647.         tmpw @ i 0 @elem sintmp @ f* f-
  648.         tmpw @ i 2 !elem
  649.  
  650.             ( Put temporary into tmatrix[i,0] )
  651.         tmpw @ i 0 !elem
  652.  
  653.     loop
  654. ;
  655.  
  656.     ( Make V do a rotation of D radians around z, turning x into y )
  657. : (zrot) ( df v --- )
  658.  
  659.         ( Get our trig values )
  660.     swap gentrig
  661.  
  662.         ( Save matrix address in tmpw )
  663.     tmpw !
  664.  
  665.         ( Loop through the rows )
  666.     4 0 do
  667.  
  668.             ( Calculate an intermediate value, keep it on the stack )
  669.         tmpw @ i 0 @elem costmp @ f*
  670.         tmpw @ i 1 @elem sintmp @ f* f-
  671.  
  672.             ( Now change tmatrix[i,2] )
  673.         tmpw @ i 0 @elem sintmp @ f*
  674.         tmpw @ i 1 @elem costmp @ f* f+
  675.         tmpw @ i 1 !elem
  676.  
  677.             ( Put temporary into tmatrix[i,0] )
  678.         tmpw @ i 0 !elem
  679.  
  680.     loop
  681. ;
  682.  
  683. Funky!Stuff!
  684. cat - << \Funky!Stuff! > turtle.fth
  685.  
  686. ( Words to implement turtle-style graphics )
  687.  
  688. ( The following forth code embodies the algorithms presented )
  689. (  in "Turtle Geometry" by Abelson and diSessa.              )
  690.  
  691.     ( The three vectors which represent our turtle's heading )
  692. 3dpt hdir    ( Heading )
  693. 3dpt udir    ( 'up' direction )
  694. 3dpt ldir    ( 'left' direction )
  695.  
  696.     ( The turtle's cartesian position )
  697. 3dpt tpos
  698.  
  699.     ( Initialize to the standard turtle starting parameters )
  700. 1.0 0.0 0.0 hdir 3d!
  701. 0.0 1.0 0.0 ldir 3d!
  702. 0.0 0.0 1.0 udir 3d!
  703. 0.5 0.5 0.5 tpos 3d!
  704.  
  705.     ( Temporary storage vector )
  706. 3dpt ttmp
  707.  
  708.     ( Word to rotate one vector around another )
  709.     ( Rotates vector 'va' around vector 'pva' 'angle' degrees. )
  710.     ( Returns the new vector as 'nva' on the stack             )
  711. : dorot ( va pva angle -- nva )
  712.  
  713.         ( Get sin, cos of angle--put in sintmp, costmp )
  714.     gentrig
  715.  
  716.         ( Fill in stuff on pva, use 'cp1' for temp storage )
  717.     dup x@ sintmp @ f* cp1 x!
  718.     dup y@ sintmp @ f* cp1 y!
  719.         z@ sintmp @ f* cp1 z!
  720.  
  721.         ( Now add in stuff for va )
  722.     dup x@ costmp @ f* cp1 x@ f+ cp1 x!
  723.     dup y@ costmp @ f* cp1 y@ f+ cp1 y!
  724.         z@ costmp @ f* cp1 z@ f+ cp1 z!
  725.     
  726.         ( Finally, return the address of cp1 as our result )
  727.     cp1
  728. ;
  729.  
  730.     ( Pen position, true=down, false=up )
  731. variable penpos
  732. true penpos !
  733.  
  734.     ( Command to move forward )
  735. : forward ( d -- )
  736.  
  737.         ( Scale distance down by 100 )
  738.     i->f 100.0 f/
  739.  
  740.         ( Now multiply distance by hdir, add to tpos )
  741.     dup hdir x@ f* tpos x@ f+ ttmp x!
  742.     dup hdir y@ f* tpos y@ f+ ttmp y!
  743.         hdir z@ f* tpos z@ f+ ttmp z!
  744.  
  745.         ( Only draw the side if the pen's down )
  746.     penpos @ if
  747.             ( Add a side to current object from old position to new )
  748.         ttmp 3d@ tpos 3d@ addside
  749.     endif
  750.  
  751.         ( update turtle position )
  752.     ttmp 3d@ tpos 3d!
  753. ;
  754.  
  755.     ( 3dneg--return the address of a negated 3d vector. We use cp2, )
  756.     (  so the returned value should be used or copied immediately   )
  757. : 3dneg ( v -- v2 )
  758.     dup x@ fnegate cp2 x!
  759.     dup y@ fnegate cp2 y!
  760.         z@ fnegate cp2 z!
  761.     cp2
  762. ;
  763.  
  764.     ( yaw--this is TURN in 2D, but we go to navigational terms in 3D )
  765. : yaw ( a -- )
  766.  
  767.     i->f
  768.  
  769.         ( Calculate our new H )
  770.     dup hdir ldir rot dorot 3d@ ttmp 3d!
  771.  
  772.         ( Calculate & update L )
  773.     ldir hdir 3dneg rot dorot 3d@ ldir 3d!
  774.  
  775.         ( Now update H )
  776.     ttmp 3d@ hdir 3d!
  777. ;
  778.  
  779.     ( Pitch--tip our nose up or down )
  780. : pitch ( a -- )
  781.  
  782.     i->f
  783.         ( Calculate H )
  784.     dup hdir udir rot dorot 3d@ ttmp 3d!
  785.  
  786.         ( Calculate & update U )
  787.     udir hdir 3dneg rot dorot 3d@ udir 3d!
  788.  
  789.         ( Update H )
  790.     ttmp 3d@ hdir 3d!
  791. ;
  792.  
  793.     ( Roll--tip us sideways )
  794. : roll ( a -- )
  795.  
  796.     i->f
  797.         ( Calculate L )
  798.     dup ldir udir rot dorot 3d@ ttmp 3d!
  799.  
  800.         ( Calculate & update U )
  801.     udir ldir 3dneg rot dorot 3d@ udir 3d!
  802.  
  803.         ( Update L )
  804.     ttmp 3d@ ldir 3d!
  805. ;
  806.  
  807.     ( Pen position changing )
  808. : penup false penpos ! ;
  809. : pendown true penpos ! ;
  810.  
  811. Funky!Stuff!
  812. cat - << \Funky!Stuff! > doc/doc_implement
  813.  
  814. Implementation details of the FORTH graphics system.
  815.  
  816.     This document describes the forth graphics system turned in
  817. as the final project of CIS160 by Andy Valencia and Ross Oliver.
  818.  
  819. 1. Initial system
  820.     The forth system used to implement this graphics package was
  821. the John Hopkins University forth system. This software is in the
  822. public domain.
  823.  
  824. 2. System modifications
  825.     Three major hurdles made it necessary to modify the forth system
  826. as received. First, the system insisted that all identifiers be
  827. UPPER CASE. In a UNIX environment, this was unacceptable. The
  828. string recognition routines of JHU forth were modified so that,
  829. prior to searching for a string, all letters of the string were
  830. mapped to upper case. Thus, backward compatibility was maintained
  831. with existing software, while not forcing us to use upper case.
  832.     The second major problem was the lack of floating point. The
  833. language system was modified so that floating point math was
  834. supported. This entailed adding the floating point routines, and
  835. then modifying the input recognizer to recognize (and handle
  836. specially) floating point numbers. The biggest problem with
  837. this phase was that forth used 16-bit integers, whereas the
  838. floating point numbers were 32-bit quantities. As the major
  839. data structures became apparent, sets of words were developed
  840. so that these 32-bit quantities could be handled naturally.
  841.     Finally, the system possessed no trigonometric functions;
  842. we added sin and cosin. Our implementation of these was quite
  843. efficient; we made a table of the sin values from 0 to 90, then
  844. wrote routines which looked up the angle needed (doing quadrant
  845. mapping, sign changing, etc.), rather than executing a numeric
  846. algorithm. The initial routines returned an integer quantity
  847. which was the sign value scaled by 10000; we later wrote
  848. floating versions of sin and cosin (named "fsin" and "fcos")
  849. which scaled these integers back into real numbers between
  850. -1 and 1.
  851.  
  852. 3. Graphics interface
  853.     Although graphics presentation is most rewarding when done
  854. on a specialized device, we realized that we would probably have
  855. to do most of the development on character-display devices. Thus,
  856. the graphics display device is presented to the higher level
  857. software as a call to "line". Line takes device normal coordinates,
  858. and draws the line on the screen. On, say, a Tek 4016, the call
  859. to line merely scales the values given and displays them. However,
  860. to support character devices, a second technique was developed.
  861. "line" was written using the DDA algorithm in the book. This could
  862. then call the routine "plot", which would a character on the screen.
  863. As an efficiency enhancement, "plot" will not emit any escape
  864. sequences to the terminal if there is already a character plotted
  865. there.
  866.  
  867. 4. Matrix manipulation words
  868.     A set of words were made which allowed matrices to be used in
  869. a relatively natural way. Words were made for allocating matrices,
  870. and for accessing both their individual elements and the matrix in
  871. its entirety.
  872.     Surprisingly, the only bona fide matrix math operation which
  873. was needed was matrix multiplication; most routines access the
  874. elements of a matrix directly for efficiency.
  875.  
  876. 5. Objects
  877.     After carefully considering the book's approach to objects,
  878. which he calls "segments", we decided to take a more classic
  879. approach to the issue. An object is defined as an arbitrary number
  880. of sides. An object is either displayed or not displayed. The
  881. only things you can do to an object are: add sides, display it,
  882. hide it, or execute transformations upon it.
  883.  
  884. 6. Transformation words
  885.     The transformation capability of the forth graphics system
  886. was developed in two layers. First, a set of primitive, generalized
  887. routines were written which generated the desired transformations.
  888. Then a second set of parallel words were written which integrated
  889. all the different transformations into a single mechanism.
  890.     The high level mechanism keeps the successsive transformations
  891. internally, then executes them upon selected objects. Thus, the
  892. forth commands to translate A and B by -0.5 in the X, Y, and Z,
  893. then rotate about the X axis by 45 degrees would be:
  894.      xfm -0.5 -0.5 -0.5 trans 45 xrot a doxfm b doxfm
  895. Note that forth is a free-format language; the commands did not
  896. have to be put on a single line. Also note that the invocation
  897. of the listed transformations is on an object-by-object basis.
  898.  
  899. 7. 3D viewing system
  900.     We soon realized that the display file concept described in
  901. the book was at odds with the interactive nature of the forth
  902. system we were implementing our graphics routines on. The approach
  903. we took was to enhance the interactive nature of the graphics
  904. tools; this is most obvious in our viewing system.
  905.     Our viewing system is invoked by the "draw" word. Each object
  906. which is not hidden will be displayed on the screen. An object
  907. is drawn on a line-by-line basis. The clipping is done in two
  908. passes: first the line is clipped against the viewing plane. If the
  909. line intersects the viewing plane, then the point which is behind
  910. the viewing plane is projected to its intersection with the viewing
  911. plane. If a line is completely behind the plane, it is not displayed.
  912. After this clipping, the two endpoints are mapped onto the plane
  913. using perspective projection. Finally, these points are handed
  914. off to a 2-dimensional routine for display.
  915.     The 2-dimensional routine then clips against the right, left,
  916. top, and bottom borders. Two equivalent ways of looking at the
  917. viewing process can be taken: the viewer can move around the object,
  918. or the object can be moved. In deviating from the book's (and
  919. CORE's) decision to move the viewer, we took the philosophy that
  920. what is most natural to a human should be used. In a system this
  921. size, we will be looking at rather small objects. It is natural
  922. for a human to reach out and manipulate an object, rather than
  923. passively move around it (consider the plethora of "Don't touch"
  924. signs we encounter in museums and expensive stores). Thus, one's
  925. viewing plane is fixed at the plane Y=0, with border limits
  926. of 0..1 for each side.
  927.     We found this solution to be quite acceptable, with the exception
  928. of the case where one wanted to rotate an object to see it from
  929. different angles--it was quite inconvenient to figure out what kind
  930. of translation was needed to move it to the origin. We solved this
  931. by adding the transformations "center" and "uncenter". The former
  932. translates the object so that its center (defined as the arithmetic
  933. mean of its X, Y, and Z componenets) was at the origin. The latter
  934. merely undoes this affect. Thus, a common transformation to view
  935. an object named "box" from a tilted angle might be:
  936.     xfm box center 22 xrot 22 yrot uncenter box doxfm
  937. Which would rotate the box by 22 degrees around its center on both
  938. the X and Y axes.
  939.  
  940. 8. A nicer way to make pictures
  941.     As an application to exercise this graphics system, we implemented
  942. a 3D turtle graphics system. In such a system, you have an entity named
  943. the turtle which possesses a 3D location and heading. Using the
  944. navigational terms "yaw", "pitch", and "roll", one may make the turtle
  945. face in any direction. Then it may be moved forward with (strangely
  946. enough) the "forward" command. These may all be embedded within
  947. a FORTH program, gaining a surprising amount of power. The sequence:
  948. : octa
  949.     8 0 do
  950.         10 forward
  951.         45 yaw
  952.     loop
  953. ;
  954. will generate an octagon. Each turtle "forward" command causes a side
  955. to be added to the current object. Thus, with the previous program
  956. available, the sequence
  957.     newobj showoff
  958.     octa 90 roll octa
  959. will generate a pair of octagons, sharing a common side, which
  960. are at right angles to each other.
  961.  
  962. Funky!Stuff!
  963. cat - << \Funky!Stuff! > doc/doc_words
  964.  
  965.     The following is the list of routines, all written in forth,
  966. which implement the 3D viewing system.
  967.  
  968. init                    ( Clear our graphic buffer )
  969.     This word is called once to initialize the graphics display device.
  970.  
  971. erase
  972.     This will erase the graphics display device.
  973.  
  974. plot ( fx fy -- )
  975.     Draws a point at the specified position. This word is only defined
  976. if the device being driven does not have intrinsic line-drawing
  977. capability. It is used by the "line" word, which is an implementation
  978. of DDA.
  979.  
  980. line ( fx1 fy1 fx2 fy2 -- )
  981.     Implements DDA. Note that the line is NOT clipped; see 2dline
  982. for this functionality. Generally, this word is a simple mapping onto
  983. the escape sequences needed to display on a particular device.
  984.  
  985. rngchk ( r c -- )
  986.     An internal routine which does range checking on the indices of
  987. a matrix element.
  988.  
  989. @elem  ( v r c --- n )
  990.     Fetches the floating point element "fn" from the matrix whose
  991. address is "v", at row "r", column "c".
  992.  
  993. !elem  ( n v r c --- ) ( stores floating point value n in )
  994.     The complementary routine to "@elem@ which stores the value in
  995. the matrix.
  996.  
  997. clrmat
  998.     Initializes all members of a matrix to 0.
  999.  
  1000. ident   ( v --- )
  1001.     Sets the matrix to the identity matrix.
  1002.  
  1003. .mat ( v -- )
  1004.     Prints the contents of a matrix on the screen.
  1005.  
  1006. matvar
  1007.     Allocates space for a named matrix.
  1008.  
  1009. matcpy ( src dst -- )
  1010.     Copies the contents of matrix "src" to "dst".
  1011.  
  1012. mat*    ( S T --- )   ( 4x4 matrix multply: T = T * S )
  1013.     Matrix multiplication: T = T * S.
  1014.  
  1015. fcos ( a -- fv )
  1016.     Returns the floating cosin value of angle 'a', where 'a' is in degrees.
  1017.  
  1018. fsin ( a -- fv )
  1019.     As "fcos", but does sin.
  1020.  
  1021. newobj
  1022.     Allocates space for a new named object, and adds this object to
  1023. the object list. After creation with this routine, sides may be added
  1024. to the object with the "addside" word.
  1025.  
  1026. (addside) ( xf yf zf -- )
  1027.     Internal routine which stores a point into memory.
  1028.  
  1029. addside ( x1f y1f z1f x2f y2f z2f -- )
  1030.     Causes the 3-dimensional line segment to become a part of the
  1031. current object.
  1032.  
  1033. hide ( a -- )
  1034.     Causes the object whose address is "a" to not be displayed during
  1035. display updates. Initially, an object is drawn.
  1036.  
  1037. show ( a -- )
  1038.     Changes the attribute of the object back to "show"; undoes
  1039. the effect of a "hide".
  1040.  
  1041. dr-obj ( a -- )
  1042.     An internal routine which draws the named object on the screen.
  1043.  
  1044. draw
  1045.     Draws all objects whose attribute is "show".
  1046.  
  1047. xfm
  1048.     Starts off a series of transformations. The most common use
  1049. is: xfm <transformation>,... <object> doxfm
  1050. which will cause the named object to be put through the
  1051. specified transformations.
  1052.  
  1053. xrot ( d -- )
  1054. yrot ( d -- )
  1055. zrot ( d -- )
  1056.     Rotation of "d" degrees around the X, Y, and Z axis. Used
  1057. after "xfm" is invoked.
  1058.  
  1059. revarg ( xf yf zf -- zf yf xf )
  1060.     A generally useful word which reverses the order of the top
  1061. three floating point numbers.
  1062.  
  1063. trans ( xf yf zf -- )
  1064.     A translation with offsets of xf, yf, and zf is done. Used after
  1065. "xfm" is invoked.
  1066.  
  1067. scale ( xf yf zf -- )
  1068.     Scales the X, Y, and Z coordinates by xf, yf, and zf. Used with
  1069. "xfm".
  1070.  
  1071. doxfm ( a -- )
  1072.     Implements all pending transformations on the named object. Note
  1073. that the pending transformations may be done to several objects by
  1074. using "<object> doxfm" a number of times.
  1075.  
  1076. .obj ( a -- )
  1077.     Prints the points which make up an object. Generally useful
  1078. only for debugging.
  1079.  
  1080. cenclr
  1081.     An internal initialization routine for the "center" word.
  1082.  
  1083. center ( a -- )
  1084.     Take the named object, figure out its mathematical center, and then
  1085. enter the negation of this as a translation (see "trans"). This is used
  1086. to bring an object to the origin without doing any hand calculations.
  1087.  
  1088. uncenter
  1089.     Undoes the translation done by "center".
  1090.  
  1091. 3dpt
  1092.     Allocates space for the named 3-dimensional point.
  1093.  
  1094. x!    ( xf a -- )
  1095. x@    ( a -- xf )
  1096. y!    ( yf a -- )
  1097. y@    ( a -- yf )
  1098. z!    ( zf a -- )
  1099. z@    ( a -- zf )
  1100.     Fetch & store primitives which access the X, Y, and Z fields
  1101. of a 3D point.
  1102.  
  1103. 3d! ( xf yf zf a -- )
  1104. 3d@ ( a -- xf yf zf )
  1105.     Fetch & store of the 3 elements of a 3D point, en masse.
  1106.  
  1107. 3d.
  1108.     Print a 3D point's values.
  1109.  
  1110. cright
  1111. cleft
  1112. cbot
  1113. ctop
  1114.     Internal routines which clip the four sides of a 2D window.
  1115.  
  1116. 2dline ( x1f y1f x2f y2f -- )
  1117.     Draw a 2D line (by calling "line") after clipping.
  1118.  
  1119. intersect ( t1f t2f -- )
  1120.     Internal routine to 3dline which is used for viewing-plane
  1121. intersection calculations.
  1122.  
  1123. 3dline ( x1f y1f z1f x2f y2f z2f -- )
  1124.     Plot a line expressed in 3D. This routine does front and back-plane
  1125. clipping, then calls 2dline.
  1126.  
  1127. gentrig ( a -- )
  1128.     Internal routine which stores the sin and cosin values of angle "a"
  1129. into sintmp and costmp.
  1130.  
  1131. (scale)  ( z y x v --- )
  1132. (trans) ( z y x v --- )
  1133. (xrot) ( d v --- )
  1134. (yrot) ( d v --- )
  1135. (zrot) ( d v --- )
  1136.     Internal routines which do the actual matrix operations associated
  1137. with scaling, translating, and rotations.
  1138.  
  1139. dorot ( va pva angle -- nva )
  1140.     Internal routine used with the turtle graphics subsystem. Does
  1141. rotations of a vector around a perpendicular vector by "angle" degrees.
  1142.  
  1143. 3dneg ( v -- v2 )
  1144.     Internal turtle graphics routine which negates a 3D vector.
  1145.  
  1146. forward ( d -- )
  1147.     Turtle graphics. Moves the turtle "d" units forward in its
  1148. current direction.
  1149.  
  1150. yaw ( a -- )
  1151.     Turns the turtle right or left on its current plane by 'a' degrees.
  1152.  
  1153. pitch ( a -- )
  1154.     Tips the turtle's nose up or down by "a" degrees.
  1155.  
  1156. roll ( a -- )
  1157.     Rolls the turtle right or left by "a" degrees.
  1158.  
  1159. tab
  1160.     Internal routine to "vlist" which calculates tab stops.
  1161.  
  1162. vlist
  1163.     Word which lists all the words forth currently knows about.
  1164.  
  1165. Funky!Stuff!
  1166. cat - << \Funky!Stuff! > figs/box
  1167.  
  1168. newobj box
  1169. 0.25 0.25 0.1 0.25 0.75 0.1 addside
  1170. 0.25 0.75 0.1 0.75 0.75 0.1 addside
  1171. 0.75 0.75 0.1 0.75 0.25 0.1 addside
  1172. 0.75 0.25 0.1 0.25 0.25 0.1 addside
  1173.  
  1174. 0.25 0.25 0.9 0.25 0.75 0.9 addside
  1175. 0.25 0.75 0.9 0.75 0.75 0.9 addside
  1176. 0.75 0.75 0.9 0.75 0.25 0.9 addside
  1177. 0.75 0.25 0.9 0.25 0.25 0.9 addside
  1178.  
  1179. 0.25 0.25 0.1 0.25 0.25 0.9 addside
  1180. 0.25 0.75 0.1 0.25 0.75 0.9 addside
  1181. 0.75 0.25 0.1 0.75 0.25 0.9 addside
  1182. 0.75 0.75 0.1 0.75 0.75 0.9 addside
  1183.  
  1184. Funky!Stuff!
  1185. cat - << \Funky!Stuff! > figs/turt_box
  1186.  
  1187. : box1
  1188.     -90 pitch 8 forward
  1189.     90 pitch 8 forward
  1190.     90 pitch penup 8 forward pendown
  1191.     90 pitch 8 forward 180 pitch
  1192. ;
  1193. : box2
  1194.     4 0 do
  1195.         box1
  1196.         penup 8 forward pendown
  1197.         90 yaw
  1198.     loop
  1199. ;
  1200.  
  1201. Funky!Stuff!
  1202. cat - << \Funky!Stuff! > figs/turt_oct
  1203.  
  1204. : temp
  1205.     8 0 do
  1206.         10 forward
  1207.         -45 pitch
  1208.         10 forward
  1209.     loop
  1210. ;
  1211. : temp2
  1212.     6 0 do
  1213.         temp
  1214.         30 yaw
  1215.     loop
  1216. ;
  1217.  
  1218. Funky!Stuff!
  1219. cat - << \Funky!Stuff! > figs/turt_tube
  1220.  
  1221. : tub1
  1222.     -90 yaw
  1223.     40 forward
  1224.     90 yaw
  1225.     10 forward
  1226.     90 yaw penup
  1227.     40 forward pendown
  1228.     90 yaw 10 forward
  1229.     180 yaw
  1230. ;
  1231. : tube
  1232.     8 0 do
  1233.         tub1
  1234.         penup 10 forward pendown
  1235.         -45 pitch
  1236.     loop
  1237. ;
  1238.  
  1239. Funky!Stuff!
  1240. cat - << \Funky!Stuff! > figs/turt_tube2
  1241.  
  1242. : tub2
  1243.     90 yaw
  1244.     8 0 do
  1245.         10 forward -45 pitch
  1246.     loop
  1247.     -90 yaw
  1248. ;
  1249. : tube
  1250.     10 0 do
  1251.         tub2
  1252.         penup 5 forward pendown
  1253.     loop
  1254. ;
  1255.  
  1256. Funky!Stuff!
  1257. cat - << \Funky!Stuff! > terms/3a.fth
  1258.  
  1259. ( plot routines for an ADM3A ) decimal
  1260.  
  1261. variable scrnmem 1918 allot
  1262.  
  1263. 42 constant plotchar            ( We will plot with a star )
  1264.  
  1265. : init                    ( Clear our graphic buffer )
  1266.     1920 0 do
  1267.         0 i scrnmem + c!
  1268.     loop
  1269. ;
  1270.  
  1271. : erase
  1272.     init 26 emit
  1273. ;
  1274.  
  1275. : plot ( x y -- )
  1276.     23.0 f* int 23 swap -        ( Turn 0..1 to 23..0 )
  1277.     79.0 f* int                    ( Turn 0..1 into 0..79 )
  1278.     2dup 80 * + scrnmem + dup c@ plotchar = if
  1279.         drop            ( already plotted here )
  1280.         2drop
  1281.     else
  1282.         plotchar swap c!        ( mark our plot )
  1283.         ." ="            ( 3a Cursor address command )
  1284.         32 + emit 32 + emit        ( emit the char )
  1285.         plotchar emit        ( plot our character )
  1286.     endif
  1287. ;
  1288.  
  1289. " line.fth" fload
  1290.  
  1291. Funky!Stuff!
  1292. cat - << \Funky!Stuff! > terms/fake_line.fth
  1293.  
  1294. : line ." (" 2swap f. ." ," f. ." ) to (" 2swap f. ." ," f. ." )" cr ;
  1295.  
  1296. Funky!Stuff!
  1297. cat - << \Funky!Stuff! > terms/grafix.fth
  1298.  
  1299. ( Forth words to drive a victor )
  1300.  
  1301. : init
  1302.   27 emit ." 5d " 27 emit ." m258" cr
  1303.   27 emit ." 52" cr
  1304.   27 emit ." 5r" cr
  1305. ;
  1306.  
  1307. : line ( fx1 fy1 fx2 fy2 -- )
  1308.     399.0 f* 399.0 2swap f- 2swap 572.0 f*
  1309.     27 emit ." 5Q " int . int . cr
  1310.     399.0 f* 399.0 2swap f- 2swap 572.0 f*
  1311.     27 emit ." 5U " int . int . cr
  1312. ;
  1313.  
  1314. : erase
  1315.   27 emit ." 52" cr
  1316.   27 emit ." 5r" cr
  1317. ;
  1318.  
  1319. Funky!Stuff!
  1320. cat - << \Funky!Stuff! > terms/graphon.fth
  1321.  
  1322. ( plot routines for an GRAPHON ) decimal
  1323.  
  1324. : init                    ( Clear our graphic buffer )
  1325.     ." 1"
  1326. ;
  1327.  
  1328. : erase
  1329.     ."  "
  1330. ;
  1331.  
  1332. : plot ( fx fy -- )
  1333.  
  1334.             ( Scale Y 0..1 to 0..781 )
  1335.     760.0 f* int -rot
  1336.     1000.0 f* int swap
  1337.     29 emit
  1338.     2dup                        ( We have to fake a plot )
  1339.  
  1340.     dup 2/ 2/ 2/ 2/ 2/ 31 and    ( Get high 5 bits of Y component )
  1341.     32 or emit                    (   set it up & emit it )
  1342.     31 and 96 or emit            ( Now emit the low four bits )
  1343.     dup 2/ 2/ 2/ 2/ 2/ 31 and    ( Do the same for the X component )
  1344.     32 or emit
  1345.     31 and 64 or emit
  1346.  
  1347.     1+ swap 1+ swap                ( We fake a plot by using a SHORT line )
  1348.     dup 2/ 2/ 2/ 2/ 2/ 31 and    ( Get high 5 bits of Y component )
  1349.     32 or emit                    (   set it up & emit it )
  1350.     31 and 96 or emit            ( Now emit the low four bits )
  1351.     dup 2/ 2/ 2/ 2/ 2/ 31 and    ( Do the same for the X component )
  1352.     32 or emit
  1353.     31 and 64 or emit cr
  1354. ;
  1355.  
  1356. " line.fth" fload
  1357.  
  1358. Funky!Stuff!
  1359. cat - << \Funky!Stuff! > terms/hp.fth
  1360.  
  1361. ( plot routines for an HP terminal ) decimal
  1362.  
  1363. variable scrnmem 1918 allot
  1364.  
  1365. 42 constant plotchar            ( We will plot with a star )
  1366.  
  1367. : init                    ( Clear our graphic buffer )
  1368.     1920 0 do
  1369.         0 i scrnmem + c!
  1370.     loop
  1371. ;
  1372.  
  1373. : erase
  1374.     init ." hJ"
  1375. ;
  1376.  
  1377.     ( Plot the normal coordinate point <x,y> )
  1378. : plot ( xf yf -- )
  1379.     23.0 f* f->i 23 swap - >r    ( turn 0..1 to 23..0 )
  1380.     79.0 f* f->i                ( turn 0..1 to 0..79 )
  1381.     r> 2dup 80 * + scrnmem + dup c@ plotchar = if
  1382.         drop            ( already plotted here )
  1383.         2drop
  1384.     else
  1385.         plotchar swap c!        ( mark our plot )
  1386.         ." &a"                ( HP Cursor address command )
  1387.         . ." r" . ." C"
  1388.         plotchar emit        ( plot our character )
  1389.     endif
  1390. ;
  1391.  
  1392. input terms/line.fth
  1393. Funky!Stuff!
  1394. cat - << \Funky!Stuff! > terms/hp150.fth
  1395.  
  1396. ( plot routines for an HP terminal ) decimal
  1397.  
  1398. : init                ( Select: display graphics & text, solid set line )
  1399.     ." *dace*m2a*m1b "
  1400. ;
  1401.  
  1402. : erase                    ( Clear text screen & graphics )
  1403.     ." hJ*dA"
  1404. ;
  1405.  
  1406.     ( Plot the normal coordinate pof->i <x,y> )
  1407. : line ( x1f y1f x2f y2f -- )
  1408.     ." *pA*d"
  1409.     swap 380.0 f* f->i . ." ,"
  1410.     380.0 f* f->i . ." O*pcB*d"
  1411.     swap 380.0 f* f->i . ." ,"
  1412.     380.0 f* f->i . ." O*pC"
  1413. ;
  1414. Funky!Stuff!
  1415. cat - << \Funky!Stuff! > terms/line.fth
  1416.  
  1417. ( words to provide line-drawing capability )
  1418.  
  1419. ( NOTE: these routines are generally used only with low-resolution )
  1420. (    terminals without intrinsic line-drawing ability.              )
  1421.  
  1422. variable p1x            ( Storage for our two points )
  1423. variable p1y
  1424. variable p2x
  1425. variable p2y
  1426.  
  1427. variable dx            ( Holds delta-x,y )
  1428. variable dy
  1429.  
  1430. : line ( x2f y2f x1f y1f -- )
  1431.  
  1432.         ( Save end points )
  1433.     p1y ! p1x !
  1434.     p2y ! p2x !
  1435.  
  1436.         ( Calculate DX, DY )
  1437.     p2x @ p1x @ f- dx !
  1438.     p2y @ p1y @ f- dy ! 
  1439.  
  1440.         ( Calculate # steps needed )
  1441.     dx @ fabs dy @ fabs fmax 132.0 f* 1.0 f+
  1442.  
  1443.         ( Scale DX, DY for this number of steps )
  1444.     dx @ over f/ dx !
  1445.     dy @ over f/ dy !
  1446.  
  1447.         ( For the required # of steps, do... )
  1448.     f->i 0 do
  1449.  
  1450.             ( Get the current point, store it back incremented by DX,DY )
  1451.         p1x @ dup dx @ f+ p1x !
  1452.         p1y @ dup dy @ f+ p1y !
  1453.  
  1454.             ( Plot the point )
  1455.         plot
  1456.  
  1457.     loop
  1458.  
  1459. ;
  1460.  
  1461. Funky!Stuff!
  1462.