home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
116
/
3DEMO.ZIP
/
3DEMO2.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-07-19
|
19KB
|
747 lines
Program demo2;
Uses Graph,Crt,BGIDrv;
const
MaxPoints = 40;
MaxLines = 70;
pi = 3.1415926535897932385;
ScreenWidth = 1000;
HalfWidth = screenWidth / 2;
type
Line3d = record
FromP, ToP : integer;
end;
screenPoints = record
sX,sY : integer;
end;
axisType = (x,y,z);
point3d = record
x, y, z : real;
end;
const
zeroPoint : point3d = (x:0.0; y:0.0; z:0.0);
type
ctmPtr = ^ctm;
ctm = object
r11, r12, r13 : real; { change to single if numeric processor is present }
r21, r22, r23 : real;
r31, r32, r33 : real;
tx, ty, tz : real;
constructor SetUnit; { set to the unit (I) matrix }
constructor Copy(var src : ctm); { construct from another }
procedure save(var dest : ctm);
procedure translate(Dx, Dy, Dz : real); { used to move .. }
procedure translateX(dx : real);
procedure translateY(dy : real);
procedure translateZ(dz : real); { translate in one axis only }
{use these routines for single axis translations, they are faster!}
procedure rotateX(t : real);
procedure rotateY(t : real);
procedure rotateZ(t : real);
procedure scale(Sx, Sy, Sz : real);
procedure scaleX(sx : real);
procedure scaleY(sy : real);
procedure scaleZ(sz : real);
procedure transform(var t: point3d; p : point3d);
procedure multiply(var c : ctm); {multiply from right self * c}
procedure Multiply_2(var a, b : ctm); { mult a*b --> ctm ? }
end;
type
f_real = file of real;
BaseObjectPtr = ^BaseObject;
BaseObject = object
MyCtm : Ctm; { This CTM applied to the object gives the }
{ objects Position after transformations }
Name : String; { Identifies the object }
myColor : word; { Main color for the object }
Location : point3d; { Central of gravity in real space }
scrPntUpdt : boolean; { True if screen points updated }
constructor open(myName : string; color : word);
destructor CloseMe; virtual;
procedure show; virtual;
procedure hide; virtual;
procedure paint; virtual; {in specified color}
procedure updateScreenPoints; virtual; {transform object 3D -> 2D}
procedure move(axis : axisType; by : real); virtual;
procedure translate(dx, dy, dz : integer); virtual;
{multy dimentional move in 1 call}
procedure scale(axis : axisType; factor : real); virtual;
procedure allScale(sx, sy, sz : real); virtual;
{multy dimentional scale in 1 call}
procedure rotate(axis : axisType; deg : real); virtual;
procedure goto3dPos(x, y, z : real); virtual; {translate to absolute place}
procedure setToOrigin; virtual;
{translate to 0,0,0, update points, and set myCtm to unit}
procedure calcLocation; virtual; {set Location to central gravity}
procedure deleteTransform; virtual; {set MyCtm to unit}
function load : word; virtual; {from disk}
function save : word; virtual; {to disk}
procedure writeMe(var elementFile : f_real); virtual; {to disk .. without opening file..}
procedure readMe(var elementFile : f_real); virtual;
end;
Obj3dPtr = ^Obj3d;
Obj3d = object(BaseObject)
Points : array[1..MaxPoints] of point3d;
Lines : array[1..MaxLines] of Line3d;
scrPoints : array[1..MaxPoints] of screenPoints;
NumOfLines : integer;
NumOfPoints : integer;
ReverseRot : Ctm; { Saves only the reverse rotations }
unReverseRot: Ctm; { reverse of the above}
constructor open(myName : string; ref : point3d; color : word);
destructor CloseMe; virtual;
procedure paint; virtual; {in specified color}
procedure updateScreenPoints; virtual; {transform object 3D -> 2D}
procedure calcLocation; virtual; {set Location to central gravity}
procedure setToOrigin; virtual;
procedure writeMe(var elementFile : f_real); virtual;
procedure readMe(var elementFile : f_real); virtual;
end;
var
OutString,OutString2 : String;
MaxX, MaxY : word; { In pixels for graphics screen }
MaxColor : word;
GraphDriver : integer;
GraphMode : integer;
var OldExitProc : Pointer;
constructor ctm.SetUnit;
begin
r11 := 1; r12 := 0; r13 := 0;
r21 := 0; r22 := 1; r23 := 0;
r31 := 0; r32 := 0; r33 := 1;
Tx := 0; Ty := 0; Tz := 0;
end;
constructor ctm.copy;
begin
r11 := Src.r11;
r12 := Src.r12;
r13 := Src.r13;
r21 := Src.r21;
r22 := Src.r22;
r23 := Src.r23;
r31 := Src.r31;
r32 := Src.r32;
r33 := Src.r33;
tx := Src.tx;
ty := Src.ty;
tz := Src.tz;
end;
procedure ctm.save;
begin
dest := self;
end;
procedure ctm.translate;
begin
Tx := Tx + Dx;
Ty := Ty + Dy;
Tz := Tz + Dz;
end;
procedure ctm.translateX;
begin
tx := tx+dx;
end;
procedure ctm.translateY;
begin
ty := ty+dy;
end;
procedure ctm.translateZ;
begin
tz := tz+dz;
end;
procedure ctm.scale;
begin
r11 := r11*Sx; r12 := r12*Sy; r13 := r13*Sz;
r21 := r21*Sx; r22 := r22*Sy; r23 := r23*Sz;
r31 := r31*Sx; r32 := r32*Sy; r33 := r33*Sz;
tx := tx*Sx; ty := ty*Sy; tz := tz*Sz
end;
procedure ctm.scaleZ;
begin
r13 := r13*Sz;
r23 := r23*Sz;
r33 := r33*Sz;
tz := tz*Sz;
end;
procedure ctm.scaleY;
begin
r12 := r12*Sy;
r22 := r22*Sy;
r32 := r32*Sy;
ty := ty*Sy;
end;
procedure ctm.scaleX;
begin
r11 := r11*Sx;
r21 := r21*Sx;
r31 := r31*Sx;
tx := tx*Sx;
end;
procedure ctm.rotateZ;
var
cost, sint : real;
tmp : real;
begin
cost := cos((pi/180) * t);
sint := sin((pi/180) * t);
tmp := r11*cost - r12*sint;
r12 := r11*sint + r12*cost;
r11 := tmp;
tmp := r21*cost - r22*sint;
r22 := r21*sint + r22*cost;
r21 := tmp;
tmp := r31*cost - r32*sint;
r32 := r31*sint + r32*cost;
r31 := tmp;
tmp := tx *cost - ty *sint;
ty := tx *sint + ty *cost;
tx := tmp;
end;
procedure ctm.rotateX;
var
cost, sint : real;
tmp : real;
begin
cost := cos((pi/180) * t);
sint := sin((pi/180) * t);
tmp := r12*cost - r13*sint;
r13 := r12*sint + r13*cost;
r12 := tmp;
tmp := r22*cost - r23*sint;
r23 := r22*sint + r23*cost;
r22 := tmp;
tmp := r32*cost - r33*sint;
r33 := r32*sint + r33*cost;
r32 := tmp;
tmp := ty *cost - tz *sint;
tz := ty *sint + tz *cost;
ty := tmp;
end;
procedure ctm.rotateY;
var
cost, sint : real;
tmp : real;
begin
cost := cos((pi/180) * t);
sint := sin((pi/180) * t);
tmp := r11*cost + r13*sint;
r13 := r13*cost - r11*sint;
r11 := tmp;
tmp := r21*cost + r23*sint;
r23 := r23*cost - r21*sint;
r21 := tmp;
tmp := r31*cost + r33*sint;
r33 := r33*cost - r31*sint;
r31 := tmp;
tmp := tx *cost + tz *sint;
tz := tz *cost - tx *sint;
tx := tmp;
end;
procedure ctm.transform;
begin
t.x := p.x*r11 + p.y*r21 + p.z*r31 + tx;
t.y := p.x*r12 + p.y*r22 + p.z*r32 + ty;
t.z := p.x*r13 + p.y*r23 + p.z*r33 + tz;
end;
procedure ctm.multiply;
var
t : ctm;
begin
t.r11 := r11*c.r11+r12*c.r21+r13*c.r31;
t.r21 := r21*c.r11+r22*c.r21+r23*c.r31;
t.r31 := r31*c.r11+r32*c.r21+r33*c.r31;
t.tx := tx *c.r11+ty *c.r21+tz *c.r31+c.tx;
t.r12 := r11*c.r12+r12*c.r22+r13*c.r32;
t.r22 := r21*c.r12+r22*c.r22+r23*c.r32;
t.r32 := r31*c.r12+r32*c.r22+r33*c.r32;
t.ty := tx *c.r12+ty *c.r22+tz *c.r32+c.ty;
t.r13 := r11*c.r13+r12*c.r23+r13*c.r33;
t.r23 := r21*c.r13+r22*c.r23+r23*c.r33;
t.r33 := r31*c.r13+r32*c.r23+r33*c.r33;
t.tz := tx *c.r13+ty *c.r23+tz *c.r33+c.tz;
copy(t);
end;
procedure ctm.multiply_2;
begin
r11 := a.r11*b.r11+a.r12*b.r21+a.r13*b.r31;
r21 := a.r21*b.r11+a.r22*b.r21+a.r23*b.r31;
r31 := a.r31*b.r11+a.r32*b.r21+a.r33*b.r31;
tx := a.tx *b.r11+a.ty *b.r21+a.tz *b.r31+b.tx;
r12 := a.r11*b.r12+a.r12*b.r22+a.r13*b.r32;
r22 := a.r21*b.r12+a.r22*b.r22+a.r23*b.r32;
r32 := a.r31*b.r12+a.r32*b.r22+a.r33*b.r32;
ty := a.tx *b.r12+a.ty *b.r22+a.tz *b.r32+b.ty;
r13 := a.r11*b.r13+a.r12*b.r23+a.r13*b.r33;
r23 := a.r21*b.r13+a.r22*b.r23+a.r23*b.r33;
r33 := a.r31*b.r13+a.r32*b.r23+a.r33*b.r33;
tz := a.tx *b.r13+a.ty *b.r23+a.tz *b.r33+b.tz;
end;
procedure MyExitProc; far;
Begin
ExitProc := OldExitProc; { Restore exit procedure address }
CloseGraph; { Shut down the graphics system }
End;
Procedure StartGraph;
var
ErrorCode : integer;
Begin
{ when using Crt and graphics, turn off Crt's memory-mapped writes }
RegisterBGIDriver(@EGAVGADriver);
OldExitProc := ExitProc; { save previous exit proc }
ExitProc := @MyExitProc; { insert our exit proc in chain }
GraphDriver := VGA; { use autodetection }
GraphMode := 2;
InitGraph(GraphDriver,GraphMode,''); { activate graphics }
ErrorCode := GraphResult; { error? }
if ErrorCode <> grOk then
Begin
Writeln('Graphics error: ', GraphErrorMsg(ErrorCode));
Writeln;
Writeln(' It seems as though your computer does not support VGA');
Halt(1);
End;
MaxColor := GetMaxColor; { Get the maximum allowable drawing color }
MaxX := GetMaxX; { Get screen resolution values }
MaxY := GetMaxY;
End;
procedure calcPoint(p3d : point3d; var psc : screenPoints);
Begin with p3d, psc do
Begin
sX := Round( (x*(HalfWidth/(HalfWidth-z))) * (MaxX/ScreenWidth) ) + (MaxX DIV 2);
sY := Round( (-y*(HalfWidth/(HalfWidth-z))) * (MaxY/ScreenWidth) ) + (MaxY DIV 2);
end;
End;
constructor BaseObject.Open;
begin
name := myName;
myColor := color;
location := ZeroPoint;
MyCtm.SetUnit;
end;
destructor BaseObject.CloseMe;
begin
end;
procedure BaseObject.move(axis : axisType; by: real);
begin
case axis of
x : begin
myCtm.translateX(by);
location.x :=location.x+by;
end;
y : begin
myCtm.translateY(by);
location.y :=location.y+by;
end;
z : begin
myCtm.translateZ(by);
location.z :=location.z+by;
end;
end; {case}
scrPntUpdt := False;
end;
procedure BaseObject.translate(dx, dy, dz : integer);
begin
myCtm.translate(dx,dy,dz);
location.x :=location.x+dx;
location.y :=location.y+dy;
location.z :=location.z+dz;
scrPntUpdt := False;
end;
procedure BaseObject.show;
begin
setColor(myColor);
paint;
end;
procedure BaseObject.hide;
begin
setColor(0); {backGround}
paint; {at this color}
end;
procedure BaseObject.Paint;
begin
if (not(scrPntUpdt)) then
updateScreenPoints;
end;
procedure BaseObject.UpdateScreenPoints;
begin
scrPntUpdt := True;
end;
procedure BaseObject.scale(axis : axisType; factor : real);
begin
myCtm.translate(-location.x,-location.y,-location.z);
case axis of
x : myCtm.scaleX(factor);
y : myCtm.scaleY(factor);
z : myCtm.scaleZ(factor);
end; {scale}
myCtm.translate(location.x,location.y,location.z);
scrPntUpdt := False;
end; {baseObject.scale}
procedure BaseObject.allScale(sx,sy,sz : real);
begin
myCtm.translate(-location.x, -location.y, -location.z);
myCtm.scale(sx,sy,sz);
myCtm.translate(location.x, location.y, location.z);
scrPntUpdt := False;
end;
procedure BaseObject.goto3dPos;
begin
translate(round(x - location.x), round(y - location.y)
, round(z - location.z));
end;
procedure BaseObject.setToOrigin;
begin
goto3dPos(0, 0, 0);
myCtm.setUnit;
location := zeroPoint;
end;
procedure BaseObject.CalcLocation;
begin
location := zeroPoint;
end;
procedure BaseObject.deleteTransform;
begin
myCtm.setUnit;
scrPntUpdt := false;
end;
procedure BaseObject.rotate;
begin
myCtm.translate(-location.x,-location.y,-location.z);
case axis of
x : myCtm.rotateX(deg);
y : myCtm.rotateY(deg);
z : myCtm.rotateZ(deg);
end; {case}
myCtm.translate(location.x,location.y,location.z);
scrPntUpdt := False;
end;
function baseObject.load;
var
elementFile : f_real;
errC : word;
begin
{$i-} {supposed to be so, just making sure}
assign(elementFile,name);
reset(elementFile); {o.k. open it}
errC := ioResult;
load := errC;
if (errC = 0) then begin
readMe(elementFile);
errC := ioResult;
load := errC;
close(elementFile);
calcLocation;
scrPntUpdt := false;
end; {if}
end;
function baseObject.save;
var
elementFile : f_real;
errC : word;
begin
{$i-} {supposed to be so, just making sure}
assign(elementFile,name);
rewrite(elementFile); {o.k. open it}
errC := ioResult;
save := errC;
if (errC = 0) then begin
writeMe(elementFile);
errC := ioResult; save := errC;
close(elementFile);
end; {if}
end;
procedure baseObject.writeMe;
begin
{override by descendents }
end;
procedure baseObject.readMe;
begin
{override by descendents }
end;
constructor Obj3d.open;
begin
BaseObject.Open(myName, color);
scrPntUpdt := False; {not calculated yet}
numOfLines := 0;
numOfPoints := 0;
myCtm.setUnit; {initialize to unit matrix}
reverseRot.setUnit;
unReverseRot.setUnit;
end;
destructor Obj3d.CloseMe;
begin
end;
procedure Obj3d.updateScreenPoints;
var i : integer;
p : point3d;
begin
for i := 1 to numOfPoints do begin
myCtm.transform(p,points[i]); {transform by ctm}
calcPoint(p, scrPoints[i]);
end; {for}
scrPntUpdt := True; {make sure for next time..}
{make all points ready}
end;
procedure Obj3d.paint;
var
i : integer;
begin
if ((numOfPoints = 0) or (numOfLines = 0)) then exit;
if (not(scrPntUpdt)) then
updateScreenPoints;
for i := 1 to numOfLines do
line( scrPoints[lines[i].fromP].sX,
scrPoints[lines[i].fromP].sY,
scrPoints[lines[i].toP].sX,
scrPoints[lines[i].toP].sY );
{it should be noted that calcPoint has to convert points to integers}
end;
procedure obj3d.readMe;
var
tmp1,tmp2 : real;
i,j : byte;
begin
read(elementFile, tmp1);
numOfPoints := trunc(tmp1);
for j := 1 to numOfPoints do begin
read(elementFile, points[j].x);
read(elementFile, points[j].y);
read(elementFile, points[j].z);
end; {for}
read(elementFile, tmp1);
numOfLines := trunc(tmp1);
for j := 1 to numOfLines do begin
read(elementFile, tmp1, tmp2);
lines[j].fromP := trunc(tmp1);
lines[j].toP := trunc(tmp2);
end; {for}
end;
procedure obj3d.writeMe;
var
tmp1,tmp2 : real;
i,j : byte;
begin
tmp1 := numOfPoints;
write(elementFile, tmp1);
for j := 1 to numOfPoints do begin
write(elementFile, points[j].x);
write(elementFile, points[j].y);
write(elementFile, points[j].z);
end; {for}
tmp1 := numOfLines;
write(elementFile, tmp1);
for j := 1 to numOfLines do begin
tmp1 := lines[j].fromP;
tmp2 := lines[j].toP;
write(elementFile, tmp1, tmp2);
end;
end;
procedure obj3d.calcLocation;
var
ce : point3d;
p : point3d;
i : integer;
begin
ce := zeroPoint; { (0, 0, 0) -> ce }
for i := 1 to numOfPoints do begin
myCtm.transform(p, points[i]);
ce.x := ce.x + p.x;
ce.y := ce.y + p.y;
ce.z := ce.z + p.z;
end; {for}
location.x := ce.x / numOfPoints;
location.y := ce.y / numOfPoints;
location.z := ce.z / numOfPoints;
end;
procedure Obj3d.setToOrigin;
var
i : integer;
p : point3d;
begin
goto3dPos(0, 0, 0);
for i := 1 to numOfPoints do begin
myCtm.transform(p, points[i]);
points[i] := p;
end; {for}
scrPntUpdt := False; (** Instead of that THING above **)
myCtm.setUnit;
location := zeroPoint;
end;
var
i,Dlay,code,
element : integer;
ee : word;
obj : array [ 1 .. 9 ] of baseObjectPtr;
ch : char;
V0 ,V1 ,V2 ,V3 ,V4 ,V5 ,V6 ,V7 ,V8 ,V9 : real;
I0 ,I1 ,I2 ,I3 ,I4 ,I5 ,I6 ,I7 ,I8 ,I9 : integer;
procedure error(i : byte; j : word);
var
errStr : string[20];
a :char;
begin
restoreCrtMode;
case i of
1 : errStr := 'I/O error #'
else errStr := 'General error #'
end; { case }
writeln;
write(errStr);
if (j <> 0) then begin
write(j);
if j=2 then Writeln('> Files Not Found (OBJ1.3DD and OBJ2.3DD)');
end
else
writeln;
closeGraph;
halt(1)
end;
Begin
OutString:='OBJ1.3DD';
OutString2:='OBJ2.3DD';
StartGraph;SetColor(White);
OutTextXY(10,10,'Press a key to stop...');
Obj[1] := new(obj3dPtr, open(OutString, zeroPoint, maxColor));
Obj[2] := new(obj3dPtr, open(OutString2, zeroPoint, maxColor));
ee := obj[1]^.load;
ee := obj[2]^.load;
if (ee <> 0) then
error(1, ee);
Obj[1]^.myctm.SetUnit;
Obj[2]^.myctm.SetUnit;
Obj[1]^.AllScale(1.5,1.7,1.5);
Obj[2]^.AllScale(1.0,1.5,1.0);
Obj[1]^.goto3DPos(0,0,0);
Obj[2]^.goto3dpos(0,0,0);
repeat
obj[1]^.myctm.rotateX(1);
obj[2]^.myctm.rotateY(1);
obj[1]^.ScrPntUpdt:=True;
obj[2]^.ScrPntUpdt:=True;
obj[1]^.Hide;
obj[2]^.Hide;
obj[1]^.ScrPntUpdt:=False;
obj[2]^.ScrPntUpdt:=False;
obj[1]^.show;
obj[2]^.show;
Delay(8);
until keypressed;
closeGraph;
end.