TweetFollow Us on Twitter

Graf3D
Volume Number:4
Issue Number:6
Column Tag:Forth Forum

Graf3D Library Access

By Jörg Langowski, MacTutor Editorial Board

Graf3D and Mach2 - accessing external libraries

The subject of this month has been initiated by one of our readers, Paul Thomas, who in a desperate mood sent me both a paper letter and GEnie mail, because he needed to know whether it would be possible at all to access the Graf3D routines from Mach2.

A little background for those who weren’t with the Mac (or with us, for that matter) from the beginning: Graf3D is a set of routines on top of QuickDraw, which enable to create a 3-d GrafPort with all necessary support to do 3-dimensional perspective drawing. The routines aren’t explained in Inside Macintosh, but in several other different documents, one of them being the MPW Pascal manual (Appendix J).

Graf3D was also part of the Lisa Workshop, and one of the first Macintosh demo programs, Boxes, used those routines. The Boxes program - many of you might have seen it - draws at random fifteen rectangular boxes on a plane and displays them in a 3-d perspective view. The program is written originally in Lisa Pascal, and also contained on the TML Pascal disk as an example. Listing 4 shows the original program.

Glancing through the code, you might notice that this example certainly wouldn’t please the User Interface Thought Police today. Using the whole screen as a GrafPort without regard to anything else on there is a definite no-no in the days of Multifinder, and if you run the example under Multifinder, you won’t find your windows back on the screen afterwards because they are all covered by little boxes. Nevertheless, it is a nice example for the use of Graf3D, and we’ll show you this month how to translate it into Mach2 (We’ll also correct the garbled screen problem under Multifinder).

First and most difficult question: How can we access routines from Forth that are clearly labeled (Not in ROM) in the documentation? This remark tells us, of course, that they are part of some object library, no source code available and inaccessible to the Forth user. Just like the printing manager was before it was implemented in the Mach2 and MacForth systems.

There may be other libraries to come, also not in ROM, and waiting for updates takes a long time. So I’ll give you two general strategies to get access to object library code from Forth, making you independent of those updates.

The first scheme I thought up was simply to write a short Pascal program that calls all the routines at least once - so that they will be loaded -, compile that program, create a linker map if possible, and pass the final application through Nosy. That will get you a more or less annotated assembly listing from which you can extract the source code of the not in ROM routines that you are interested in.

Well, that works for you and me on our respective desks, but we certainly cannot publish reverse-engineered Apple source code in MacTutor, at least if we want to stay in business. Also, it is a lot of work (i.e. translating to a different assembler dialect, writing the glue code, etc.), and all in all qualifies as a master example of a dirty hack.

There is an easier way to go, and much more general, too: write some sort of a linker for Pascal library code. We write an assembly main program (Listing 2), which is just a table of JMP instructions to the routines that we want to call, and let the MPW linker do its job (listing 3).

The assembly/link script will create a new resource, gr3D, which contains the jump instructions at the beginning, followed by the linked Graf3D code. All we have to do now is to provide a block of memory in our Forth code where this resource can be copied to.

In order to assign Forth words to the JMP instructions, we simply make a table of CREATEs, which will allocate 4 bytes to each name (the length of a JMP d(PC) instruction), and create a dictionary entry so that we know the routine’s address in the jump table. After the block of CREATEs, we allocate sufficient memory so that the gr3D resource can be loaded (see listing 1).

We write a word, Init3D, that gets the gr3D resource and copies it into the table, starting with the address of the first Graf3d word, gInitGrf3D. Now the Graf3D routines are all set up for use by Mach2. As simple as that.

Well, not quite. We still need to write glue code to move the parameters from the Forth stack (A6) to the Pascal stack (A7). That glue code is rather simple and is just the same as is used for calling toolbox ROM routines. Like the traps, the Graf3D code preserves all registers that are vital to Mach2 (A2-A7, D4-D7). Like in the case of traps, we have to make A7 point to the lowest stack (EXG D4,A7) in order to avoid overwriting of Mach2 space by the intermediate Quickdraw record that is put between the stack and the heap. The glue code for the different Graf3D routines is given at the beginning of listing 1.

The Boxes examples should be self-explanatory when you compare it with the Pascal code; in fact, it might help some of you Pascal programmers and casual Forth readers appreciate that there is really no big difference between Forth and Pascal code...

