home *** CD-ROM | disk | FTP | other *** search
- Program ThreeD;
-
- { This program displays and rotates three-dimensional images on }
- { the IBM PC's graphics display. The program used three data files }
- { on the default drive. The data files have the extension '.3D'. }
- { }
- { The program uses two External Procedures: Line.inv & Cls.inv. }
- { These procedures must be on the default drive when compiling. }
- { }
- { Author - Jay Mallin }
- { PC Tech Journal, May 1984, pp. 44-48. }
- { Typed & Translated into Pascal by Jeff Firestone. }
-
-
- Type
- Strng = String[200];
-
- Var
- Nam : Strng;
- f : text;
- exit : boolean;
- i, j, Length, LineCount, pnt, pta, ptb, temp1, temp2 : integer;
-
- max, xmax, ymax, zmax, xmin, ymin, zmin : real;
- Center, Xcenter, Ycenter, Zcenter : Real;
- factor, temp, rcnt : real;
-
- Rot : Array [0..2, 0..2] of real;
- Lines : Array [0..149, 0..1] of integer;
- XYZ : Array [0..149, 0..2] of real;
- XY : Array [0..149, 0..1] of integer;
-
-
- Procedure Line(x1,y1,x2,y2,color:integer);
- External 'line.inv';
-
- Procedure Cls; External 'Cls.inv';
-
-
- Procedure InitPrgm; { Initialize the arrays & global variables }
- Begin
- FillChar(Rot, SizeOf(Rot), 0);
- FillChar(Lines, SizeOf(Lines), 0);
- FillChar(XYZ, SizeOf(XYZ), 0);
- FillChar(XY, SizeOf(XY), 0);
- max:= 0; Center:= 0; Rcnt:= 0;
- ClrScr;
- end;
-
-
- { Array XYZ contains the three coordinates for each data point, and }
- { Array XY contains the x, y coordinates for drawing on the display. }
-
- Procedure ReadFile; { Read in the data from the '.3D' file }
- begin
- assign(f, 'pyramid.3d');
- reset(f);
- readln(f, length);
- for i:= 0 to length-1 do
- read(f, xyz[i,0], xyz[i,1], xyz[i,2]);
-
- { Now get the pairs of points to connect with lines and store in the }
- { array LINES. }
-
- LineCount:= -1;
- while (LineCount < 149) and not(EOF(f)) do
- begin
- LineCount:= LineCount + 1;
- read(f, temp1, temp2);
- Lines[LineCount, 0]:= Temp1-1;
- Lines[LineCount, 1]:= Temp2-1;
- end;
- end;
-
-
- { The figure is centered, then proportioned to fit on the screen. }
- { The first step is to find the largest and smallest value of x,y & z. }
-
- Procedure SetupVars; { Initialize our Variables }
- begin
- xmax:= xyz[0,0]; ymax:= xyz[0,1]; zmax:= xyz[0,2];
- xmin:= xmax; ymin:= ymax; zmin:= zmax;
- for i:= 1 to length do
- begin
- if xyz[i,0] > xmax then xmax:= xyz[i,0];
- if xyz[i,1] > ymax then ymax:= xyz[i,1];
- if xyz[i,2] > zmax then zmax:= xyz[i,2];
- if xyz[i,0] < xmin then xmin:= xyz[i,0];
- if xyz[i,1] < ymin then ymin:= xyz[i,1];
- if xyz[i,2] < zmin then zmin:= xyz[i,2];
- end;
-
- { A center is found between the greatest and smallest values for each }
- { of the three axis, and all the coordinate values are adjusted to move }
- { those centers to be at the center. }
-
- Xcenter:= (xmax + xmin) / 2;
- Ycenter:= (ymax + ymin) / 2;
- Zcenter:= (zmax + zmin) / 2;
- for i:= 0 to length do
- begin
- xyz[i,0]:= xyz[i,0] - Xcenter;
- xyz[i,1]:= xyz[i,1] - Ycenter;
- xyz[i,2]:= xyz[i,2] - Zcenter;
- end;
-
- { The largest value of all the newly adjusted coordinates is found, }
- { and that is used to scale the picture to stay within the screen. }
-
- max:= Xmax - Xcenter;
- writeln(max,' ',xmax,' ',ymax,' ',zmax);
- writeln(xcenter,' ',ycenter,' ',zcenter);
- if max < Ymax - Ycenter then max:= Ymax - Ycenter;
- if max < Zmax - Zcenter then max:= Zmax - Zcenter;
- Factor:= 90 / Max;
- for i:= 0 to length do
- begin
- xyz[i,0]:= factor * xyz[i,0];
- xyz[i,1]:= factor * xyz[i,1];
- xyz[i,2]:= factor * xyz[i,2];
- end;
- end;
-
-
- { Now we begin the section of Procedure which are run each time we }
- { wish to rotate the object in XYZ. }
-
- Procedure DrawIt;
-
- { First build the 2D data based upon the 3D data. }
-
- begin
- for pnt:= 0 to length do
- begin
- xy[pnt, 1]:= round(91 - (5*xyz[pnt,2]/12));
- xy[pnt, 0]:= round(320 + xyz[pnt, 1]);
- end;
-
- { Clear the old screen and draw the 2D data by connecting the points. }
-
- cls;
- for i:= 0 to LineCount do
- begin
- pta:= Lines[i,0];
- ptb:= Lines[i,1];
- Line(xy[pta,0],xy[pta,1],xy[ptb,0],xy[ptb,1],1);
- end;
- end;
-
-
- { This procedure is not currently being used. }
- Procedure GetCoords;
- begin
- gotoXY(1,24);
- writeln('Enter next rotation in degrees for each axis, or enter 361 to exit.');
- Line(0,199,620,199,1);
- gotoXY(1,25);
- write('X: '); read(rot[0,0]);
- if rot[0,0] = 361 then exit:= true;
- gotoXY(14,25);
- write('Y: '); read(rot[1,0]);
- if rot[1,0] = 361 then exit:= true;
- gotoXY(27,25);
- write('Z: '); read(rot[2,0]);
- if rot[2,0] = 361 then exit:= true;
- end; {Procedure GetCoords}
-
-
- { Convert the coordinates and rotates them about the x, y & Z axis. }
-
- Procedure CalcCoords;
- begin
-
- { Convert the input to degrees; find SIN and COS of each. All the }
- { results are stored in Rot. }
-
- for i:= 0 to 2 do
- begin
- rot[i,0]:= pi*(round(rot[i,0]) mod 360)/180;
- rot[i,1]:= sin(rot[i,0]);
- rot[i,2]:= cos(rot[i,0]);
- end;
-
- { Compute the new coordinates in XYZ to rotate around the Z axis. }
-
- if rot[2,2] <> 1 then
- for pnt:= 0 to length do
- begin
- temp:= xyz[pnt,0];
- xyz[pnt,0]:= (rot[2,2] * xyz[pnt,0]) - (rot[2,1] * xyz[pnt,1]);
- xyz[pnt,1]:= (rot[2,1] * temp) + (rot[2,2] * xyz[pnt,1]);
- end;
-
- { Rotate around the Y axis if the rotation is not 0. }
-
- if rot[1,2] <> 1 then
- for pnt:= 0 to length do
- begin
- temp:= xyz[pnt,0];
- xyz[pnt,0]:= (temp * rot[1,2]) + (xyz[pnt,2] * rot[1,1]);
- xyz[pnt,2]:= (xyz[pnt,2] * rot[1,2]) - (temp * rot[1,1]);
- end;
-
- { Rotate around the X axis. }
-
- if rot[0,2] <> 1 then
- for pnt:= 0 to length do
- begin
- temp:= xyz[pnt,1];
- xyz[pnt,1]:= (temp * rot[0,2]) - (xyz[pnt,2] * rot[0,1]);
- xyz[pnt,2]:= (temp * rot[0,1]) + (xyz[pnt,2] * rot[0,2]);
- end;
- end; {Procedure CalcCoords}
-
-
- { Here we caculate the stepping of the rotation. This sends the figure }
- { spinning in space. }
-
- Procedure ProcessCoords;
- begin
- exit:= false;
- while not(exit) do
- begin
- DrawIt;
- { GetCoords; }
- rot[0,0]:= rot[0,0]+3; { X axis rotation }
- rot[1,0]:= rot[1,0]+1; { Y axis rotation }
- rot[2,0]:= rot[2,0]+6; { Z axis rotation }
- rcnt:=rcnt+1;if rcnt>40 then exit:= true;
- CalcCoords;
-
- for i:= 0 to length do
- begin
- xyz[i,0]:= 0.98 * xyz[i,0];
- xyz[i,1]:= 0.94 * xyz[i,1];
- xyz[i,2]:= 0.9 * xyz[i,2];
- end;
- end; {while not(exit)}
- end; {Procedure ProcessCoords}
-
-
- begin
- InitPrgm;
- ReadFile;
- SetupVars;
- HiRes; HiResColor(7);
- ProcessCoords;
- TextMode;
- end.