home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
TUT09NEW.ZIP
/
TUT9.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1995-01-21
|
19KB
|
567 lines
(*****************************************************************************)
(* *)
(* TUT9.PAS - VGA Trainer Program 9 (in Pascal) *)
(* *)
(* "The VGA Trainer Program" is written by Denthor of Asphyxia. However it *)
(* was limited to Pascal only in its first run. All I have done is taken *)
(* his original release, translated it to C++, and touched up a few things. *)
(* I take absolutely no credit for the concepts presented in this code. *)
(* -Christopher G. Mann (Snowman) *)
(* *)
(* Program Notes : This program presents polygons. *)
(* *)
(* Author : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za *)
(* *)
(*****************************************************************************)
{$X+}
USES Crt;
CONST VGA = $A000;
maxpolys = 5;
A : Array [1..maxpolys,1..4,1..3] of integer =
(
((-10,10,0),(-2,-10,0),(0,-10,0),(-5,10,0)),
((10,10,0),(2,-10,0),(0,-10,0),(5,10,0)),
((-2,-10,0),(2,-10,0),(2,-5,0),(-2,-5,0)),
((-6,0,0),(6,0,0),(7,5,0),(-7,5,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0))
); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
{ (X2,Y2,Z2) ... for the 4 points of a poly }
S : Array [1..maxpolys,1..4,1..3] of integer =
(
((-10,-10,0),(10,-10,0),(10,-7,0),(-10,-7,0)),
((-10,10,0),(10,10,0),(10,7,0),(-10,7,0)),
((-10,1,0),(10,1,0),(10,-2,0),(-10,-2,0)),
((-10,-8,0),(-7,-8,0),(-7,0,0),(-10,0,0)),
((10,8,0),(7,8,0),(7,0,0),(10,0,0))
); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
{ (X2,Y2,Z2) ... for the 4 points of a poly }
P : Array [1..maxpolys,1..4,1..3] of integer =
(
((-10,-10,0),(-7,-10,0),(-7,10,0),(-10,10,0)),
((10,-10,0),(7,-10,0),(7,0,0),(10,0,0)),
((-9,-10,0),(9,-10,0),(9,-7,0),(-9,-7,0)),
((-9,-1,0),(9,-1,0),(9,2,0),(-9,2,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0))
); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
{ (X2,Y2,Z2) ... for the 4 points of a poly }
H : Array [1..maxpolys,1..4,1..3] of integer =
(
((-10,-10,0),(-7,-10,0),(-7,10,0),(-10,10,0)),
((10,-10,0),(7,-10,0),(7,10,0),(10,10,0)),
((-9,-1,0),(9,-1,0),(9,2,0),(-9,2,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0))
); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
{ (X2,Y2,Z2) ... for the 4 points of a poly }
Y : Array [1..maxpolys,1..4,1..3] of integer =
(
((-7,-10,0),(0,-3,0),(0,0,0),(-10,-7,0)),
((7,-10,0),(0,-3,0),(0,0,0),(10,-7,0)),
((-2,-3,0),(2,-3,0),(2,10,0),(-2,10,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0))
); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
{ (X2,Y2,Z2) ... for the 4 points of a poly }
X : Array [1..maxpolys,1..4,1..3] of integer =
(
((-7,-10,0),(10,7,0),(7,10,0),(-10,-7,0)),
((7,-10,0),(-10,7,0),(-7,10,0),(10,-7,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0))
); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
{ (X2,Y2,Z2) ... for the 4 points of a poly }
I : Array [1..maxpolys,1..4,1..3] of integer =
(
((-10,-10,0),(10,-10,0),(10,-7,0),(-10,-7,0)),
((-10,10,0),(10,10,0),(10,7,0),(-10,7,0)),
((-2,-9,0),(2,-9,0),(2,9,0),(-2,9,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0)),
((0,0,0),(0,0,0),(0,0,0),(0,0,0))
); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
{ (X2,Y2,Z2) ... for the 4 points of a poly }
Type Point = Record
x,y,z:real; { The data on every point we rotate}
END;
Virtual = Array [1..64000] of byte; { The size of our Virtual Screen }
VirtPtr = ^Virtual; { Pointer to the virtual screen }
VAR Lines : Array [1..maxpolys,1..4] of Point; { The base object rotated }
Translated : Array [1..maxpolys,1..4] of Point; { The rotated object }
Xoff,Yoff,Zoff:Integer; { Used for movement of the object }
lookup : Array [0..360,1..2] of real; { Our sin and cos lookup table }
Virscr : VirtPtr; { Our first Virtual screen }
Vaddr : word; { The segment of our virtual screen}
{──────────────────────────────────────────────────────────────────────────}
Procedure SetMCGA; { This procedure gets you into 320x200x256 mode. }
BEGIN
asm
mov ax,0013h
int 10h
end;
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure SetText; { This procedure returns you to text mode. }
BEGIN
asm
mov ax,0003h
int 10h
end;
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure Cls (Where:word;Col : Byte);
{ This clears the screen to the specified color }
BEGIN
asm
push es
mov cx, 32000;
mov es,[where]
xor di,di
mov al,[col]
mov ah,al
rep stosw
pop es
End;
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure SetUpVirtual;
{ This sets up the memory needed for the virtual screen }
BEGIN
GetMem (VirScr,64000);
vaddr := seg (virscr^);
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure ShutDown;
{ This frees the memory used by the virtual screen }
BEGIN
FreeMem (VirScr,64000);
END;
{──────────────────────────────────────────────────────────────────────────}
procedure flip(source,dest:Word);
{ This copies the entire screen at "source" to destination }
begin
asm
push ds
mov ax, [Dest]
mov es, ax
mov ax, [Source]
mov ds, ax
xor si, si
xor di, di
mov cx, 32000
rep movsw
pop ds
end;
end;
{──────────────────────────────────────────────────────────────────────────}
Procedure Pal(Col,R,G,B : Byte);
{ This sets the Red, Green and Blue values of a certain color }
Begin
asm
mov dx,3c8h
mov al,[col]
out dx,al
inc dx
mov al,[r]
out dx,al
mov al,[g]
out dx,al
mov al,[b]
out dx,al
end;
End;
{──────────────────────────────────────────────────────────────────────────}
Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
{ This draws a horizontal line from x1 to x2 on line y in color col }
asm
mov ax,where
mov es,ax
mov ax,y
mov di,ax
shl ax,8
shl di,6
add di,ax
add di,x1
mov al,col
mov ah,al
mov cx,x2
sub cx,x1
shr cx,1
jnc @start
stosb
@Start :
rep stosw
end;
{──────────────────────────────────────────────────────────────────────────}
Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
{ This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
in color col }
var
x:integer;
mny,mxy:integer;
mnx,mxx,yc:integer;
mul1,div1,
mul2,div2,
mul3,div3,
mul4,div4:integer;
begin
mny:=y1; mxy:=y1;
if y2<mny then mny:=y2;
if y2>mxy then mxy:=y2;
if y3<mny then mny:=y3;
if y3>mxy then mxy:=y3; { Choose the min y mny and max y mxy }
if y4<mny then mny:=y4;
if y4>mxy then mxy:=y4;
if mny<0 then mny:=0;
if mxy>199 then mxy:=199;
if mny>199 then exit;
if mxy<0 then exit; { Verticle range checking }
mul1:=x1-x4; div1:=y1-y4;
mul2:=x2-x1; div2:=y2-y1;
mul3:=x3-x2; div3:=y3-y2;
mul4:=x4-x3; div4:=y4-y3; { Constansts needed for intersection calc }
for yc:=mny to mxy do
begin
mnx:=320;
mxx:=-1;
if (y4>=yc) or (y1>=yc) then
if (y4<=yc) or (y1<=yc) then { Check that yc is between y1 and y4 }
if not(y4=y1) then
begin
x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
if x<mnx then
mnx:=x;
if x>mxx then
mxx:=x; { Set point as start or end of horiz line }
end;
if (y1>=yc) or (y2>=yc) then
if (y1<=yc) or (y2<=yc) then { Check that yc is between y1 and y2 }
if not(y1=y2) then
begin
x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
if x<mnx then
mnx:=x;
if x>mxx then
mxx:=x; { Set point as start or end of horiz line }
end;
if (y2>=yc) or (y3>=yc) then
if (y2<=yc) or (y3<=yc) then { Check that yc is between y2 and y3 }
if not(y2=y3) then
begin
x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
if x<mnx then
mnx:=x;
if x>mxx then
mxx:=x; { Set point as start or end of horiz line }
end;
if (y3>=yc) or (y4>=yc) then
if (y3<=yc) or (y4<=yc) then { Check that yc is between y3 and y4 }
if not(y3=y4) then
begin
x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
if x<mnx then
mnx:=x;
if x>mxx then
mxx:=x; { Set point as start or end of horiz line }
end;
if mnx<0 then
mnx:=0;
if mxx>319 then
mxx:=319; { Range checking on horizontal line }
if mnx<=mxx then
hline (mnx,mxx,yc,color,where); { Draw the horizontal line }
end;
end;
{──────────────────────────────────────────────────────────────────────────}
Function rad (theta : real) : real;
{ This calculates the degrees of an angle }
BEGIN
rad := theta * pi / 180
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure SetUpPoints;
{ This creates the lookup table }
VAR loop1,loop2:integer;
BEGIN
For loop1:=0 to 360 do BEGIN
lookup [loop1,1]:=sin (rad (loop1));
lookup [loop1,2]:=cos (rad (loop1));
END;
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
{ This puts a pixel on the screen by writing directly to memory. }
BEGIN
Asm
mov ax,[where]
mov es,ax
mov bx,[X]
mov dx,[Y]
mov di,bx
mov bx, dx {; bx = dx}
shl dx, 8
shl bx, 6
add dx, bx {; dx = dx + bx (ie y*320)}
add di, dx {; finalise location}
mov al, [Col]
stosb
End;
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure RotatePoints (X,Y,Z:Integer);
{ This rotates object lines by X,Y and Z; then places the result in
TRANSLATED }
VAR loop1,loop2:integer;
temp:point;
BEGIN
For loop1:=1 to maxpolys do BEGIN
For loop2:=1 to 4 do BEGIN
temp.x:=lines[loop1,loop2].x;
temp.y:=lookup[x,2]*lines[loop1,loop2].y - lookup[x,1]*lines[loop1,loop2].z;
temp.z:=lookup[x,1]*lines[loop1,loop2].y + lookup[x,2]*lines[loop1,loop2].z;
translated[loop1,loop2]:=temp;
If y>0 then BEGIN
temp.x:=lookup[y,2]*translated[loop1,loop2].x - lookup[y,1]*translated[loop1,loop2].y;
temp.y:=lookup[y,1]*translated[loop1,loop2].x + lookup[y,2]*translated[loop1,loop2].y;
temp.z:=translated[loop1,loop2].z;
translated[loop1,loop2]:=temp;
END;
If z>0 then BEGIN
temp.x:=lookup[z,2]*translated[loop1,loop2].x + lookup[z,1]*translated[loop1,loop2].z;
temp.y:=translated[loop1,loop2].y;
temp.z:=-lookup[z,1]*translated[loop1,loop2].x + lookup[z,2]*translated[loop1,loop2].z;
translated[loop1,loop2]:=temp;
END;
END;
END;
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure DrawPoints;
{ This draws the translated object to the virtual screen }
VAR loop1:Integer;
nx,ny,nx2,ny2,nx3,ny3,nx4,ny4:integer;
temp:integer;
BEGIN
For loop1:=1 to maxpolys do BEGIN
If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0) and
(translated[loop1,3].z+zoff<0) and (translated[loop1,4].z+zoff<0) then BEGIN
temp:=round (translated[loop1,1].z+zoff);
nx :=round (256*translated[loop1,1].X) div temp+xoff;
ny :=round (256*translated[loop1,1].Y) div temp+yoff;
temp:=round (translated[loop1,2].z+zoff);
nx2:=round (256*translated[loop1,2].X) div temp+xoff;
ny2:=round (256*translated[loop1,2].Y) div temp+yoff;
temp:=round (translated[loop1,3].z+zoff);
nx3:=round (256*translated[loop1,3].X) div temp+xoff;
ny3:=round (256*translated[loop1,3].Y) div temp+yoff;
temp:=round (translated[loop1,4].z+zoff);
nx4:=round (256*translated[loop1,4].X) div temp+xoff;
ny4:=round (256*translated[loop1,4].Y) div temp+yoff;
drawpoly (nx,ny,nx2,ny2,nx3,ny3,nx4,ny4,13,vaddr);
END;
END;
END;
{──────────────────────────────────────────────────────────────────────────}
Procedure MoveAround;
{ This is the main display procedure. Firstly it brings the object towards
the viewer by increasing the Zoff, then passes control to the user }
VAR deg,loop1,loop2:integer;
ch:char;
Procedure Whizz (sub:boolean);
VAR loop1:integer;
BEGIN
For loop1:=-64 to -5 do BEGIN
zoff:=loop1*8;
if sub then xoff:=xoff-7 else xoff:=xoff+7;
RotatePoints (deg,deg,deg);
DrawPoints;
flip (vaddr,vga);
Cls (vaddr,0);
deg:=(deg+5) mod 360;
END;
END;
BEGIN
deg:=0;
ch:=#0;
Yoff:=100;
Xoff:=350;
Cls (vaddr,0);
For loop1:=1 to maxpolys do
For loop2:=1 to 4 do BEGIN
Lines [loop1,loop2].x:=a [loop1,loop2,1];
Lines [loop1,loop2].y:=a [loop1,loop2,2];
Lines [loop1,loop2].z:=a [loop1,loop2,3];
END;
Whizz (TRUE);
For loop1:=1 to maxpolys do
For loop2:=1 to 4 do BEGIN
Lines [loop1,loop2].x:=s [loop1,loop2,1];
Lines [loop1,loop2].y:=s [loop1,loop2,2];
Lines [loop1,loop2].z:=s [loop1,loop2,3];
END;
Whizz (FALSE);
For loop1:=1 to maxpolys do
For loop2:=1 to 4 do BEGIN
Lines [loop1,loop2].x:=p [loop1,loop2,1];
Lines [loop1,loop2].y:=p [loop1,loop2,2];
Lines [loop1,loop2].z:=p [loop1,loop2,3];
END;
Whizz (TRUE);
For loop1:=1 to maxpolys do
For loop2:=1 to 4 do BEGIN
Lines [loop1,loop2].x:=h [loop1,loop2,1];
Lines [loop1,loop2].y:=h [loop1,loop2,2];
Lines [loop1,loop2].z:=h [loop1,loop2,3];
END;
Whizz (FALSE);
For loop1:=1 to maxpolys do
For loop2:=1 to 4 do BEGIN
Lines [loop1,loop2].x:=y [loop1,loop2,1];
Lines [loop1,loop2].y:=y [loop1,loop2,2];
Lines [loop1,loop2].z:=y [loop1,loop2,3];
END;
Whizz (TRUE);
For loop1:=1 to maxpolys do
For loop2:=1 to 4 do BEGIN
Lines [loop1,loop2].x:=x [loop1,loop2,1];
Lines [loop1,loop2].y:=x [loop1,loop2,2];
Lines [loop1,loop2].z:=x [loop1,loop2,3];
END;
Whizz (FALSE);
For loop1:=1 to maxpolys do
For loop2:=1 to 4 do BEGIN
Lines [loop1,loop2].x:=i [loop1,loop2,1];
Lines [loop1,loop2].y:=i [loop1,loop2,2];
Lines [loop1,loop2].z:=i [loop1,loop2,3];
END;
Whizz (TRUE);
For loop1:=1 to maxpolys do
For loop2:=1 to 4 do BEGIN
Lines [loop1,loop2].x:=a [loop1,loop2,1];
Lines [loop1,loop2].y:=a [loop1,loop2,2];
Lines [loop1,loop2].z:=a [loop1,loop2,3];
END;
Whizz (FALSE);
cls (vaddr,0);
cls (vga,0);
Xoff := 160;
Repeat
if keypressed then BEGIN
ch:=upcase (Readkey);
Case ch of 'A' : zoff:=zoff+5;
'Z' : zoff:=zoff-5;
',' : xoff:=xoff-5;
'.' : xoff:=xoff+5;
'S' : yoff:=yoff-5;
'X' : yoff:=yoff+5;
END;
END;
DrawPoints;
flip (vaddr,vga);
cls (vaddr,0);
RotatePoints (deg,deg,deg);
deg:=(deg+5) mod 360;
Until ch=#27;
END;
BEGIN
SetUpVirtual;
clrscr;
Writeln ('Hello there! Varsity has begun once again, so it is once again');
Writeln ('back to the grindstone ;-) ... anyway, this tutorial is, by');
Writeln ('popular demand, on poly-filling, in relation to 3-D solids.');
Writeln;
Writeln ('In this program, the letters of ASPHYXIA will fly past you. As you');
Writeln ('will see, they are solid, not wireframe. After the last letter has');
Writeln ('flown by, a large A will be left in the middle of the screen.');
Writeln;
Writeln ('You will be able to move it around the screen, and you will notice');
Writeln ('that it may have bits only half on the screen, i.e. clipping is');
Writeln ('perfomed. To control it use the following : "A" and "Z" control the Z');
Writeln ('movement, "," and "." control the X movement, and "S" and "X"');
Writeln ('control the Y movement. I have not included rotation control, but');
Writeln ('it should be easy enough to put in yourself ... if you have any');
Writeln ('hassles, leave me mail.');
Writeln;
Writeln ('I hope this is what you wanted...leave me mail for new ideas.');
writeln;
writeln;
Write (' Hit any key to contine ...');
Readkey;
SetMCGA;
SetUpPoints;
MoveAround;
SetText;
ShutDown;
Writeln ('All done. This concludes the ninth sample program in the ASPHYXIA');
Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
Writeln ('Connectix BBS user, and occasionally read RSAProg.');
Writeln ('The numbers are available in the main text. You may also write to me at:');
Writeln (' Grant Smith');
Writeln (' P.O. Box 270');
Writeln (' Kloof');
Writeln (' 3640');
Writeln ('I hope to hear from you soon!');
Writeln; Writeln;
Write ('Hit any key to exit ...');
Readkey;
END.