home *** CD-ROM | disk | FTP | other *** search
- {$I defines.inc }
-
- program SURFMODL;
- uses
- {$IFDEF ANSICRT}
- ansicrt,
- {$ELSE}
- crt,
- {$ENDIF}
- SURFGRAF; { Graphics Routines }
-
- {$IFDEF USE8087}
- type
- REAL = single;
- {$ENDIF}
-
- const
- {$IFDEF USE8087}
- SURFMVSN: STRING[10] = '2.00c 8087';
- {$ELSE}
- Surfmvsn: string[5] = '2.00c'; { version number }
- {$ENDIF}
- Lastupd: string[20] = '06 February 1988'; { date of last update }
-
- { SURFMODL: Surface modeling in three dimensions.
-
- SURFMODL is distributed without any warranty, express or implied.
- In no event shall the authors be liable for any loss of profit or
- any other commercial damage, including but not limited to
- special, incidental, consequential or other damages.
-
- SURFMODL may be freely distributed, or distributed at nominal
- copying/mailing fee, but may not be otherwise charged for.
- It may not be distributed with commercial software without
- express written permission of the principle author:
- Kenneth Van Camp
- P.O. Box 784
- Stroudsburg, PA 18360
-
- HISTORY OF MODIFICATIONS:
- Version 1.0 (February 1987)
- Version 1.1 (March 1987) - Added preliminary support for Borland's
- Turbo Graphix Toolbox, and axes on the plots.
- Version 1.1A (April 1987) - Added Russell Nelson's updates for
- HZ-100 without Toolbox
- Version 1.2 (May 1987) - Added Russell Nelson's updates for
- EGA without Toolbox. Changed NORMALIZ.PAS to NORMALIZ.PRE and
- added a check for the YREVERSE preprocessor definition. Added
- a check in SURFMODL.PRE for the NO_OVLY preprocessor definition,
- so SURFMODL is not overlaid.
- Version 1.3 (November 1987) - Added Ian Murphy's updates to use
- pointers into the heap for all the major arrays, if BIGMEM is
- defined. Fixed thick/thin line problem in hidden line removal,
- per Brad Keister. Allowed Toolbox versions to call windowing
- routines. Fixed Read New File problem in PARAMENU. Fixed dithering
- problem in FILLSURF where Pcolor was not defined. Fixed interpolated
- shading problem in INTRFILL where a surface was allowed to have a
- shade of 0, and Pcolor was not defined. Fixed Axis-drawing bug.
- Added abort capability during plotting. Modified all menu reads
- so hitting Enter keeps old value. Added random shading in Gouraud
- interpolation. Added "status dots" at bottom of graphics screen.
- Speeded up non-Gouraud surface filling by adding special horizontal
- line-draw routine. Added supported for the QuadEGA Prosync graphics
- card, as provided by Rainer Kleinrensing. Added in-line assembly
- code by Klara Schroeder and Jochen Kraemer to support Hercules
- graphics adapter without the Turbo Graphix Toolbox.
- Version 1.31 (December 1987) - Took out in-line assembly code for
- Hercules, and went back to the Toolbox code. This is the ONLY
- difference between versions 1.3 and 1.31!
- Version 2.00 (January 1988) - Converted to Turbo Pascal 4.0 by Kevin
- Lowey. Many minor changes such as having menu ask if you really
- want to quit. Major changes included use of built in preprocessor
- directives (eliminating the need for mprep) and use of Borland
- Graphics Interface (BGI). All SURFMODL graphics primitives are now
- in the unit SURFGRAF.PAS. If non-BGI supported devices are used
- (such as the enclosed DEC VAXmate driver) then the unit SURFBGI is
- included. This unit emulates the BGI functions used by SURFMODL.
-
- The systems supported have changed. Support was dropped (for now)
- for the Sanyo and Zenith Z-100 computers, but full support for the
- BGI systems (see Turbo 4 manual) are supported. Because of
- these changes the SYSTEM value in the .INI files has been changed.
- This program will read version 3 and earlier .INI files, but creates
- version 4 .INI files. In addition to storing the graphics system,
- the graphics mode on that system is now also stored, and you can
- select the mode from the parameters menu.
-
- Benefits: Drawings which used to take 1.5 minutes to draw now take
- one minute. Device independant support for CGA, EGA, VGA, MCGA,
- Hercules Mono, and AT&T computers are provided, and overlays are no
- longer needed.
-
- A minor change to the shading calculation was provided by Steve Enns
- of the University of Saskatchewan. It eliminates the "normalization"
- of the data points done in the shading calculation. The end results
- are the same but some floating point operations have been deleted,
- speeding up the program a bit.
-
- A new option, "F" is now available when a completed image is on the
- screen. Typing "F" will save the current image into a file called
- SURFMODL.PIC. You can play back sequences of these images with the
- new utility program called PLAYBACK.
-
- IFDEF support for the 8087 chip has been added.
-
- }
-
-
- {$ifdef BIGMEM}
- const MAXNODES = 4096; { maximum # of nodes in the entire solid }
- MAXCONNECT = 16384; { maximum # of connections in entire solid }
- MAXSURF = 5461; { maximum # of surfaces in entire solid }
- { (MAXSURF = MAXCONNECT / 3) }
- {$ELSE}
- const MAXNODES = 1024; { maximum # of nodes in the entire solid }
- MAXCONNECT = 4096; { maximum # of connections in entire solid }
- MAXSURF = 1365; { maximum # of surfaces in entire solid }
- { (MAXSURF = MAXCONNECT / 3) }
- {$endif}
- MAXMATL = 30; { maximum # of materials in entire solid }
- MAXPTS = 600; { maximum # of line points (in fillsurf) }
- MAXVAR = 20; { maximum # of numeric inputs on a line }
- MAXLITE = 20; { maximum # of light sources }
-
-
- type points = array[1..MAXPTS] of integer;
- realpts = array[1..MAXPTS] of real;
- text80 = string[80];
- vartype = array[1..MAXVAR] of real;
- surfaces = array[1..MAXSURF] of real;
- vector = array[1..3] of real;
- nodearray= array[1..MAXNODES] of real;
-
- {$ifdef BIGMEM}
- { A note on the BIGMEM definition: Everything included under this
- section is a trick designed to overcome the memory limitations
- imposed by Turbo Pascal version 3.x and below. Since TP limits
- all variable storage to one segment (64K), the following pointer
- definitions overcome this by storing the major SURFMODL arrays
- in the heap space.
- }
- heaparray1 = record Xworld:nodearray;
- end;
- hptr1 = ^heaparray1;
- heaparray2 = record Yworld:nodearray;
- end;
- hptr2 = ^heaparray2;
- heaparray3 = record Zworld:nodearray;
- end;
- hptr3 = ^heaparray3;
-
- heaparray4 = record Xtran:nodearray;
- end;
- hptr4 = ^heaparray4;
- heaparray5 = record Ytran:nodearray;
- end;
- hptr5 = ^heaparray5;
- heaparray6 = record Ztran:nodearray;
- end;
- hptr6 = ^heaparray6;
- heaparray7 = record Connect :array[1..MAXCONNECT] of integer;
- end;
- hptr7 = ^heaparray7;
- heaparray8 = record Nvert : array[1..MAXSURF] of integer;
- end;
- hptr8 = ^heaparray8;
- heaparray9 = record Matl : array[1..MAXSURF] of integer;
- end;
- hptr9 = ^heaparray9;
- heaparray10 = record Shades : nodearray;
- end;
- hptr10 = ^heaparray10;
- heaparray11 = record Surfmin, Surfmax : surfaces;
- end;
- hptr11 = ^heaparray11;
- heaparray12 = record Nshades : array[1..MAXNODES] of integer;
- end;
- hptr12 = ^heaparray12;
- heaparray13 = record Sshade : surfaces;
- end;
- hptr13 = ^heaparray13;
- {$endif}
-
- {$ifdef BIGMEM}
- var ptra : hptr1; { Xworld }
- ptrb : hptr2; { Yworld }
- ptrc : hptr3; { Zworld }
- ptrd : hptr4; { Xtran }
- ptre : hptr5; { Ytran }
- ptrf : hptr6; { Ztran }
- ptrg : hptr7; { Connect }
- ptrh : hptr8; { Nvert }
- ptri : hptr9; { Matl }
- ptrj : hptr10; { Shades }
- ptrk : hptr11; { Surfmin, Surfmax }
- ptrl : hptr12; { Nshades }
- ptrm : hptr13; { Sshade }
- {$ELSE}
- var Xworld, Yworld, Zworld: nodearray;
- { world coordinates of each node }
- Xtran, Ytran, Ztran: nodearray;
- { transformed coordinates of each node }
- Connect: array[1..MAXCONNECT] of integer;
- { surface connectivity data }
- Nvert: array[1..MAXSURF] of integer;
- { # vertices per surface }
- Matl: array[1..MAXSURF] of integer;
- { material number of each surface }
- { NOTE: The Shades, Surfmin, Surfmax, Nshades and Sshade arrays are
- defined in the individual procedures that require them, to save
- global variable space. }
- {$endif}
- R1, R2, R3: array[1..MAXMATL] of real;
- { material reflectivity constants }
- Color: array[1..MAXMATL] of integer;
- { material color number }
- Ambient: array[1..MAXMATL] of real;
- { ambient light intensity for each material }
- Xlite, Ylite, Zlite: array[1..MAXLITE] of real;
- { coords of light sources }
- Intensity: array[1..MAXLITE] of real;
- { light source intensities }
-
- Xeye, Yeye, Zeye: real; { coords of eye }
- Xfocal, Yfocal, Zfocal: real; { coords of focal point }
- Maxvert: integer; { max # vertices per surface }
- Nsurf: integer; { # surfaces }
- Nnodes: integer; { # nodes }
- Nlite: integer; { # light sources }
- Magnify: real; { magnification factor }
- Viewtype: integer; { code for viewing type: }
- { 0=perspective, 1=XY, 2=XZ, 3=YZ }
- Fileread: boolean; { flag first file read }
- Nmatl: integer; { number of materials }
- Nsides: integer; { #sides of surface used (1 or 2)}
- Interpolate: boolean; { flag for Gouraud interpolation }
- Epsilon: real; { Gouraud interpolation range }
- Shadowing: boolean; { flag shadowing option }
- Inifile: text80; { name of INI file }
- XYadjust: real; { factor for screen width }
- Showaxes: integer; { code to show (0) no axes; (1) }
- { axis directions; (2) full axes }
- Xaxislen,Yaxislen,Zaxislen: real; { lengths of axes }
- Axiscolor: integer; { color to draw axes }
- Nwindow: integer; { # graphics windows on screen }
- Xfotran, Yfotran, Zfotran: real; { transformed focal point }
- XYmax: real; { limits of transformed coords }
- Mxc: integer; { suggested value of MAXCONNECT }
- memerr : boolean; { True if a memory error occured }
- { An important function for decoding the Connect array: }
-
-
- function KONNEC (Surf, Vert: integer): integer;
- { Decode the Connect array to yield the connection data: Vertex Vert of
- surface Surf. This function returns an index to the global Xtran, Ytran,
- and Ztran arrays (i.e., a node number) }
-
- begin
- {$ifdef BIGMEM}
- with ptrg^ do
- begin
- {$endif}
- Konnec := Connect[(Surf-1) * Maxvert + Vert];
- {$ifdef BIGMEM}
- end; {with}
- {$endif}
- end; { function KONNEC }
-
- { Procedure include files }
-
- { Graphics Functions }
- {$I colormod.INC} { COLORMOD }
- {$I Dither.INC } { Graphics Dithering functions }
- {$I OPENWIN.INC } { procedure BRIGHT, OPENWIN }
-
- {$I MENUMSG.INC } { procedure MENUMSG }
-
- { Math routines and number input routines}
- {$I ARCCOS.INC } { function ARCCOS }
- {$I MINMAX.INC } { procedure MINMAX }
- {$I GETKEY.INC } { function GETKEY }
- {$I INREAL.INC } { procedure INREAL }
- {$I GETONE.INC } { functions GETONEREAL, GETONEINT }
-
- { File Handling routines }
- {$I READINI.INC } { procedure READINI }
- {$I WRITEINI.INC } { procedure WRITEINI }
- {$I READFILE.INC } { procedure OPENFILE, READFILE }
-
- { startup routines }
- {$I INITIAL.INC } { procedure INITIAL }
- {$I TITLESCR.INC } { procedure TITLESCREEN }
-
- { Menuing Functions }
- {$I LITEMENU.INC } { procedure LITEMENU }
- {$I PARAMENU.INC } { procedure PARAMENU }
- {$I MENU.INC } { procedure MENU }
-
- {$I PERSPECT.INC } { procedure SETORG, PERSPECT }
- {$I NORMALIZ.INC } { procedure SETNORMAL, NORMALIZE }
- {$I CHECKEY.INC } { function CHECKEY }
- {$I CONTINUE.INC } { procedure CONTINUE }
- {$I BORDER.INC } { procedure BORDER }
- {$I DRAWAXES.INC } { procedure DRAWAXES }
- {$I WIREFRAM.INC } { procedure WIREFRAME }
- {$I ONSCREEN.INC } { function ONSCREEN }
- {$I STORLINE.INC } { procedure STORLINE }
- {$I SWAPS.INC } { procedure SWAPINT, SWAPREAL }
- {$I SHELLPTS.INC } { procedure SHELLPTS, SHELLSHADES }
- {$I FILLSURF.INC } { procedure BADSURF, FILLSURF }
- {$I SHELSURF.INC } { procedure SHELSURF }
- {$I SHADING.INC } { procedure NORMAL, POWER,SETSHADE,SHADING,VISIBLE}
- {$I HIDNLINE.INC } { procedure HIDDENLINE }
-
- {$ifndef NOSHADOW}
- {$I INLIMITS.INC } { function INLIMITS (for shadowing) }
- {$I CHEKSURF.INC } { function CHEKSURF (for shadowing) }
- {$I SHADOWS.INC } { procedure SHADOWS (for shadowing) }
- {$endif}
-
- {$I SURFACE.INC } { procedure SURFACE }
- {$I STORSHAD.INC } { procedure STORSHADES }
- {$I INTRFILL.INC } { procedure INTRFILL }
- {$I GOURAUD.INC } { procedure GOURAUD }
-
- { Local variables for main procedure }
- var Cmmd: integer; { user command }
- Imemavail: longint; { initial memory available }
-
- begin { SURFMODL main program }
- {$IFDEF DEBUG}
- CheckBreak := true; {enable CONTROL-C checking}
- {$ENDIF}
-
- if paramcount <> 2 then {only display if not in "engine" mode}
- titlescreen;
-
- {$ifdef BIGMEM}
- Imemavail := Maxavail;
-
- { Calculate what MAXCONNECT, MAXNODES & MAXSURF could have been if
- storage were completely used. The formula is based on the following:
-
- Array Dim | #Real Arrays | #Int Arrays | Total # Bytes
- ===========|==============|=============|===============
- MAXNODES | 7 | 1 | 44 * MAXNODES
- MAXSURF | 3 | 2 | 22 * MAXSURF
- MAXCONNECT | 0 | 1 | 2 * MAXCONNECT
-
- The rightmost column is calculated by the fact that a real takes up
- 6 bytes and an integer takes 2 bytes. Then, using the recommended
- relationships between the three constants:
- MAXNODES = MAXCONNECT / 4
- MAXSURF = MAXCONNECT / 3
- we can calculate Mxc, which is the "ideal" value for MAXCONNECT based
- on current memory available. The 10000 is to reserve room for the
- graphics device driver.
-
- 44*(Mxc/4) + 22*(Mxc/3) + 2*Mxc = MaxAvail - 10000
- Solving, we get:
-
- Mxc = (MaxAvail - 10000) * 0.0492
-
- which is the calculated value for the ideal MAXCONNECT. Alternatively,
- we can say that the currently dimensioned SURFMODL requires
- MAXCONNECT / 0.0674 bytes of free memory after initially
- loading SURFMODL in order to run successfully.
-
- To be safe, I'll use the value 0.0491
-
- }
-
- Mxc := trunc((maxavail - 10000) * 0.0491);
-
- if (Mxc > 32767.0) then
- Mxc := 32767;
-
-
- {$ifdef MEMRPT}
- clrscr;
- writeln ('Initial memory available is ',(MaxAvail):7, ' bytes.');
- writeln ('Based on this:');
- if (Mxc < MAXCONNECT) then
- writeln ('MAXCONNECT must be lowered to ',Mxc)
- else
- writeln ('MAXCONNECT may be raised to ',Mxc);
-
- if (Mxc div 4 < MAXNODES) then
- writeln ('MAXNODES must be lowered to ',Mxc div 4)
- else
- writeln ('MAXNODES may be raised to ', Mxc div 4);
-
- if (Mxc div 3 < MAXSURF) then
- writeln ('MAXSURF must be lowered to ', Mxc div 3)
- else
- writeln ('MAXSURF may be raised to ', Mxc div 3);
-
- writeln;
- write ('Initial calculations indicate you ');
- if maxconnect/0.0491 > MaxAvail - 10000 then
- write ('need')
- else
- write('have');
-
- writeln (' ',abs(MAXCONNECT/0.0491 - (Maxavail - 10000)):7:0,
- ' bytes extra mem.');
- writeln;
- {$endif}
- memerr := false;
-
- new (ptra);
- if ptra = nil then
- memerr := true;
-
- new (ptrb);
- if ptrb = nil then
- memerr := true;
-
- new (ptrc);
- if ptrc = nil then
- memerr := true;
-
- new (ptrd);
- if ptrd = nil then
- memerr := true;
-
- new (ptre);
- if ptre = nil then
- memerr := true;
-
- new (ptrf);
- if ptrf = nil then
- memerr := true;
-
- new (ptrg);
- if ptrg = nil then
- memerr := true;
-
- new (ptrh);
- if ptrh = nil then
- memerr := true;
-
- new (ptri);
- if ptri = nil then
- memerr := true;
-
- new (ptrj);
- if ptrj = nil then
- memerr := true;
-
- new (ptrk);
- if ptrk = nil then
- memerr := true;
-
- new (ptrl);
- if ptrl = nil then
- memerr := true;
-
- new (ptrm);
- if ptrm = nil then
- memerr := true;
-
-
- {$ifdef MEMRPT}
- writeln ('After heap allocations:');
- writeln ('Extra memory available is ',(Maxavail-10000):7, ' bytes.');
- writeln ('Actual memory usage was a factor of ',
- ((Imemavail - (Maxavail - 10000)) / (MAXCONNECT / 0.0491)):5:2,
- ' larger than calculated.');
- writeln;
- writeln ('Press any key to continue');
- repeat until keypressed;
- while keypressed do
- if readkey = ' ' then; {flush keyboard}
-
- {$endif} {MEMRPT}
-
- if memerr then begin
- writeln ('You have run out of memory, you must do one of:');
- writeln (' -- Increase your available memory');
- writeln (' -- Decrease the array dimensions in SURFMODL and recompile');
- writeln (' -- Run the smaller version of SURFMODL.');
- writeln;
- halt(1);
- end;
- {$endif} {BIGMEM}
-
- {Initialize variables}
- Cmmd := 1;
- initial;
-
- if paramcount < 2 then begin
- repeat
- Cmmd := 2;
- menu (Cmmd);
- if (Cmmd > 1) and (Cmmd < 5) and (not Fileread) then begin
- writeln ('Please proceed to parameter menu to read data file');
- write ('Press any key to continue...');
- while (not keypressed) do;
- Cmmd := 1;
- end;
-
- case Cmmd of
- 1: paramenu;
- 2: wireframe;
- 3: hiddenline;
- 4: if (Interpolate) then
- gouraud
- else
- surface;
- end;
- until (Cmmd = 0) or (paramcount = 3);
- end
- else if paramstr(2) = '2' then
- wireframe
- else if paramstr(2) = '3' then
- hiddenline
- else if paramstr(2) = '4' then
- if interpolate then
- gouraud
- else
- surface
- else begin
- clrscr;
- writeln ('Option "',paramstr(2),'" is not recognised.');
- writeln ('Use a number between 2 and 4');
- writeln ('Program halted');
- halt(1);
- end;
-
- window (1,1,80,25);
- clrscr;
- {$ifdef MEMRPT}
- writeln;
- writeln ('The smallest amount of free memory during your run was ',
- (Maxavail):7, ' bytes.');
- {$endif}
- end. { program SURFMODL }