home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 April A
/
Pcwk4a98.iso
/
PROGRAM
/
DELPHI16
/
Disp3d
/
ROT3D.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1995-10-07
|
7KB
|
208 lines
{ 3D Transform unit borrowed from public domain lad3d project }
{ with minor adaptations for use with 3D example program }
{ written by Michael Day V5.03 }
{ This version as of 30 September 1995 }
{1. To use this unit, first call SetDataConversion to specify }
{ how to convert the provided data to screen values.}
{2. Next call SetTransformMatrix to setup the transform matrix }
{ to rotate the data by the angles passed. }
{3. Finally, call PointTransform to transform each data point into the }
{ screen plot data. You can then use that informtion to plot the point.}
{These may be called in any order with the exception that #1 & #2 must be}
{called at least once before calling #3 to initialize the rotation object.}
{SetRef can be used to chnage the center of rotation if desired, but }
{normally you will want to leave it at the value set by the }
{SetTransformMatrix procedure. If you want to call SetRef, do so after the}
{call to SetTransformMatrix and before using PointTransform. }
{$N+,E+}
unit Rot3D;
interface
type Int3DType = record X,Y,Z:integer; end;
Float3DType = record X,Y,Z:single; end;
MatrixType = array [1..4, 1..4] of single;
type RotObj = object
PlotSize : Int3DType;
PlotCenter : Int3DType;
PlotOffset : Float3DType;
TmpF : Float3DType;
DataStart : Float3DType;
DataRange : Float3DType;
DataOffset : Float3DType;
DataConvert : Float3DType;
RotationAngle : Float3Dtype;
Smat,Xmat,Ymat,Zmat,Tmat : MatrixType;
public
procedure SetRef(X,Y,Z:single);
procedure SetDataConversion(Xs,Ys,Zs,Xr,Yr,Zr:single;
Cx,Cy,Cz,Sx,Sy,Sz:integer);
procedure SetTransformMatrix(Xa,Ya,Za:single);
procedure PointTransform(Xf,Yf,Zf:single; var Xo,Yo,Zo:integer);
private
procedure InitRotation;
end;
const pi180 : single = pi/180;
{++++++++++++++++++++++++++++++++++++++}
implementation
{---------------------------------------}
{ Setup the Data translation constants }
{ These are used to convert the real data into plot (screen) values }
{ immediately prior to the 3D transformation }
{ Xs,Ys,Zs is the lowest (starting) value of the data points used }
{ Xr,Yr,Zr is the range of the data points used }
{It is assumed all data points will fit on the graph }
{You must clip the data points feed to the the transformation matrix }
{if you expect the resulting data to be valid. Data points that are }
{outside the provided range may return erronious coordinate values }
{Cx,Cy,Cz is the offset on the screen about which the data will rotate.}
{Sx,Sy,Sz is the target 3D plot (screen) size in pixels.}
{The data is adjusted to be centered on the rotation point,}
{which will be the center of the defined screen image area.}
procedure RotObj.SetDataConversion(Xs,Ys,Zs,Xr,Yr,Zr:single;
Cx,Cy,Cz,Sx,Sy,Sz:integer);
begin
DataStart.X := Xs;
DataStart.Y := Ys;
DataStart.Z := Zs;
DataRange.X := abs(Xr);
DataRange.Y := abs(Yr);
DataRange.Z := abs(Zr);
PlotSize.X := abs(Sx);
PlotSize.Y := abs(Sy);
PlotSize.Z := abs(Sz);
PlotCenter.X := Cx;
PlotCenter.Y := Cy;
PlotCenter.Z := Cz;
DataConvert.X := PlotSize.X / DataRange.X;
DataConvert.Y := PlotSize.Y / DataRange.Y;
DataConvert.Z := PlotSize.Z / DataRange.Z;
PlotOffset.X := PlotSize.X / 2;
PlotOffset.Y := PlotSize.Y / 2;
PlotOffset.Z := PlotSize.Z / 2;
end;
{---------------------------------------}
{Set the reference point of the image. }
{is the point about which the image will be rotated.}
{This is set to zero (center) at the time SetTransformMatrix is called.}
{It can be changed after the fact if desired with this function.}
procedure RotObj.SetRef(X,Y,Z:single);
begin
Tmat[4,1] := X;
Tmat[4,2] := Y;
Tmat[4,3] := Z;
end;
{---------------------------------------}
{This initializes the rotation matrixes to idenity}
{i.e. it sets them for no rotation of the data}
{This must be done before modifying the matrix}
procedure RotObj.InitRotation;
var i,ii:integer;
begin
for i := 1 to 4 do
begin
for ii := 1 to 4 do
begin
Xmat[i,ii] := 0;
Ymat[i,ii] := 0;
Zmat[i,ii] := 0;
end;
if i <> 4 then
begin
Xmat[i,i] := 1;
Ymat[i,i] := 1;
Zmat[i,i] := 1;
end;
end;
end;
{---------------------------------------}
{create a rotation transform matrix using Xa, Ya, Za parameters}
procedure RotObj.SetTransformMatrix(Xa,Ya,Za:single);
var Xc,Yc,Zc,Xs,Ys,Zs:single;
i,j,k:word;
Lmat : MatrixType;
begin
RotationAngle.X := Xa;
Xc := cos(Xa*pi180);
Xs := sin(Xa*pi180);
RotationAngle.Y := Ya;
Yc := cos(Ya*pi180);
Ys := sin(Ya*pi180);
RotationAngle.Z := Za;
Zc := cos(Za*pi180);
Zs := sin(Za*pi180);
InitRotation;
Xmat[2,2] := Xc; Xmat[2,3] := -Xs; Xmat[3,2] := Xs; Xmat[3,3] := Xc;
Ymat[1,1] := Yc; Ymat[1,3] := Ys; Ymat[3,1] := -Ys; Ymat[3,3] := Yc;
Zmat[1,1] := Zc; Zmat[1,2] := -Zs; Zmat[2,1] := Zs; Zmat[2,2] := Zc;
for i := 1 to 4 do
begin
for j := 1 to 4 do
begin
Lmat[i,j] := 0;
for k := 1 to 4 do
begin
Lmat[i,j] := Lmat[i,j]+(Xmat[i,k]*Ymat[k,j]);
end;
end;
end;
for i := 1 to 4 do
begin
for j := 1 to 4 do
begin
Tmat[i,j] := 0;
for k := 1 to 4 do
begin
Tmat[i,j] := Tmat[i,j]+(Lmat[i,k]*Zmat[k,j]);
end;
end;
end;
end;
{---------------------------------------}
{converts the real data in Xf,Yf,Zf into 3D plot (screen) cordinates}
{then transforms the data by multiplying it by the TM matrix}
{returns the transformed points (screen values) in Xo,Yo,Zo}
procedure RotObj.PointTransform(Xf,Yf,Zf:single; var Xo,Yo,Zo:integer);
begin
{Convert the data to screen coordinates in TmpF}
TmpF.X := ((Xf-DataStart.X)*DataConvert.X)-PlotOffset.X;
TmpF.Y := ((Yf-DataStart.Y)*DataConvert.Y)-PlotOffset.Y;
TmpF.Z := ((Zf-DataStart.Z)*DataConvert.Z)-PlotOffset.Z;
{rotate the screen coordinates to the desired position}
Xo := PlotCenter.X+round(((TmpF.X*Tmat[1,1])+(TmpF.Y*Tmat[1,2])+
(TmpF.Z*Tmat[1,3]))+Tmat[1,4]);
Yo := PlotCenter.Y+round(((TmpF.X*Tmat[2,1])+(TmpF.Y*Tmat[2,2])+
(TmpF.Z*Tmat[2,3]))+Tmat[2,4]);
Zo := PlotCenter.Z+round(((TmpF.X*Tmat[3,1])+(TmpF.Y*Tmat[3,2])+
(TmpF.Z*Tmat[3,3]))+Tmat[3,4]);
end;
end.