I should point out some more things. First, the ‘access words’ for fields in a record, .x, .y, .pt1, and so on, defined at the beginning of the Forth code. Second, the word restore.screen, which cleans up the display after the example has run; very important when running under Multifinder. It basically does a PaintBehind(FrontWindow, grayRgn), the same mechanism by which many screen savers restore a blacked-out screen. Third, we define a terminal task that runs the Boxes example; that way, we can simply check for ?terminal after each drawing loop to see whether we’re done. Again, we have to make sure (like always in Mach2 multitasking) that the correct GrafPort is set by calling myPort3D SetPort3D before each passage through the loop. This is because any PAUSE-containing word, such as ?terminal, may change the active GrafPort.

For using the example, you will first have to create the Graf3Dglue resource file with the gr3D resource in it, then move that resource into the MACH.RSRC file before starting your Mach2 system. In case you don’t have access to MPW, the source code disk contains the Graf3Dglue and MACH.RSRC files. The complete program, of course, is also on the disk.

That’s it for this month; next month I plan to discuss various projects of object-oriented extensions to Mach2 that have recently appeared on the networks. Some of you might also appreciate that NEON hasn’t died altogether, but that there is at least one person trying to extend it in a very interesting way.

Listing 1: The Boxes example in Mach2
\ Graf3d / Mach2 glue code
\ An example for calling MPW routines from Forth
\ J. Langowski April 1988
\ __________________________________________
Only Forth Also Mac Also Assembler

\ some general definitions first
16 CONSTANT portRect

GLOBAL
 CODE SCALE
    MOVE.L   (A6)+,D0
    BMI.S    @1
    MOVE.L   (A6),D1
    ASL.L    D0,D1
    MOVE.L   D1,(A6)
    RTS
@1  MOVE.L   (A6),D1
    NEG.L    D0
    ASR.L    D0,D1
    MOVE.L   D1,(A6)
    RTS
END-CODE

global
CODE white
 MOVE.L (A5),-(A6)
 SUBQ.L #8,(A6)
 RTS
END-CODE MACH

global
CODE black
 MOVE.L (A5),-(A6)
 SUBI.L #16,(A6)
 RTS
END-CODE MACH

global
CODE gray
 MOVE.L (A5),-(A6)
 SUBI.L #24,(A6)
 RTS
END-CODE MACH

: 4ASCII 
 0
4 0 DO
  8 SCALE 0 WORD 1+ C@ + 
LOOP
;

4ASCII gr3D CONSTANT “gr3D \ resource ID

\ Graf3D jump table

CREATE  gInitGrf3D
CREATE  gOpen3DPort
CREATE  gSetPort3D 
CREATE  gGetPort3D 
CREATE  gMoveTo2D
CREATE  gMoveTo3D
CREATE  gLineTo2D
CREATE  gLineTo3D
CREATE  gMove2D
CREATE  gMove3D
CREATE  gLine2D
CREATE  gLine3D
CREATE  gViewPort
CREATE  gLookAt
CREATE  gViewAngle
CREATE  gIdentity
CREATE  gScale
CREATE  gTranslate
CREATE  gPitch
CREATE  gYaw
CREATE  gRoll
CREATE  gSkew
CREATE  gTransform
CREATE  gClip3D
CREATE  gSetPt3D
CREATE  gSetPt2D

\ The glue code is 2636 bytes long, so we allocate
\ sufficient additional buffer space to put it into
2600 ALLOT

: Init3D \ gets Graf3D code from gr3D=1 resource 
  \ and copies it into buffer
 “gr3D 1 call GetResource
 dup @ swap call SizeRsrc
 [‘] gInitGrf3D swap cmove
;

