MM3D.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:30k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49 (0)351-8037944              =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 31.07.98 - 23:35:59 $                                        =}
  24. {========================================================================}
  25. unit MM3D;
  26. {$I COMPILER.INC}
  27. {.$DEFINE _DEBUG}
  28. interface
  29. uses
  30.     Classes,
  31.     SysUtils,
  32.     Windows,
  33.     Graphics,
  34.     MMObj;
  35. type
  36.     FLOAT3D         = Extended;
  37.     {$IFDEF CBUILDER3} {$EXTERNALSYM LONG} {$ENDIF}
  38.     LONG            = LongInt;
  39.     {$IFDEF CBUILDER3} {$EXTERNALSYM PVOID} {$ENDIF}
  40.     PVOID           = Pointer;
  41.     PMM3DColor      = ^TMM3DColor;
  42.     TMM3DColor      = DWORD;
  43.     PMM3DValue      = ^TMM3DValue;
  44.     TMM3DValue      = FLOAT3D;
  45.     PMM3DVector     = ^TMM3DVector;
  46.     TMM3DVector     = record
  47.         case Byte of
  48.             0: (x, y, z: TMM3DValue);
  49.             1: (dvX, dvY, dvZ: TMM3DValue);
  50.             2: (Values: array [0..2] of TMM3DValue);
  51.     end;
  52.     PMM3DVector4D   = ^TMM3DVector4D;
  53.     TMM3DVector4D   = record
  54.         x, y, z, w  : TMM3DValue;
  55.     end;
  56.     PMM3DQuaternion = ^TMM3DQuaternion;
  57.     TMM3DQuaternion = record
  58.         s           : TMM3DValue;
  59.         v           : TMM3DVector;
  60.     end;
  61.     PMM3DMatrix4D   = ^TMM3DMatrix4D;
  62.     TMM3DMatrix4D   = array[0..3,0..3] of TMM3DValue;
  63.     TMM3DProjectionType = (ptPerspective,ptOrthographic);
  64. type
  65.     {-- TMM3DMatrix --------------------------------------------------------------}
  66.     TMMMatrix3D     = class(TMMObject)
  67.     private
  68.         FMatrix     : TMM3DMatrix4D;
  69.         procedure   SetMatrix(const Value: TMM3DMatrix4D);
  70.         procedure   WriteMatrix(Writer: TWriter);
  71.         procedure   ReadMatrix(Reader: TReader);
  72.         function    GetCell(Row, Col: Integer): TMM3DValue;
  73.         procedure   SetCell(Row, Col: Integer; Value: TMM3DValue);
  74.     protected
  75.         procedure   DefineProperties(Filer: TFiler); override;
  76.     public
  77.         function    VectorTransform(const V: TMM3DVector): TMM3DVector4D;
  78.         function    InverseVectorTransform(const V: TMM3DVector): TMM3DVector4D;
  79.         procedure   Assign(Source: TPersistent); override;
  80.         {$IFDEF CBUILDER3} {$EXTERNALSYM TMMMatrix3D.AsMatrix} {$ENDIF}
  81.         property    AsMatrix                : TMM3DMatrix4D read FMatrix write SetMatrix;
  82.         property    Cell[Row,Col: Integer]  : TMM3DValue read GetCell write SetCell; default;
  83.     end;
  84.     {-- TMM3DVector --------------------------------------------------------------}
  85.     TMMVector3D     = class(TMMObject)
  86.     private
  87.         FVector     : TMM3DVector;
  88.         procedure   SetComp(Index: Integer; Value: TMM3DValue);
  89.         function    GetComp(Index: Integer): TMM3DValue;
  90.         procedure   SetAsVector(const Value: TMM3DVector);
  91.     public
  92.         procedure   Assign(Source: TPersistent); override;
  93.         property    AsVector : TMM3DVector read FVector write SetAsVector;
  94.     published
  95.         property    X: TMM3DValue index 0 read GetComp write SetComp;
  96.         property    Y: TMM3DValue index 1 read GetComp write SetComp;
  97.         property    Z: TMM3DValue index 2 read GetComp write SetComp;
  98.     end;
  99. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DCreateColorRGB} {$ENDIF}
  100. function    MM3DCreateColorRGB(red, green, blue: TMM3DValue): TMM3DColor;
  101. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DCreateColorRGBA} {$ENDIF}
  102. function    MM3DCreateColorRGBA(red, green, blue, alpha: TMM3DValue): TMM3DColor;
  103. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DColorGetRed} {$ENDIF}
  104. function    MM3DColorGetRed(color: TMM3DColor): TMM3DValue;
  105. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DColorGetGreen} {$ENDIF}
  106. function    MM3DColorGetGreen(color: TMM3DColor): TMM3DValue;
  107. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DColorGetBlue} {$ENDIF}
  108. function    MM3DColorGetBlue(color: TMM3DColor): TMM3DValue;
  109. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DColorGetAlpha} {$ENDIF}
  110. function    MM3DColorGetAlpha(color: TMM3DColor): TMM3DValue;
  111. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DBuildRGBColor} {$ENDIF}
  112. function    MM3DBuildRGBColor(color: TMM3DColor): TColor;
  113. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorAdd} {$ENDIF}
  114. function    MM3DVectorAdd(const s1, s2: TMM3DVector): TMM3DVector;
  115. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorSubtract} {$ENDIF}
  116. function    MM3DVectorSubtract(const s1, s2: TMM3DVector): TMM3DVector;
  117. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorReflect} {$ENDIF}
  118. function    MM3DVectorReflect(const ray, normal: TMM3DVector): TMM3DVector;
  119. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorCrossProduct} {$ENDIF}
  120. function    MM3DVectorCrossProduct(const s1, s2: TMM3DVector): TMM3DVector;
  121. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorDotProduct} {$ENDIF}
  122. function    MM3DVectorDotProduct(const s1, s2: TMM3DVector): TMM3DValue;
  123. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorNormalize} {$ENDIF}
  124. function    MM3DVectorNormalize(const v: TMM3DVector): TMM3DVector;
  125. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorNormalise} {$ENDIF}
  126. function    MM3DVectorNormalise(const v: TMM3DVector): TMM3DVector;
  127. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorModulus} {$ENDIF}
  128. function    MM3DVectorModulus(const v: TMM3DVector): TMM3DValue;
  129. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorRotate} {$ENDIF}
  130. function    MM3DVectorRotate(const v, axis: TMM3DVector; theta: TMM3DValue): TMM3DVector;
  131. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorScale} {$ENDIF}
  132. function    MM3DVectorScale(const s: TMM3DVector; factor: TMM3DValue): TMM3DVector;
  133. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorRandom} {$ENDIF}
  134. function    MM3DVectorRandom: TMM3DVector;
  135. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DQuaternionFromRotation} {$ENDIF}
  136. function    MM3DQuaternionFromRotation(const v: TMM3DVector; theta: TMM3DValue): TMM3DQuaternion;
  137. //function    MM3DQuaternionMultiply(const a, b: TMM3DQuaternion): TMM3DQuaternion;
  138. //function    MM3DQuaternionSlerp(const a, b: TMM3DQuaternion; alpha: TMM3DValue): TMM3DQuaternion;
  139. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixFromQuaternion} {$ENDIF}
  140. function    MM3DMatrixFromQuaternion(const q: TMM3DQuaternion): TMM3DMatrix4D;
  141. { NOTE: Not all functions listed below work properly }
  142. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVector} {$ENDIF}
  143. function    MM3DVector(x, y, z: TMM3DValue): TMM3DVector;
  144. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorRotateQ} {$ENDIF}
  145. function    MM3DVectorRotateQ(const v: TMM3DVector; const q: TMM3DQuaternion): TMM3DVector;
  146. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorTransform} {$ENDIF}
  147. function    MM3DVectorTransform(const v: TMM3DVector; const Mat: TMM3DMatrix4D): TMM3DVector4D;
  148. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVector3D} {$ENDIF}
  149. function    MM3DVector3D(const v: TMM3DVector4D): TMM3DVector;
  150. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DCreateViewportMatrix} {$ENDIF}
  151. function    MM3DCreateViewportMatrix(Front: TMM3DValue; Proj: TMM3DProjectionType): TMM3DMatrix4D;
  152. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixMul} {$ENDIF}
  153. function    MM3DMatrixMul(const M1, M2: TMM3DMatrix4D): TMM3DMatrix4D;
  154. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixFromTranslation} {$ENDIF}
  155. function    MM3DMatrixFromTranslation(const T: TMM3DVector): TMM3DMatrix4D;
  156. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixFromScaling} {$ENDIF}
  157. function    MM3DMatrixFromScaling(const T: TMM3DVector): TMM3DMatrix4D;
  158. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixFromRotation} {$ENDIF}
  159. function    MM3DMatrixFromRotation(const Axis: TMM3DVector; Angle: TMM3DValue): TMM3DMatrix4D;
  160. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixFromRotationTo} {$ENDIF}
  161. function    MM3DMatrixFromRotationTo(const Dest: TMM3DVector): TMM3DMatrix4D;
  162. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DCreateCameraMatrix} {$ENDIF}
  163. function    MM3DCreateCameraMatrix(const Origin, Front, Top: TMM3DVector): TMM3DMatrix4D;
  164. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorInvert} {$ENDIF}
  165. function    MM3DVectorInvert(const V: TMM3DVector): TMM3DVector;
  166. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixInvert} {$ENDIF}
  167. function    MM3DMatrixInvert(const M: TMM3DMatrix4D): TMM3DMatrix4D;
  168. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixDeterminant} {$ENDIF}
  169. function    MM3DMatrixDeterminant(const M: TMM3DMatrix4D): TMM3DValue;
  170. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixCofactor} {$ENDIF}
  171. function    MM3DMatrixCofactor(const M: TMM3DMatrix4D; i, j: Integer): TMM3DValue;
  172. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorDegToRad} {$ENDIF}
  173. function    MM3DVectorDegToRad(const R: TMM3DVector): TMM3DVector;
  174. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorRadToDeg} {$ENDIF}
  175. function    MM3DVectorRadToDeg(const R: TMM3DVector): TMM3DVector;
  176. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DDegToRad} {$ENDIF}
  177. function    MM3DDegToRad(D: TMM3DValue): TMM3DValue;
  178. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DRadToDeg} {$ENDIF}
  179. function    MM3DRadToDeg(R: TMM3DValue): TMM3DValue;
  180. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DMatrixFromCameraOrientation} {$ENDIF}
  181. function    MM3DMatrixFromCameraOrientation(const Front, Top: TMM3DVector): TMM3DMatrix4D;
  182. {$IFDEF CBUILDER3} {$EXTERNALSYM MM3DVectorEqual} {$ENDIF}
  183. function    MM3DVectorEqual(const V1, V2: TMM3DVector): Boolean;
  184. type
  185.     {-- EMM3DError ---------------------------------------------------------------}
  186.     EMM3DError  = class(Exception)
  187.     end;
  188. const
  189.     XUnit       : TMM3DVector   = (x:1;y:0;z:0);
  190.     YUnit       : TMM3DVector   = (x:0;y:1;z:0);
  191.     ZUnit       : TMM3DVector   = (x:0;y:0;z:1);
  192.     ZeroVector  : TMM3DVector   = (x:0;y:0;z:0);
  193.     Identity    : TMM3DMatrix4D = (
  194.                                     (1, 0, 0, 0),
  195.                                     (0, 1, 0, 0),
  196.                                     (0, 0, 1, 0),
  197.                                     (0, 0, 0, 1)
  198.                                   );
  199. var
  200.     White       : TMM3DColor;
  201.     Red         : TMM3DColor;
  202.     Blue        : TMM3DColor;
  203.     Green       : TMM3DColor;
  204.     LightRed    : TMM3DColor;
  205.     LightBlue   : TMM3DColor;
  206.     LightGreen  : TMM3DColor;
  207.     Yellow      : TMM3DColor;
  208.     Black       : TMM3DColor;
  209. implementation
  210. uses
  211.     MMMath,
  212.     MMUtils
  213. {$IFDEF _DEBUG}
  214.     ,MMDebug
  215. {$ENDIF}
  216.     ;
  217. {-----------------------------------------------------------------------------}
  218. function    MM3DCreateColorRGB(red, green, blue: TMM3DValue): TMM3DColor;
  219. begin
  220.     Result  := $ff000000 or (Trunc(red * 255) shl 16) or (Trunc(green * 255) shl 8) or Trunc(blue * 255);
  221. end;
  222. {-----------------------------------------------------------------------------}
  223. function    MM3DCreateColorRGBA(red, green, blue, alpha: TMM3DValue): TMM3DColor;
  224. begin
  225.     Result  := (Trunc(alpha * 255) shl 24) or (Trunc(red * 255) shl 16) or (Trunc(green * 255) shl 8) or Trunc(blue * 255);
  226. end;
  227. {-----------------------------------------------------------------------------}
  228. function    MM3DColorGetRed(color: TMM3DColor): TMM3DValue;
  229. begin
  230.     Result  := ((color shr 16) and $ff)/255;
  231. end;
  232. {-----------------------------------------------------------------------------}
  233. function    MM3DColorGetGreen(color: TMM3DColor): TMM3DValue;
  234. begin
  235.     Result  := ((color shr 8) and $ff)/255;
  236. end;
  237. {-----------------------------------------------------------------------------}
  238. function    MM3DColorGetBlue(color: TMM3DColor): TMM3DValue;
  239. begin
  240.     Result  := (color and $ff)/255;
  241. end;
  242. {-----------------------------------------------------------------------------}
  243. function    MM3DColorGetAlpha(color: TMM3DColor): TMM3DValue;
  244. begin
  245.     Result  := (color shr 24)/255;
  246. end;
  247. {-----------------------------------------------------------------------------}
  248. function    MM3DBuildRGBColor(color: TMM3DColor): TColor;
  249. type
  250.     TBytes = record
  251.         case Byte of
  252.             0: (C: TMM3DColor);
  253.             1: (B, G, R, A: Byte);
  254.     end;
  255. begin
  256.     with TBytes(color) do
  257.         Result := RGB(R,G,B);
  258. end;
  259. {-----------------------------------------------------------------------------}
  260. function    MM3DVectorAdd(const s1, s2: TMM3DVector): TMM3DVector;
  261. begin
  262.     with Result do
  263.     begin
  264.         x := s1.x + s2.x;
  265.         y := s1.y + s2.y;
  266.         z := s1.z + s2.z;
  267.     end;
  268. end;
  269. {-----------------------------------------------------------------------------}
  270. function    MM3DVectorSubtract(const s1, s2: TMM3DVector): TMM3DVector;
  271. begin
  272.     with Result do
  273.     begin
  274.         x := s1.x - s2.x;
  275.         y := s1.y - s2.y;
  276.         z := s1.z - s2.z;
  277.     end;
  278. end;
  279. {-----------------------------------------------------------------------------}
  280. function    MM3DVectorReflect(const ray, normal: TMM3DVector): TMM3DVector;
  281. begin
  282.     Result := MM3DVectorRotate(ray,normal,Pi);
  283. end;
  284. {-----------------------------------------------------------------------------}
  285. function    MM3DVectorCrossProduct(const s1, s2: TMM3DVector): TMM3DVector;
  286. begin
  287.     with Result do
  288.     begin
  289.        X := (s1.Y*s2.Z)-(s1.Z*s2.Y);
  290.        Y := (s1.Z*s2.X)-(s1.X*s2.Z);
  291.        Z := (s1.X*s2.Y)-(s1.Y*s2.X);
  292.     end;
  293. end;
  294. {-----------------------------------------------------------------------------}
  295. function    MM3DVectorDotProduct(const s1, s2: TMM3DVector): TMM3DValue;
  296. begin
  297.     Result  := (s1.X * s2.X) + (s1.Y * s2.Y) + (s1.Z * s2.Z);
  298. end;
  299. {-----------------------------------------------------------------------------}
  300. function    MM3DVectorNormalize(const v: TMM3DVector): TMM3DVector;
  301. var
  302.     M: TMM3DValue;
  303. begin
  304.     M := MM3DVectorModulus(v);
  305.     if M = 0 then
  306.         { TODO: Should be resource id }
  307.         raise EMM3DError.Create('Zero-length vector passed to normalize');
  308.     with Result do
  309.     begin
  310.         X := v.X/M;
  311.         Y := v.Y/M;
  312.         Z := v.Z/M;
  313.     end;
  314. end;
  315. {-----------------------------------------------------------------------------}
  316. function    MM3DVectorNormalise(const v: TMM3DVector): TMM3DVector;
  317. begin
  318.     Result  := MM3DVectorNormalize(v);
  319. end;
  320. {-----------------------------------------------------------------------------}
  321. function    MM3DVectorModulus(const v: TMM3DVector): TMM3DValue;
  322. begin
  323.     Result := Sqrt(Sqr(v.x)+Sqr(v.y)+Sqr(v.z));
  324. end;
  325. {-----------------------------------------------------------------------------}
  326. function    MM3DVectorRotate(const v, axis: TMM3DVector; theta: TMM3DValue): TMM3DVector;
  327. var
  328.     M: TMM3DMatrix4D;
  329. begin
  330.     M       := MM3DMatrixFromRotation(axis,theta);
  331.     Result  := MM3DVector3D(MM3DVectorTransform(v,M));
  332. end;
  333. {-----------------------------------------------------------------------------}
  334. function    MM3DVectorScale(const s: TMM3DVector; factor: TMM3DValue): TMM3DVector;
  335. begin
  336.     with Result do
  337.     begin
  338.         X := s.X*factor;
  339.         Y := s.Y*factor;
  340.         Z := s.Z*factor;
  341.     end;
  342. end;
  343. {-----------------------------------------------------------------------------}
  344. function    MM3DVectorRandom: TMM3DVector;
  345. begin
  346.     with Result do
  347.     begin
  348.         X := Random(MaxInt)-(MaxInt div 2);
  349.         Y := Random(MaxInt)-(MaxInt div 2);
  350.         Z := Random(MaxInt)-(MaxInt div 2);
  351.     end;
  352.     Result := MM3DVectorNormalize(Result);
  353. end;
  354. {-----------------------------------------------------------------------------}
  355. function    MM3DQuaternionFromRotation(const v: TMM3DVector; theta: TMM3DValue): TMM3DQuaternion;
  356. var
  357.     ht: TMM3DValue;
  358.     ch, sh: TMM3DValue;
  359.     ax: TMM3DVector;
  360. begin
  361.     ax := MM3DVectorNormalize(v);
  362.     ht := theta/2;
  363.     ch := cos(ht);
  364.     sh := sin(ht);
  365.     Result.v.x := ax.x*sh;
  366.     Result.v.y := ax.y*sh;
  367.     Result.v.z := ax.z*sh;
  368.     Result.s   := ch;
  369. end;
  370. {-----------------------------------------------------------------------------}
  371. function    MM3DMatrixFromQuaternion(const q: TMM3DQuaternion): TMM3DMatrix4D;
  372. var
  373.     xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz: TMM3DValue;
  374. begin
  375.     xs := 2*q.v.x;
  376.     ys := 2*q.v.y;
  377.     zs := 2*q.v.z;
  378.     wx := q.s*xs;
  379.     wy := q.s*ys;
  380.     wz := q.s*zs;
  381.     xx := q.v.x*xs;
  382.     xy := q.v.x*ys;
  383.     xz := q.v.x*zs;
  384.     yy := q.v.y*ys;
  385.     yz := q.v.y*zs;
  386.     zz := q.v.z*zs;
  387.     Result      := Identity;
  388.     Result[0,0] := 1 - (yy + zz);
  389.     Result[0,1] := xy - wz;
  390.     Result[0,2] := xz + wy;
  391.     Result[1,0] := xy + wz;
  392.     Result[1,1] := 1 - (xx + zz);
  393.     Result[1,2] := yz - wx;
  394.     Result[2,0] := xz - wy;
  395.     Result[2,1] := yz + wx;
  396.     Result[2,2] := 1 - (xx + yy);
  397. end;
  398. {-----------------------------------------------------------------------------}
  399. function    MM3DVector(x, y, z: TMM3DValue): TMM3DVector;
  400. begin
  401.     Result.x := x;
  402.     Result.y := y;
  403.     Result.z := z;
  404. end;
  405. {-----------------------------------------------------------------------------}
  406. function    MM3DVectorRotateQ(const v: TMM3DVector; const q: TMM3DQuaternion): TMM3DVector;
  407. begin
  408.     Result  := MM3DVector3D(MM3DVectorTransform(v,MM3DMatrixFromQuaternion(q)));
  409. end;
  410. {-----------------------------------------------------------------------------}
  411. function    MM3DVectorTransform(const v: TMM3DVector; const Mat: TMM3DMatrix4D): TMM3DVector4D;
  412. begin
  413.     with v do
  414.     begin
  415.         Result.x   := x * mat[0,0] + y * mat[0,1] + z * mat[0,2] + 1 * mat[0,3];
  416.         Result.y   := x * mat[1,0] + y * mat[1,1] + z * mat[1,2] + 1 * mat[1,3];
  417.         Result.z   := x * mat[2,0] + y * mat[2,1] + z * mat[2,2] + 1 * mat[2,3];
  418.         Result.w   := x * mat[3,0] + y * mat[3,1] + z * mat[3,2] + 1 * mat[3,3];
  419.     end;
  420. end;
  421. {-----------------------------------------------------------------------------}
  422. function    MM3DCreateViewportMatrix(Front: TMM3DValue; Proj: TMM3DProjectionType): TMM3DMatrix4D;
  423. begin
  424.     FillChar(Result,SizeOf(Result),0);
  425.     if Proj = ptPerspective then
  426.     begin
  427.         Result[0,0] := Front;
  428.         Result[1,1] := Front;
  429.         Result[2,2] := 1;
  430.         Result[3,2] := 1;
  431.     end
  432.     else
  433.     begin
  434.         Result[0,0] := 1;
  435.         Result[1,1] := 1;
  436.         Result[2,3] := Front;
  437.         Result[3,3] := 1;
  438.     end;
  439. end;
  440. {-----------------------------------------------------------------------------}
  441. function    MM3DVector3D(const v: TMM3DVector4D): TMM3DVector;
  442. begin
  443.     with v do
  444.     begin
  445.         Result.X := X/W;
  446.         Result.Y := Y/W;
  447.         Result.Z := Z/W;
  448.     end;
  449. end;
  450. {-----------------------------------------------------------------------------}
  451. function    MM3DMatrixMul(const M1, M2: TMM3DMatrix4D): TMM3DMatrix4D;
  452. var
  453.     i, j: Integer;
  454. begin
  455.     for i := 0 to 3 do
  456.         for j := 0 to 3 do
  457.             Result[j,i] := M1[0,i] * M2[j,0] + M1[1,i] * M2[j,1] + M1[2,i] * M2[j,2] + M1[3,i] * M2[j,3];
  458. end;
  459. {-----------------------------------------------------------------------------}
  460. function    MM3DMatrixFromTranslation(const T: TMM3DVector): TMM3DMatrix4D;
  461. begin
  462.     FillChar(Result,SizeOf(Result),0);
  463.     Result[0,3] := T.x;
  464.     Result[1,3] := T.y;
  465.     Result[2,3] := T.z;
  466.     Result[0,0] := 1;
  467.     Result[1,1] := 1;
  468.     Result[2,2] := 1;
  469.     Result[3,3] := 1;
  470. end;
  471. {-----------------------------------------------------------------------------}
  472. function    MM3DMatrixFromScaling(const T: TMM3DVector): TMM3DMatrix4D;
  473. begin
  474.     FillChar(Result,SizeOf(Result),0);
  475.     Result[0,0] := T.x;
  476.     Result[1,1] := T.y;
  477.     Result[2,2] := T.z;
  478.     Result[3,3] := 1;
  479. end;
  480. {-----------------------------------------------------------------------------}
  481. function    MM3DMatrixFromRotation(const Axis: TMM3DVector; Angle: TMM3DValue): TMM3DMatrix4D;
  482. var
  483.     Q: TMM3DQuaternion;
  484. begin
  485.     if Angle = 0 then
  486.         Result := Identity
  487.     else
  488.     begin
  489.         Q := MM3DQuaternionFromRotation(Axis,Angle);
  490.         Result := MM3DMatrixFromQuaternion(Q);
  491.     end;
  492. end;
  493. {-----------------------------------------------------------------------------}
  494. function    MM3DMatrixFromRotationTo(const Dest: TMM3DVector): TMM3DMatrix4D;
  495. type
  496.     PVect = ^TVect;
  497.     TVect = array[0..2] of TMM3DValue;
  498. var
  499.     N, T, W, U, V: TMM3DVector;
  500.     function    GetMinorAxis(const V: TMM3DVector): Integer;
  501.     begin
  502.         Result := 0;
  503.         if V.X > V.Y then
  504.             Result := 1;
  505.         if V.Z < PVect(@V)[Result] then
  506.             Result := 2;
  507.     end;
  508. begin
  509.     N := MM3DVectorNormalize(Dest);
  510. T := N;
  511.     W := N;
  512.     PVect(@T)[GetMinorAxis(W)] := 1.0;
  513.     U := MM3DVectorNormalize(MM3DVectorCrossProduct(T,W));
  514.     V := MM3DVectorCrossProduct(W,U);
  515.     Result := Identity;
  516.     Result[0,0] := U.X;
  517.     Result[0,1] := U.Y;
  518.     Result[0,2] := U.Z;
  519.     Result[1,0] := V.X;
  520.     Result[1,1] := V.Y;
  521.     Result[1,2] := V.Z;
  522.     Result[2,0] := W.X;
  523.     Result[2,1] := W.Y;
  524.     Result[2,2] := W.Z;
  525. end;
  526. {-----------------------------------------------------------------------------}
  527. function    MM3DCreateCameraMatrix(const Origin, Front, Top: TMM3DVector): TMM3DMatrix4D;
  528. var
  529.     QM, M   : TMM3DMatrix4D;
  530. begin
  531.     M       := MM3DMatrixFromTranslation(MM3DVectorInvert(Origin));
  532.     QM      := MM3DMatrixInvert(MM3DMatrixFromCameraOrientation(Front,Top));
  533.     M       := MM3DMatrixMul(M,QM);
  534.     Result  := M;
  535. end;
  536. {-----------------------------------------------------------------------------}
  537. function    MM3DVectorInvert(const V: TMM3DVector): TMM3DVector;
  538. begin
  539.     with Result do
  540.     begin
  541.         x := -V.x;
  542.         y := -V.y;
  543.         z := -V.z;
  544.     end;
  545. end;
  546. {-----------------------------------------------------------------------------}
  547. function    MM3DMatrixInvert(const M: TMM3DMatrix4D): TMM3DMatrix4D;
  548. var
  549.     D   : TMM3DValue;
  550.     i, j: Integer;
  551. begin
  552.     D := MM3DMatrixDeterminant(M);
  553.     for i := 0 to 3 do
  554.         for j := 0 to 3 do
  555.             Result[j,i] := MM3DMatrixCofactor(M, i, j)/D;
  556. end;
  557. {-----------------------------------------------------------------------------}
  558. function    MM3DMatrixDeterminant(const M: TMM3DMatrix4D): TMM3DValue;
  559. begin
  560.     Result := M[0,0] * MM3DMatrixCofactor (M, 0, 0) +
  561.               M[0,1] * MM3DMatrixCofactor (M, 0, 1) +
  562.               M[0,2] * MM3DMatrixCofactor (M, 0, 2) +
  563.               M[0,3] * MM3DMatrixCofactor (M, 0, 3);
  564. end;
  565. {-----------------------------------------------------------------------------}
  566. function    MM3DMatrixCofactor(const M: TMM3DMatrix4D; i, j: Integer): TMM3DValue;
  567. var
  568.     i0, i1, i2, j0, j1, j2: Integer;
  569.     Det: TMM3DValue;
  570. begin
  571.     case i of
  572.         0: begin i0 := 1; i1 := 2; i2 := 3; end;
  573. 1: begin i0 := 0; i1 := 2; i2 := 3; end;
  574. 2: begin i0 := 0; i1 := 1; i2 := 3; end;
  575. 3: begin i0 := 0; i1 := 1; i2 := 2; end;
  576.     else
  577.         i0 := 0; i1 := 0; i2 := 0;
  578.     end;
  579. case j of
  580. 0: begin j0 := 1; j1 := 2; j2 := 3; end;
  581. 1: begin j0 := 0; j1 := 2; j2 := 3; end;
  582. 2: begin j0 := 0; j1 := 1; j2 := 3; end;
  583. 3: begin j0 := 0; j1 := 1; j2 := 2; end;
  584.     else
  585.         j0 := 0; j1 := 0; j2 := 0;
  586.     end;
  587.     Det := M[i0,j0] * (M[i1,j1] * M[i2,j2] - M[i1,j2] * M[i2,j1]) -
  588.            M[i0,j1] * (M[i1,j0] * M[i2,j2] - M[i1,j2] * M[i2,j0]) +
  589.            M[i0,j2] * (M[i1,j0] * M[i2,j1] - M[i1,j1] * M[i2,j0]);
  590.     if Odd(i + j) then
  591.         Result := -Det
  592.     else
  593.         Result := Det;
  594. end;
  595. {-----------------------------------------------------------------------------}
  596. function    MM3DVectorDegToRad(const R: TMM3DVector): TMM3DVector;
  597. begin
  598.     with Result do
  599.     begin
  600.         X := R.X/180*Pi;
  601.         Y := R.Y/180*Pi;
  602.         Z := R.Z/180*Pi;
  603.     end;
  604. end;
  605. {-----------------------------------------------------------------------------}
  606. function    MM3DVectorRadToDeg(const R: TMM3DVector): TMM3DVector;
  607. begin
  608.     with Result do
  609.     begin
  610.         X := R.X/Pi*180;
  611.         Y := R.Y/Pi*180;
  612.         Z := R.Z/Pi*180;
  613.     end;
  614. end;
  615. {-----------------------------------------------------------------------------}
  616. function    MM3DDegToRad(D: TMM3DValue): TMM3DValue;
  617. begin
  618.     Result := D/180*Pi;
  619. end;
  620. {-----------------------------------------------------------------------------}
  621. function    MM3DRadToDeg(R: TMM3DValue): TMM3DValue;
  622. begin
  623.     Result := R/Pi*180;
  624. end;
  625. {-----------------------------------------------------------------------------}
  626. function    MM3DMatrixFromCameraOrientation(const Front, Top: TMM3DVector): TMM3DMatrix4D;
  627. var
  628.     Axis: TMM3DVector;
  629.     A   : TMM3DValue;
  630.     F, T: TMM3DVector;
  631.     M   : TMM3DMatrix4D;
  632.     function    Transf(const V: TMM3DVector; const M: TMM3DMatrix4D): TMM3DVector;
  633.     begin
  634.         Result := MM3DVector3D(MM3DVectorTransform(V,M));
  635.     end;
  636. begin
  637.     F       := MM3DVectorNormalize(Front);
  638.     T       := MM3DVectorNormalize(Top);
  639.     // Put Y to its place
  640.     Axis    := MM3DVectorCrossProduct(YUnit,T);
  641.     A       := ArcCos(MM3DVectorDotProduct(YUnit,T));
  642.     if Round(A/Pi*180) > 178 then
  643.     begin
  644.         Axis := ZUnit;
  645.     end;
  646.     Result  := MM3DMatrixFromRotation(Axis,A);
  647.     M       := MM3DMatrixInvert(Result);
  648.     T       := Transf(T,M);
  649.     F       := MM3DVectorNormalize(Transf(F,M));
  650.     // Put Z to its place
  651.     Axis    := MM3DVectorCrossProduct(ZUnit,F);
  652.     A       := ArcCos(MM3DVectorDotProduct(ZUnit,F));
  653.     if Round(A/Pi*180) > 178 then
  654.     begin
  655.         Axis := YUnit;
  656.     end;
  657.     Result  := MM3DMatrixMul(MM3DMatrixFromRotation(Axis,A),Result);
  658. end;
  659. {-----------------------------------------------------------------------------}
  660. function    MM3DVectorEqual(const V1, V2: TMM3DVector): Boolean;
  661. begin
  662.     Result := GlobalCmpMem(V1,V2,SizeOf(V1));
  663. end;
  664. {== TMMVector3D =========================================================}
  665. procedure   TMMVector3D.SetComp(Index: Integer; Value: TMM3DValue);
  666. begin
  667.     case Index of
  668.         0: if FVector.x <> Value then FVector.x := Value else Exit;
  669.         1: if FVector.y <> Value then FVector.y := Value else Exit;
  670.         2: if FVector.z <> Value then FVector.z := Value else Exit;
  671.     end;
  672.     Changed;
  673. end;
  674. {-- TMMVector3D ---------------------------------------------------------}
  675. function    TMMVector3D.GetComp(Index: Integer): TMM3DValue;
  676. begin
  677.     Result := 0;
  678.     case Index of
  679.         0: Result := FVector.x;
  680.         1: Result := FVector.y;
  681.         2: Result := FVector.z;
  682.     end;
  683. end;
  684. {-- TMMVector3D ---------------------------------------------------------}
  685. procedure   TMMVector3D.SetAsVector(const Value: TMM3DVector);
  686. begin
  687.     if not MM3DVectorEqual(FVector,Value) then
  688.     begin
  689.         FVector := Value;
  690.         Changed;
  691.     end;
  692. end;
  693. {-- TMMVector3D ---------------------------------------------------------}
  694. procedure   TMMVector3D.Assign(Source: TPersistent);
  695. begin
  696.     if Source is TMMVector3D then
  697.         AsVector := (Source as TMMVector3D).AsVector
  698.     else
  699.         inherited Assign(Source);
  700. end;
  701. {== TMMMatrix3D ==============================================================}
  702. procedure   TMMMatrix3D.SetMatrix(const Value: TMM3DMatrix4D);
  703. begin
  704.     FMatrix := Value;
  705.     Changed;
  706. end;
  707. {-- TMMMatrix3D --------------------------------------------------------------}
  708. procedure   TMMMatrix3D.WriteMatrix(Writer: TWriter);
  709. var
  710.     i, j: Integer;
  711. begin
  712.     Writer.WriteListBegin;
  713.     for i := 0 to 3 do
  714.         for j := 0 to 3 do
  715.             Writer.WriteFloat(FMatrix[i,j]);
  716.     Writer.WriteListEnd;
  717. end;
  718. {-- TMMMatrix3D --------------------------------------------------------------}
  719. procedure   TMMMatrix3D.ReadMatrix(Reader: TReader);
  720. var
  721.     i, j: Integer;
  722. begin
  723.     Reader.ReadListBegin;
  724.     for i := 0 to 3 do
  725.         for j := 0 to 3 do
  726.             FMatrix[i,j] := Reader.ReadFloat;
  727.     Reader.ReadListEnd;
  728. end;
  729. {-- TMMMatrix3D --------------------------------------------------------------}
  730. function    TMMMatrix3D.GetCell(Row, Col: Integer): TMM3DValue;
  731. begin
  732.     Result := FMatrix[Row,Col];
  733. end;
  734. {-- TMMMatrix3D --------------------------------------------------------------}
  735. procedure   TMMMatrix3D.SetCell(Row, Col: Integer; Value: TMM3DValue);
  736. begin
  737.     FMatrix[Row,Col] := Value;
  738.     Changed;
  739. end;
  740. {-- TMMMatrix3D --------------------------------------------------------------}
  741. procedure   TMMMatrix3D.DefineProperties(Filer: TFiler);
  742. begin
  743.     inherited DefineProperties(Filer);
  744.     Filer.DefineProperty('Data',ReadMatrix,WriteMatrix,True);
  745. end;
  746. {-- TMMMatrix3D --------------------------------------------------------------}
  747. function    TMMMatrix3D.VectorTransform(const V: TMM3DVector): TMM3DVector4D;
  748. begin
  749.     Result := MM3DVectorTransform(V,FMatrix);
  750. end;
  751. {-- TMMMatrix3D --------------------------------------------------------------}
  752. function    TMMMatrix3D.InverseVectorTransform(const V: TMM3DVector): TMM3DVector4D;
  753. var
  754.     M: TMM3DMatrix4D;
  755. begin
  756.     M := MM3DMatrixInvert(FMatrix);
  757.     Result := MM3DVectorTransform(V,M);
  758. end;
  759. {-- TMMMatrix3D --------------------------------------------------------------}
  760. procedure   TMMMatrix3D.Assign(Source: TPersistent);
  761. begin
  762.     if Source is TMMMatrix3D then
  763.         AsMatrix := (Source as TMMMatrix3D).AsMatrix
  764.     else
  765.         inherited Assign(Source);
  766. end;
  767. initialization
  768.     White       := MM3DCreateColorRGB(1,1,1);
  769.     Red         := MM3DCreateColorRGB(0.5,0,0);
  770.     Green       := MM3DCreateColorRGB(0,0.5,0);
  771.     Blue        := MM3DCreateColorRGB(0,0,0.5);
  772.     LightRed    := MM3DCreateColorRGB(1,0,0);
  773.     LightGreen  := MM3DCreateColorRGB(0,1,0);
  774.     LightBlue   := MM3DCreateColorRGB(0,0,1);
  775.     Yellow      := MM3DCreateColorRGB(1,1,0);
  776.     Black       := MM3DCreateColorRGB(0,0,0);
  777. end.