home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Virtual Reality Homebrewer's Handbook
/
vr.iso
/
3dgraph
/
pascal
/
chap2_11.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-03-19
|
9KB
|
285 lines
program chap2_11;
uses graph, crt;
const xoffset=640/2;
yoffset=480/2;
xscale=1;
yscale=-1;
persp=500;
type point=record
xw, yw, zw : real;
xs, ys, zs : integer;
end;
matrix_4x4=array[1..4,1..4] of real;
var vertex : array[1..18] of point;
faces : array[1..13,1..6] of word; {First entry is face colour}
face_list : array[1..13,1..2] of integer; {First entry is face, second is depth}
polygon : array[1..15] of PointType;
f : text;
c, c2 : integer;
ch : char;
w2v, temp, temp2 : matrix_4x4;
procedure Initialise_Graphics;
var Graphdriver, Graphmode, Errorcode : integer;
begin
Graphdriver:=Detect;
InitGraph(Graphdriver, Graphmode,'');
Errorcode:=graphresult;
if Errorcode<>grOk then
begin
writeln('Graphics Error: ',GraphErrorMsg(ErrorCode));
writeln('Program Aborted');
Halt(1);
end;
SetLineStyle(0,0,3);
end;
procedure translate(x,y,z : real; var m : matrix_4x4);
begin
m[1,1]:=1; m[2,1]:=0; m[3,1]:=0; m[4,1]:=0;
m[1,2]:=0; m[2,2]:=1; m[3,2]:=0; m[4,2]:=0;
m[1,3]:=0; m[2,3]:=0; m[3,3]:=1; m[4,3]:=0;
m[1,4]:=x; m[2,4]:=y; m[3,4]:=z; m[4,4]:=1;
end;
procedure rotate_x(t : real; var m : matrix_4x4);
begin
m[1,1]:=1; m[2,1]:=0; m[3,1]:=0; m[4,1]:=0;
m[1,2]:=0; m[2,2]:=cos(t); m[3,2]:=sin(t); m[4,2]:=0;
m[1,3]:=0; m[2,3]:=-sin(t); m[3,3]:=cos(t); m[4,3]:=0;
m[1,4]:=0; m[2,4]:=0; m[3,4]:=0; m[4,4]:=1;
end;
procedure rotate_y(t : real; var m : matrix_4x4);
begin
m[1,1]:=cos(t); m[2,1]:=0; m[3,1]:=-sin(t); m[4,1]:=0;
m[1,2]:=0; m[2,2]:=1; m[3,2]:=0; m[4,2]:=0;
m[1,3]:=sin(t); m[2,3]:=0; m[3,3]:=cos(t); m[4,3]:=0;
m[1,4]:=0; m[2,4]:=0; m[3,4]:=0; m[4,4]:=1;
end;
procedure rotate_z(t : real; var m : matrix_4x4);
begin
m[1,1]:=cos(t); m[2,1]:=sin(t); m[3,1]:=0; m[4,1]:=0;
m[1,2]:=-sin(t); m[2,2]:=cos(t); m[3,2]:=0; m[4,2]:=0;
m[1,3]:=0; m[2,3]:=0; m[3,3]:=1; m[4,3]:=0;
m[1,4]:=0; m[2,4]:=0; m[3,4]:=0; m[4,4]:=1;
end;
procedure mult_4x4(a,b : matrix_4x4; var m : matrix_4x4);
var c : integer;
begin
for c:=1 to 4 do
m[c,1]:=a[1,1]*b[c,1]+a[2,1]*b[c,2]+a[3,1]*b[c,3]+a[4,1]*b[c,4];
for c:=1 to 4 do
m[c,2]:=a[1,2]*b[c,1]+a[2,2]*b[c,2]+a[3,2]*b[c,3]+a[4,2]*b[c,4];
for c:=1 to 4 do
m[c,3]:=a[1,3]*b[c,1]+a[2,3]*b[c,2]+a[3,3]*b[c,3]+a[4,3]*b[c,4];
for c:=1 to 4 do
m[c,4]:=a[1,4]*b[c,1]+a[2,4]*b[c,2]+a[3,4]*b[c,3]+a[4,4]*b[c,4];
end;
procedure draw_face(face: integer);
var x1,y1,z1,x2,y2,z2 : integer;
count, c : integer;
begin
count:=0;
{Copy vertices to polygon}
for c:=2 to 6 do
begin
if faces[face,c]<>0 then
begin
polygon[c-1].x:=vertex[faces[face,c]].xs;
polygon[c-1].y:=vertex[faces[face,c]].ys;
inc(count);
end;
end;
{Draw polygon}
SetFillStyle(1,(faces[face,1]));
FillPoly(count,polygon);
end;
procedure draw_picture;
var c, c2, max_z : integer;
any_swapped : boolean;
begin
{Put faces into a list and find each's furthest distance}
for c:=1 to 13 do
begin
face_list[c,1]:=c;
max_z:=-9999;
for c2:=2 to 6 do
begin
if faces[c,c2]<>0 then
if vertex[faces[c,c2]].zs>max_z then max_z:=vertex[faces[c,c2]].zs;
end;
face_list[c,2]:=max_z;
end;
{Bubble sort into decreasing depth order}
repeat
any_swapped:=false;
for c:=1 to 12 do
begin
if face_list[c+1,2]>face_list[c,2] then
begin
c2:=face_list[c+1,2];
face_list[c+1,2]:=face_list[c,2];
face_list[c,2]:=c2;
c2:=face_list[c+1,1];
face_list[c+1,1]:=face_list[c,1];
face_list[c,1]:=c2;
any_swapped:=true;
end;
end;
until any_swapped=false;
ClearDevice;
for c:=1 to 13 do
draw_face(face_list[c,1]);
end;
procedure transform(m : matrix_4x4);
var c : integer;
begin
for c:=1 to 18 do
begin
vertex[c].zs:=round(vertex[c].xw*m[3,1]+vertex[c].yw*m[3,2]+vertex[c].zw*m[3,3]+m[3,4]);
vertex[c].xs:=round(((vertex[c].xw*m[1,1]+vertex[c].yw*m[1,2]+vertex[c].zw*m[1,3]+m[1,4])
*(persp/vertex[c].zs)*xscale)+xoffset);
vertex[c].ys:=round(((vertex[c].xw*m[2,1]+vertex[c].yw*m[2,2]+vertex[c].zw*m[2,3]+m[2,4])
*(persp/vertex[c].zs)*yscale)+yoffset);
end;
end;
begin
clrscr;
writeln; writeln; writeln; writeln;
writeln('This is from Chapter 2 Step 11 of the Virtual Reality Homebrewer''s Handbook');
writeln('and shows how to move around a virtual shape drawn with depth sorted, ');
writeln('flat shaded faces.');
writeln;
writeln;
writeln('Controls: 8/2 - move forwards/back');
writeln(' 4/6 - move left/back');
writeln(' 7/1 - move up/down');
writeln(' o/l - pitch up/down');
writeln(' </> - yaw left/right');
writeln(' n/m - roll left/right');
writeln;
writeln(' q - quit');
writeln;
writeln(' Press any key to continue');
ch:=ReadKey;
{Read in vertices}
assign(f,'points.dat');
reset(f);
for c:=1 to 18 do
begin
readln(f,vertex[c].xw,vertex[c].yw,vertex[c].zw);
end;
close(f);
{Read in faces}
assign(f,'faces.dat');
reset(f);
for c:=1 to 13 do
for c2:=1 to 6 do
read(f,faces[c,c2]);
close(f);
{Move to z=500}
for c:=1 to 18 do
begin
vertex[c].zw:=vertex[c].zw+500;
end;
Initialise_Graphics;
translate(-500,-400,0,w2v);
Rotate_Y(pi/5,temp);
mult_4x4(w2v,temp,w2v);
Rotate_X(-pi/6,temp);
mult_4x4(w2v,temp,w2v);
transform(w2v);
draw_picture;
repeat
ch:=Readkey;
case ch of
'8': begin
translate(0,0,-10,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'2': begin
translate(0,0,10,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'4': begin
translate(10,0,0,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'6': begin
translate(-10,0,0,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'1': begin
translate(0,10,0,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'7': begin
translate(0,-10,0,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
',': begin
rotate_y(PI/180,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'.': begin
rotate_y(-PI/180,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'm': begin
rotate_z(PI/180,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'n': begin
rotate_z(-PI/180,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'o': begin
rotate_x(PI/180,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
'l': begin
rotate_x(-PI/180,temp);
mult_4x4(w2v,temp,temp2);
w2v:=temp2;
end;
end;
transform(w2v);
draw_picture;
until ch='q';
CloseGraph;
end.