CODE InitGrf3d ( globalPtr -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gInitGrf3d
 EXG  D4,A7
 RTS
END-CODE

CODE Open3DPort  ( port -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gOpen3DPort
 EXG  D4,A7
 RTS
END-CODE

CODE SetPort3d ( port -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gSetPort3d
 EXG  D4,A7
 RTS
END-CODE

CODE GetPort3d ( VAR port -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gGetPort3d
 EXG  D4,A7
 RTS
END-CODE

CODE MoveTo2d  ( x y -- )
 EXG  D4,A7
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #8,A6
 JSR  gMoveTo2d
 EXG  D4,A7
 RTS
END-CODE

CODE MoveTo3d  ( x y z -- )
 EXG  D4,A7
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #12,A6
 JSR  gMoveTo3d
 EXG  D4,A7
 RTS
END-CODE

CODE LineTo2d  ( x y -- )
 EXG  D4,A7
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #8,A6
 JSR  gLineTo2d
 EXG  D4,A7
 RTS
END-CODE

CODE LineTo3d  ( x y z -- )
 EXG  D4,A7
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #12,A6
 JSR  gLineTo3d
 EXG  D4,A7
 RTS
END-CODE

CODE Move2d ( dx dy -- )
 EXG  D4,A7
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #8,A6
 JSR  gMove2d
 EXG  D4,A7
 RTS
END-CODE

CODE Move3d ( dx dy dz -- )
 EXG  D4,A7
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #12,A6
 JSR  gMove3d
 EXG  D4,A7
 RTS
END-CODE

CODE Line2d ( x y -- )
 EXG  D4,A7
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #8,A6
 JSR  gLine2d
 EXG  D4,A7
 RTS
END-CODE

CODE Line3d ( x y z -- )
 EXG  D4,A7
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #12,A6
 JSR  gLine3d
 EXG  D4,A7
 RTS
END-CODE

CODE ViewPort  ( r -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gViewPort
 EXG  D4,A7
 RTS
END-CODE

CODE LookAt ( left top right bottom -- )
 EXG  D4,A7
 MOVE.L 12(A6),-(A7)
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #16,A6
 JSR  gLookAt
 EXG  D4,A7
 RTS
END-CODE

CODE ViewAngle ( angle -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gViewAngle
 EXG  D4,A7
 RTS
END-CODE

CODE Identity
 EXG  D4,A7
 JSR  gIdentity
 EXG  D4,A7
 RTS
END-CODE

CODE Scal ( xfactor yfactor zfactor -- )
 EXG  D4,A7
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #12,A6
 JSR  gScale
 EXG  D4,A7
 RTS
END-CODE

CODE Translate ( dx dy dz -- )
 EXG  D4,A7
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #12,A6
 JSR  gTranslate
 EXG  D4,A7
 RTS
END-CODE

CODE Pitch( xangle -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gPitch
 EXG  D4,A7
 RTS
END-CODE

CODE Yaw( yangle -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gYaw
 EXG  D4,A7
 RTS
END-CODE

CODE Rol( zangle -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gRoll
 EXG  D4,A7
 RTS
END-CODE

CODE Skew ( zangle -- )
 EXG  D4,A7
 MOVE.L (A6)+,-(A7)
 JSR  gSkew
 EXG  D4,A7
 RTS
END-CODE

CODE Transform ( src dst -- )
 EXG  D4,A7
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #8,A6
 JSR  gTransform
 EXG  D4,A7
 RTS
END-CODE

CODE Clip3D ( src1 src2 dst1 dst2 -- flag )
 EXG  D4,A7
 CLR.W  -(A7)
 MOVE.L 12(A6),-(A7)
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #16,A6
 JSR  gClip3D
 MOVE.W (A7)+,D0
 EXT.L  D0
 MOVE.L D0,-(A6)
 EXG  D4,A7
 RTS
END-CODE

CODE SetPt3d( pt3D x y z -- )
 EXG  D4,A7
 MOVE.L 12(A6),-(A7)
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #16,A6
 JSR  gSetPt3D
 EXG  D4,A7
 RTS
END-CODE

CODE SetPt2d( pt2D x y -- )
 EXG  D4,A7
 MOVE.L 8(A6),-(A7)
 MOVE.L 4(A6),-(A7)
 MOVE.L (A6),-(A7)
 ADDA.W #12,A6
 JSR  gSetPt2D
 EXG  D4,A7
 RTS
END-CODE

\ Translation of Boxes.pas example into Forth follows
\ _________________________________________

: .x ; mach
: .y 4 + ; mach
: .z 8 + ; mach

: .pt1 ; mach
: .pt2 12 + ; mach

15 CONSTANT BoxCount
Variable MyPort  104 vallot 
 \ grafPort is 108 bytes long
Variable MyPort3D  150 vallot 
 \ graf3DPort is 154 bytes long
Variable boxArray   24 BoxCount * vallot 
 \ BoxCount * 2* point3D @ 3 long words
Variable nboxes     \ # of boxes made
Variable MyBox   20 vallot \ 24 bytes for 2* point3d
Variable p1   8 vallot \ point3d
Variable p2   8 vallot \ point3d
Variable myRect    4 vallot \ Rect
Variable testRect   4 vallot \ Rect

: DrawBrick { pt1 pt2 | tempRgn -- }
 call NewRgn -> tempRgn

 call OpenRgn  
 pt1 .x @ pt1 .y @ pt1 .z @ MoveTo3D
 pt1 .x @ pt1 .y @ pt2 .z @ LineTo3D
 pt2 .x @ pt1 .y @ pt2 .z @ LineTo3D
 pt2 .x @ pt1 .y @ pt1 .z @ LineTo3D
 pt1 .x @ pt1 .y @ pt1 .z @ LineTo3D
 tempRgn call CloseRgn
 tempRgn white call FillRgn

 call OpenRgn
 pt1 .x @ pt1 .y @ pt2 .z @ MoveTo3D
 pt1 .x @ pt2 .y @ pt2 .z @ LineTo3D
 pt2 .x @ pt2 .y @ pt2 .z @ LineTo3D
 pt2 .x @ pt1 .y @ pt2 .z @ LineTo3D
 pt1 .x @ pt1 .y @ pt2 .z @ LineTo3D
 tempRgn call CloseRgn
 tempRgn gray call FillRgn

 call OpenRgn  
 pt2 .x @ pt1 .y @ pt1 .z @ MoveTo3D
 pt2 .x @ pt1 .y @ pt2 .z @ LineTo3D
 pt2 .x @ pt2 .y @ pt2 .z @ LineTo3D
 pt2 .x @ pt2 .y @ pt1 .z @ LineTo3D
 pt2 .x @ pt1 .y @ pt1 .z @ LineTo3D
 tempRgn call CloseRgn
 tempRgn black call FillRgn

 white call penpat
 pt2 .x @ pt2 .y @ pt2 .z @ MoveTo3D
 pt2 .x @ pt2 .y @ pt1 .z @ LineTo3D
 pt2 .x @ pt1 .y @ pt1 .z @ LineTo3D
 call pennormal

 tempRgn call DisposRgn
;

: hi -16 scale ;

: chkBox { | box -- }
 1 ( flag )
 nBoxes @ 0 DO
 boxArray i 24 * + -> box
 testRect  
 box .pt1 .x @ hi   
 box .pt1 .y @ hi 
 box .pt2 .x @ hi 
 box .pt2 .y @ hi  call SetRect
 testRect -1 -1 call InSetRect
 myRect testRect testRect call SectRect
 IF drop 0 leave THEN
 LOOP
;

: MakeBox { | p1x p1y p1z p2x p2y p2z box ii -- }
 call random 70 mod 15 - 1 call FixRatio -> p1x
 call random 70 mod 10 - 1 call FixRatio -> p1y
 0 -> p1z

 call random 30 mod abs 10 + 1 call FixRatio p1x + 
 -> p2x
 call random 45 mod abs 10 + 1 call FixRatio p1y + 
 -> p2y
 call random 30 mod abs 10 + 1 call FixRatio p1z + 
 -> p2z

 myRect p1x hi p1y hi p2x hi p2y hi call SetRect

 chkBox IF
 p1x myBox .pt1 .x !
 p1y myBox .pt1 .y !
 p1z myBox .pt1 .z !
 p2x myBox .pt2 .x !
 p2y myBox .pt2 .y !
 p2z myBox .pt2 .z !

 0 -> ii
 myBox boxArray nBoxes @ 24 * + 24 cmove

 BEGIN
 myBox .pt1 .y @  boxArray ii + .pt2 .y @ >
 myBox .pt2 .y @  boxArray ii + .pt1 .y @ > and
 myBox .pt1 .x @  boxArray ii + .pt2 .x @ <
 myBox .pt2 .x @  boxArray ii + .pt1 .x @ < and or
 WHILE
 24 +> ii
 REPEAT
 ii 24 / -> ii

 ii 1+ nBoxes @ DO
 boxArray i 1- 24 * +
 boxArray i 24 * + 
 24 cmove
 -1 +loop
 myBox boxArray ii 24 * + 24 cmove
 
 1 nBoxes +!
 THEN
;

: drawGrid
 11 -10 DO
 i 10 * 1 call FixRatio -100 1 call FixRatio 0
 MoveTo3D
 i 10 * 1 call FixRatio  100 1 call FixRatio 0
 LineTo3D
 LOOP

 11 -10 DO
 -100 1 call FixRatio i 10 * 1 call FixRatio 0
 MoveTo3D
  100 1 call FixRatio i 10 * 1 call FixRatio 0
 LineTo3D
 LOOP
;

: restore.screen
 call drawmenubar
 call frontwindow 
 grayrgn @ call paintbehind
 call showcursor
;

: main
 init3d
 call hidecursor
 myPort call OpenPort
 myPort3D Open3DPort
 myPort portRect + ViewPort
 -100 1 call FixRatio  75 1 call FixRatio
  100 1 call FixRatio -75 1 call FixRatio
 LookAt
 30 1 call FixRatio ViewAngle
 Identity
 20 1 call FixRatio Rol
 70 1 call FixRatio Pitch 

 BEGIN
 myPort3D SetPort3D
 0 nBoxes !
 BEGIN makeBox nBoxes @ boxCount = UNTIL

 white call penPat
 black call backPat
 myPort portRect + call EraseRect

 drawGrid

 0 nBoxes @ 1- DO
 boxArray i 24 * + 
 dup .pt1 swap .pt2 DrawBrick
 -1 +LOOP 
 
 ?terminal UNTIL
 restore.screen
 bye
;

NEW.WINDOW Boxes
“ Boxes” Boxes TITLE
0 0 20 20 Boxes BOUNDS
Plain Visible NoCloseBox NoGrowBox Boxes ITEMS

600 5000 terminal Box

: go.box activate main ;

: start
 Boxes add
 Boxes Box build
 Box go.Box
; 

.( To create a turkey application ) cr
.( type TURNKEY START BOXES )
Listing 2: MPW Assembly glue code for accessing the Graf3D Pascal library
 TITLE  ‘Graf3D glue code for Mach2’
 BLANKS OFF 
 PRINT  OFF
 INCLUDE  ‘Traps.a’
 INCLUDE  ‘ToolEqu.a’
 INCLUDE  ‘QuickEqu.a’
 INCLUDE  ‘SysEqu.a’
 INCLUDE  ‘Graf3DEqu.a’
 PRINT  ON

GrafGlueMAIN
 JMP   InitGrf3D
 JMP   Open3DPort
 JMP   SetPort3D
 JMP   GetPort3D
 JMP   MoveTo2D
 JMP   MoveTo3D
 JMP   LineTo2D
 JMP   LineTo3D
 JMP   Move2D
 JMP   Move3D
 JMP   Line2D
 JMP   Line3D
 JMP   ViewPort
 JMP   LookAt
 JMP   ViewAngle
 JMP   Identity
 JMP   Scale
 JMP   Translate
 JMP   Pitch
 JMP   Yaw
 JMP   Roll
 JMP   Skew
 JMP   Transform
 JMP   Clip3D
 JMP   SetPt3D
 JMP   SetPt2D
 END  
Listing 3: MPW assembly / link script for generating the gr3D resource 
(to be put into the MACH.RSRC file)
 Asm Graf3dglue.a -l
 Link Graf3dglue.a.o 
 {Libraries}Interface.o 
 -rt gr3D=1 -o Graf3dglue -l > Graf3dglue.map
Listing 4: The original Boxes example (from TML Pascal)
 PROGRAM Boxes;

{ Boxes demonstrates the use of the Three Dimensional
Quickdraw package Graf3D.

  Pascal source:  Boxes.Pas
  Resources:      *none*
  
  This program is from Apple’s Lisa Software Supplement,
modified for TML Systems Pascal compiler.
}

USES MacIntf, FixMath, Graf3D;

CONST boxCount = 15;
 keyOrMouse = 10;

TYPE  Box3D = 
     RECORD
 pt1: Point3D;
 pt2: Point3D;
     END;

VARmyPort:   GrafPort;
 myPort3D: Port3D;
 boxArray: ARRAY [0..boxCount] OF Box3D;
 nBoxes:   INTEGER;
 i:        INTEGER;
 dummy:    EventRecord;
      
PROCEDURE DrawBrick(pt1, pt2: Point3D);
{ draws a 3D brick with shaded faces.  
  only shades correctly in one direction.
}
VARtempRgn: RgnHandle;
BEGIN
   tempRgn := NewRgn;
   OpenRgn;
   MoveTo3D(pt1.X, pt1.Y, pt1.Z); { front face, y=y1 }
   LineTo3D(pt1.X, pt1.Y, pt2.Z);
   LineTo3D(pt2.X, pt1.Y, pt2.Z);
   LineTo3D(pt2.X, pt1.Y, pt1.Z);
   LineTo3D(pt1.X, pt1.Y, pt1.Z);
   CloseRgn(tempRgn);
   FillRgn(tempRgn, white);

   OpenRgn;
   MoveTo3D(pt1.X, pt1.Y, pt2.Z); { top face, z=z2 }
   LineTo3D(pt1.X, pt2.Y, pt2.Z);
   LineTo3D(pt2.X, pt2.Y, pt2.Z);
   LineTo3D(pt2.X, pt1.Y, pt2.Z);
   LineTo3D(pt1.X, pt1.Y, pt2.Z);
   CloseRgn(tempRgn);
   FillRgn(tempRgn, gray);

   OpenRgn;
   MoveTo3D(pt2.X, pt1.Y, pt1.Z); { right face, x=x2 }
   LineTo3D(pt2.X, pt1.Y, pt2.Z);
   LineTo3D(pt2.X, pt2.Y, pt2.Z);
   LineTo3D(pt2.X, pt2.Y, pt1.Z);
   LineTo3D(pt2.X, pt1.Y, pt1.Z);
   CloseRgn(tempRgn);
   FillRgn(tempRgn, black);

   PenPat(white);
   MoveTo3D(pt2.X, pt2.Y, pt2.Z); { outline right }
   LineTo3D(pt2.X, pt2.Y, pt1.Z);
   LineTo3D(pt2.X, pt1.Y, pt1.Z);
   PenNormal;

   DisposeRgn(tempRgn);
END;

PROCEDURE MakeBox;
LABEL 1;
VARmyBox: Box3D;
 i, j, h, v: INTEGER;
 p1, p2: Point3D;
 myRect: Rect;
 testRect: Rect;
BEGIN
   p1.x := FixRatio((Random mod 70 - 15), 1);
   p1.y := FixRatio((Random mod 70 - 10), 1);
   p1.z := 0;

   p2.x := p1.x + FixRatio((10 + ABS(Random) MOD 30), 1);
   p2.y := p1.y + FixRatio((10 + ABS(Random) MOD 45), 1);

   p2.z := p1.z + FixRatio((10 + ABS(Random) MOD 35), 1);

   { reject box if it intersects one already in list }
   SetRect(myRect, HiWord(p1.x), HiWord(p1.y), HiWord(p2.x), HiWord(p2.y));

   FOR i := 0 TO nBoxes - 1 DO BEGIN
      WITH boxArray[i] DO
  SetRect(testRect, 
          HiWord(pt1.x), 
  HiWord(pt1.y), 
  HiWord(pt2.x),
          HiWord(pt2.y));
      InSetRect(testRect, -1, -1);
      IF SectRect(myRect, testRect, testRect) THEN goto 1
      END;

   myBox.pt1 := p1;
   myBox.pt2 := p2;

   { calc midpoint of box and its distance from the eye }
   i := 0;
   boxArray[nBoxes].pt1 := myBox.pt1; { sentinel }
   boxArray[nBoxes].pt2 := myBox.pt2;

   WHILE
   ((myBox.pt1.y > boxArray[i].pt2.y) AND (myBox.pt2.y > boxArray[i].pt1.y)) 
OR
   ((myBox.pt1.x < boxArray[i].pt2.x) AND (myBox.pt2.x < boxArray[i].pt1.x)) 
DO
      inc(i); { insert in order of dist }
   FOR j := nBoxes DOWNTO i + 1 DO boxArray[j] := boxArray[j - 1];
   boxArray[i] := myBox;
   inc(nBoxes);
1: 
END;

BEGIN { main program }
   FlushEvents(everyEvent, 0);
   InitGraf(@thePort);
   InitCursor;
   HideCursor;
   OpenPort(@myPort);
   Open3DPort(@myPort3D);

   { put the image in this rect }
   ViewPort(myPort.portRect);
   
   { aim the camera into 3D space }   
   LookAt(FixRatio(-100, 1), 
          FixRatio(75, 1), 
   FixRatio(100, 1),
          FixRatio(-75, 1)); 

   { choose lens focal length }
   ViewAngle(FixRatio(30, 1)); 
   Identity;
   Roll(FixRatio(20, 1));
   Pitch(FixRatio(70, 1)); { roll and pitch the plane }

   REPEAT
      nBoxes := 0;
      REPEAT
         MakeBox
      UNTIL nBoxes=boxCount;

      PenPat(white);
      BackPat(black);
      EraseRect(myPort.portRect);

      FOR i := -10 TO 10 DO BEGIN
         MoveTo3D(FixRatio(i*10, 1), FixRatio(-100, 1), 0);
         LineTo3D(FixRatio(i*10, 1), FixRatio(100, 1), 0);
         END;

      FOR i := -10 TO 10 DO BEGIN
         MoveTo3D(FixRatio(-100, 1), FixRatio(i*10, 1), 0);
         LineTo3D(FixRatio(100, 1), FixRatio(i*10, 1), 0);
         END;

      FOR i := nBoxes-1 DOWNTO 0 DO 
         DrawBrick(boxArray[i].pt1,boxArray[i].pt2);

   UNTIL OSEventAvail(keyOrMouse, dummy);
END.
 
AAPL
$524.94
Apple Inc.
+5.93
MSFT
$40.01
Microsoft Corpora
-0.39
GOOG
$536.10
Google Inc.
-20.44

MacTech Search:
Community Search:

Software Updates via MacUpdate

VMware Fusion 6.0.3 - Run Windows apps a...
VMware Fusion allows you to create a Virtual Machine on your Mac and run Windows (including Windows 8.1) and Windows software on your Mac. Run your favorite Windows applications alongside Mac... Read more
Tweetbot 1.5.1 - Popular iOS twitter cli...
Tweetbot is a full-featured OS X Twitter client with a lot of personality. Whether it's the meticulously-crafted interface, sounds and animation, or features like multiple timelines and column views... Read more
Mac DVDRipper Pro 4.1.7 - Copy, backup,...
Mac DVDRipper Pro is the DVD backup solution that lets you protect your DVDs from scratches, save your batteries by reading your movies from your hard disk, manage your collection with just a few... Read more
PDFpenPro 6.2 - Advanced PDF toolkit for...
PDFpenPro allows users to edit PDF's easily. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Create... Read more
PDFpen 6.2 - Edit and annotate PDFs with...
PDFpen allows users to easily edit PDF's. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Features... Read more
Monolingual 1.5.9 - Remove unwanted OS X...
Monolingual is a program for removing unnecesary language resources from OS X, in order to reclaim several hundred megabytes of disk space. It requires a 64-bit capable Intel-based Mac and at least... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
Starcraft II: Wings of Liberty 1.1.1.180...
Download the patch by launching the Starcraft II game and downloading it through the Battle.net connection within the app. Starcraft II: Wings of Liberty is a strategy game played in real-time. You... Read more
Sibelius 7.5.0 - Music notation solution...
Sibelius is the world's best-selling music notation software for Mac. It is as intuitive to use as a pen, yet so powerful that it does most things in less than the blink of an eye. The demo includes... Read more
Typinator 5.9 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more

Latest Forum Discussions

See All

Have a Special Dead Trigger 2 Easter Bas...
Have a Special Dead Trigger 2 Easter Basket Full of Goodies, Courtesy of Madfinger Games Posted by Rob Rich on April 18th, 2014 [ permalink ] Dead Trigger 2 | Read more »
Almost All of Playdek’s Library is on Sa...
Almost All of Playdek’s Library is on Sale Right Now, and You Should Check it Out Posted by Rob Rich on April 18th, 2014 [ permalink ] Playdek has released quite a few great iOS ports of board and card games over the years, and now most of them... | Read more »
Zynga Launches Brand New Farmville Exper...
Zynga Launches Brand New Farmville Experience with Farmville 2: Country Escape Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
David. Review
David. Review By Cata Modorcea on April 18th, 2014 Our Rating: :: MINIMALISTIC IN A DIFFERENT WAYUniversal App - Designed for iPhone and iPad David is a minimalistic game wrapped inside of a soothing atmosphere in which the hero... | Read more »
Eyefi Unveils New Eyefi Cloud Service Th...
Eyefi Unveils New Eyefi Cloud Service That Allows Users to Share Media Across Personal Devices Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
Tales from the Dragon Mountain: The Lair...
Tales from the Dragon Mountain: The Lair Review By Jennifer Allen on April 18th, 2014 Our Rating: :: STEADY ADVENTURINGiPad Only App - Designed for the iPad Treading a safe path, Tales from the Dragon Mountain: The Lair is a... | Read more »
Yahoo Updates Flickr App with Advanced E...
Yahoo Updates Flickr App with Advanced Editing Features and More Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
My Incredible Body - A Kid's App to...
My Incredible Body - A Kid's App to Learn about the Human Body 1.1.00 Device: iOS Universal Category: Education Price: $2.99, Version: 1.1.00 (iTunes) Description: Wouldn’t it be cool to look inside yourself and see what was going on... | Read more »
Trials Frontier Review
Trials Frontier Review By Carter Dotson on April 18th, 2014 Our Rating: :: A ROUGH LANDINGUniversal App - Designed for iPhone and iPad Trials Frontier finally brings the famed stunt racing franchise to mobile, but how much does its... | Read more »
Evernote Business Notebook by Moleskin I...
Evernote Business Notebook by Moleskin Introduced – Support Available in Evernote for iOS Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »

Price Scanner via MacPrices.net

13-inch 2.4GHz Retina MacBook Pro available f...
Abt has the 13″ 2.4GHz 128GB Retina MacBook Pro available for $1229 including free shipping. Their price is $70 off MSRP. Read more
iMacs on sale for up to $160 off MSRP this we...
Best Buy has iMacs on sale for up to $160 off MSRP for a limited time. Choose free home shipping or free instant local store pickup (if available). Prices are valid for online orders only, in-store... Read more
iPad Airs on sale this weekend for up to $100...
Best Buy has WiFi iPad Airs on sale for $50 off MSRP and WiFi + Cellular iPad Airs on sale for $100 off MSRP on their online store for a limited time, with prices now starting at $449. Choose free... Read more
Apple restocks refurbished Mac minis starting...
The Apple Store has restocked Apple Certified Refurbished Mac minis for up to $150 off the cost of new models. Apple’s one-year warranty is included with each mini, and shipping is free: - 2.5GHz Mac... Read more
Hyundai Brings Apple CarPlay To The 2015 Sona...
Hyundai Motor America has announced it will bring Apple CarPlay functionality to the 2015 Sonata. CarPlay is pitched as a smarter, safer and easier way to use iPhone in the car and gives iPhone users... Read more
Updated iPads Coming Sooner Than We Had Thoug...
MacRumors, cites KGI securities analyst Ming Chi Kuo, well-respected as an Apple product prognisticator, saying that Apple will introduce an upgraded iPad Air and iPad mini in 2014/Q3, meaning the... Read more
Toshiba Unveils New High And Low End Laptop M...
Toshiba has announced new laptop models covering both the high-end and low-end of the notebook computer spectrum. Toshiba 4K Ultra HD Laptop Toshiba’s new Satellite P55t features one of the world’s... Read more
Save up to $270 with Apple refurbished 13-inc...
The Apple Store has Apple Certified Refurbished October 2013 13″ Retina MacBook Pros available starting at $1099, with models up to $270 off MSRP. Apple’s one-year warranty is standard, and shipping... Read more
Apple now offering refurbished iPad mini with...
The Apple Store has Certified Refurbished 2nd generation iPad minis with Retina Displays now available starting at $339. Apple’s one-year warranty is included with each model, and shipping is free.... Read more
Microsoft Blinks – Drops Microsoft Office 365...
Microsoft has dropped the annual subscription fee for Microsoft Office 365 Personal – which is needed in order to create and edit documents in Microsoft Office for iPad. However, Apple’s iOS and OS X... Read more

Jobs Board

*Apple* Automotive Parts Department position...
Apple Automotive is one of the fastest growing dealer…and it shows. Consider making the switch to the Apple Automotive Group today! At Apple Automotive, we Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Retail - Manager - Holyoke - Apple I...
Job Summary Keeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, you’re a master of them all. In the store’s fast-paced, Read more
*Apple* Retail - Manager - Apple (United Sta...
Job SummaryKeeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, you're a master of them all. In the store's fast-paced, dynamic Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.