home *** CD-ROM | disk | FTP | other *** search
-
- { 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.
-
-