home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
surfmodl
/
surfm203.arc
/
SURFSRC.ARC
/
SURFMODL.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-02-06
|
20KB
|
539 lines
{$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 }