home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 April A / Pcwk4a98.iso / PROGRAM / DELPHI16 / Disp3d / ROT3D.PAS < prev    next >
Pascal/Delphi Source File  |  1995-10-07  |  7KB  |  208 lines

  1.  
  2. { 3D Transform unit borrowed from public domain lad3d project }
  3. { with minor adaptations for use with 3D example program }
  4. { written by Michael Day V5.03 }
  5. { This version as of 30 September 1995 }
  6.  
  7. {1. To use this unit, first call SetDataConversion to specify }
  8. {   how to convert the provided data to screen values.}
  9. {2. Next call SetTransformMatrix to setup the transform matrix }
  10. {   to rotate the data by the angles passed. } 
  11. {3. Finally, call PointTransform to transform each data point into the }
  12. {   screen plot data. You can then use that informtion to plot the point.} 
  13. {These may be called in any order with the exception that #1 & #2 must be}
  14. {called at least once before calling #3 to initialize the rotation object.}
  15. {SetRef can be used to chnage the center of rotation if desired, but }
  16. {normally you will want to leave it at the value set by the }
  17. {SetTransformMatrix procedure. If you want to call SetRef, do so after the}
  18. {call to SetTransformMatrix and before using PointTransform. }
  19.  
  20. {$N+,E+}
  21. unit Rot3D;
  22. interface
  23.  
  24. type  Int3DType   = record X,Y,Z:integer; end;
  25.       Float3DType = record X,Y,Z:single; end;
  26.       MatrixType  = array [1..4, 1..4] of single;
  27.  
  28. type  RotObj = object
  29.          PlotSize      : Int3DType;
  30.          PlotCenter    : Int3DType;
  31.          PlotOffset    : Float3DType;
  32.          TmpF          : Float3DType;
  33.          DataStart     : Float3DType;
  34.          DataRange     : Float3DType;
  35.          DataOffset    : Float3DType;
  36.          DataConvert   : Float3DType;
  37.          RotationAngle : Float3Dtype;
  38.          Smat,Xmat,Ymat,Zmat,Tmat : MatrixType;
  39.  
  40.         public
  41.          procedure SetRef(X,Y,Z:single);
  42.          procedure SetDataConversion(Xs,Ys,Zs,Xr,Yr,Zr:single;
  43.                                      Cx,Cy,Cz,Sx,Sy,Sz:integer);
  44.          procedure SetTransformMatrix(Xa,Ya,Za:single);
  45.          procedure PointTransform(Xf,Yf,Zf:single; var Xo,Yo,Zo:integer);
  46.  
  47.         private
  48.          procedure InitRotation;
  49.       end;
  50.  
  51.  
  52. const pi180 : single = pi/180;
  53.  
  54.  
  55. {++++++++++++++++++++++++++++++++++++++}
  56.  
  57. implementation
  58.  
  59.  
  60. {---------------------------------------}
  61. { Setup the Data translation constants }
  62. { These are used to convert the real data into plot (screen) values }
  63. { immediately prior to the 3D transformation }
  64. { Xs,Ys,Zs is the lowest (starting) value of the data points used }
  65. { Xr,Yr,Zr is the range of the data points used }
  66. {It is assumed all data points will fit on the graph }
  67. {You must clip the data points feed to the the transformation matrix }
  68. {if you expect the resulting data to be valid. Data points that are }
  69. {outside the provided range may return erronious coordinate values }
  70. {Cx,Cy,Cz is the offset on the screen about which the data will rotate.}
  71. {Sx,Sy,Sz is the target 3D plot (screen) size in pixels.}
  72. {The data is adjusted to be centered on the rotation point,}
  73. {which will be the center of the defined screen image area.}
  74.  
  75. procedure RotObj.SetDataConversion(Xs,Ys,Zs,Xr,Yr,Zr:single;
  76.                                    Cx,Cy,Cz,Sx,Sy,Sz:integer);
  77. begin
  78.    DataStart.X := Xs;
  79.    DataStart.Y := Ys;
  80.    DataStart.Z := Zs;
  81.    DataRange.X := abs(Xr);
  82.    DataRange.Y := abs(Yr);
  83.    DataRange.Z := abs(Zr);
  84.    PlotSize.X := abs(Sx);
  85.    PlotSize.Y := abs(Sy);
  86.    PlotSize.Z := abs(Sz);
  87.    PlotCenter.X := Cx;
  88.    PlotCenter.Y := Cy;
  89.    PlotCenter.Z := Cz;
  90.  
  91.    DataConvert.X := PlotSize.X / DataRange.X;
  92.    DataConvert.Y := PlotSize.Y / DataRange.Y;
  93.    DataConvert.Z := PlotSize.Z / DataRange.Z;
  94.    PlotOffset.X := PlotSize.X / 2;
  95.    PlotOffset.Y := PlotSize.Y / 2;
  96.    PlotOffset.Z := PlotSize.Z / 2;
  97. end;
  98.  
  99. {---------------------------------------}
  100. {Set the reference point of the image. }
  101. {is the point about which the image will be rotated.}
  102. {This is set to zero (center) at the time SetTransformMatrix is called.}
  103. {It can be changed after the fact if desired with this function.}
  104. procedure RotObj.SetRef(X,Y,Z:single);
  105. begin
  106.    Tmat[4,1] := X;
  107.    Tmat[4,2] := Y;
  108.    Tmat[4,3] := Z;
  109. end;
  110.  
  111. {---------------------------------------}
  112. {This initializes the rotation matrixes to idenity}
  113. {i.e. it sets them for no rotation of the data}
  114. {This must be done before modifying the matrix}
  115. procedure RotObj.InitRotation;
  116. var i,ii:integer;
  117. begin
  118.   for i := 1 to 4 do
  119.   begin
  120.     for ii := 1 to 4 do
  121.     begin
  122.         Xmat[i,ii] := 0;
  123.         Ymat[i,ii] := 0;
  124.         Zmat[i,ii] := 0;
  125.     end;
  126.     if i <> 4 then
  127.     begin
  128.       Xmat[i,i] := 1;
  129.       Ymat[i,i] := 1;
  130.       Zmat[i,i] := 1;
  131.     end;
  132.   end;
  133. end;
  134.  
  135.  
  136. {---------------------------------------}
  137. {create a rotation transform matrix using Xa, Ya, Za parameters}
  138. procedure RotObj.SetTransformMatrix(Xa,Ya,Za:single);
  139. var Xc,Yc,Zc,Xs,Ys,Zs:single;
  140.     i,j,k:word;
  141.     Lmat : MatrixType;
  142. begin
  143.   RotationAngle.X := Xa;
  144.   Xc := cos(Xa*pi180);
  145.   Xs := sin(Xa*pi180);
  146.   RotationAngle.Y := Ya;
  147.   Yc := cos(Ya*pi180);
  148.   Ys := sin(Ya*pi180);
  149.   RotationAngle.Z := Za;
  150.   Zc := cos(Za*pi180);
  151.   Zs := sin(Za*pi180);
  152.   InitRotation;
  153.  
  154.   Xmat[2,2] := Xc; Xmat[2,3] := -Xs; Xmat[3,2] := Xs;  Xmat[3,3] := Xc;
  155.   Ymat[1,1] := Yc; Ymat[1,3] :=  Ys; Ymat[3,1] := -Ys; Ymat[3,3] := Yc;
  156.   Zmat[1,1] := Zc; Zmat[1,2] := -Zs; Zmat[2,1] := Zs;  Zmat[2,2] := Zc;
  157.  
  158.   for i := 1 to 4 do
  159.   begin
  160.     for j := 1 to 4 do
  161.     begin
  162.       Lmat[i,j] := 0;
  163.       for k := 1 to 4 do
  164.       begin
  165.         Lmat[i,j] := Lmat[i,j]+(Xmat[i,k]*Ymat[k,j]);
  166.       end;
  167.     end;
  168.   end;
  169.  
  170.   for i := 1 to 4 do
  171.   begin
  172.     for j := 1 to 4 do
  173.     begin
  174.       Tmat[i,j] := 0;
  175.       for k := 1 to 4 do
  176.       begin
  177.         Tmat[i,j] := Tmat[i,j]+(Lmat[i,k]*Zmat[k,j]);
  178.       end;
  179.     end;
  180.   end;
  181.  
  182. end;
  183.  
  184. {---------------------------------------}
  185. {converts the real data in Xf,Yf,Zf into 3D plot (screen) cordinates}
  186. {then transforms the data by multiplying it by the TM matrix}
  187. {returns the transformed points (screen values) in Xo,Yo,Zo}
  188. procedure RotObj.PointTransform(Xf,Yf,Zf:single; var Xo,Yo,Zo:integer);
  189. begin
  190.   {Convert the data to screen coordinates in TmpF}
  191.   TmpF.X := ((Xf-DataStart.X)*DataConvert.X)-PlotOffset.X;
  192.   TmpF.Y := ((Yf-DataStart.Y)*DataConvert.Y)-PlotOffset.Y;
  193.   TmpF.Z := ((Zf-DataStart.Z)*DataConvert.Z)-PlotOffset.Z;
  194.   {rotate the screen coordinates to the desired position}
  195.   Xo := PlotCenter.X+round(((TmpF.X*Tmat[1,1])+(TmpF.Y*Tmat[1,2])+
  196.                             (TmpF.Z*Tmat[1,3]))+Tmat[1,4]);
  197.   Yo := PlotCenter.Y+round(((TmpF.X*Tmat[2,1])+(TmpF.Y*Tmat[2,2])+
  198.                             (TmpF.Z*Tmat[2,3]))+Tmat[2,4]);
  199.   Zo := PlotCenter.Z+round(((TmpF.X*Tmat[3,1])+(TmpF.Y*Tmat[3,2])+
  200.                             (TmpF.Z*Tmat[3,3]))+Tmat[3,4]);
  201. end;
  202.  
  203.  
  204.  
  205. end.
  206.  
  207.  
  208.