Subversion Repositories spacemission

Rev

Blame | Last modification | View Log | RSS feed

  1. unit D3DUtils;
  2.  
  3. interface
  4.  
  5. {$INCLUDE DelphiXcfg.inc}
  6.  
  7. uses
  8.   Windows, Math,
  9. {$IFDEF StandardDX}
  10.   {$IFDEF VER14UP} DXTypes, {$ENDIF} Direct3D, DirectDraw;
  11. {$ELSE}
  12.   DirectX;
  13. {$ENDIF}
  14.  
  15. const
  16.   g_PI = 3.14159265358979323846; // Pi
  17.   g_Uhel = g_PI / 180;
  18.   g_2_PI = 6.28318530717958623200; // 2 * Pi
  19.   g_PI_DIV_2 = 1.57079632679489655800; // Pi / 2
  20.   g_PI_DIV_4 = 0.78539816339744827900; // Pi / 4
  21.   g_INV_PI = 0.31830988618379069122; // 1 / Pi
  22.   g_DEGTORAD = 0.01745329251994329547; // Degrees to Radians
  23.   g_RADTODEG = 57.29577951308232286465; // Radians to Degrees
  24.   g_HUGE = 1.0E+38; // Huge number for FLOAT
  25.   g_EPSILON = 1.0E-5; // Tolerance for FLOATs
  26.  
  27. type
  28.   TD2DVector = packed record
  29.     X, Y: Single;
  30.   end;
  31.   TD3DHVector = packed record
  32.     X, Y, Z, W: Single;
  33.   end;
  34.   TQuaternion = packed record
  35.     case Integer of
  36.       0: (X, Y, Z, W: Single); //like TD3DHVector
  37.       1: (
  38.         V: TD3DVector;
  39.         );
  40.   end;
  41. function ProjectionMatrix(near_plane, far_plane, fov_horiz, fov_vert: real): TD3DMatrix; {$IFDEF VER9UP}inline; {$ENDIF}
  42. //--------------------------
  43. // 3D Vector
  44. //--------------------------
  45. function MakeD3DVector(x, y, z: TD3DValue): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  46. function MakeD2DVector(x, y: TD3DValue): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  47. function MakeD3DVertex(hv, nv: TD3DVector; tu, tv: TD3DValue): TD3DVertex; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  48. function MakeD3DVertex(hx, hy, hz, nx, ny, nz, tu, tv: TD3DValue): TD3DVertex; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  49. function MakeD3DLVertex(hv: TD3DVector; col, sp: DWORD; tu, tv: TD3DValue): TD3DLVertex; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  50. function MakeD3DLVertex(hx, hy, hz: TD3DValue; col, sp: DWORD; tu, tv: TD3DValue): TD3DLVertex; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  51. function MakeD3DTLVertex(hx, hy, hz, rhw: TD3DValue; col, sp: DWORD; tu, tv: TD3DValue): TD3DTLVERTEX; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  52. function MakeD3DTLVertex(hv: TD3DVector; rhw: TD3DValue; col, sp: DWORD; tu, tv: TD3DValue): TD3DTLVERTEX; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  53. function Vector2RGBA(const v: TD3DVector; fHeight: Single): DWord; {$IFDEF VER9UP}inline; {$ENDIF}
  54. function VectorToRGB(NormalVector: TD3DVector): DWORD; {$IFDEF VER9UP}inline; {$ENDIF}
  55. //--------------------------
  56. // 3D Vector
  57. //--------------------------
  58. function Quaternion(_w, _x, _y, _z: Single): TQuaternion;
  59. function QuaternionLength(const a: TQuaternion): Single;
  60. function QuaternionNormalize(const a: TQuaternion): TQuaternion;
  61.  
  62. function D3DMath_VecNormalize(const v: TD3DVector): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  63. function D3DMath_VecViewScreenize(const v: TD3DHVector): TD3DHVector; {$IFDEF VER9UP}inline; {$ENDIF}
  64. function D3DMath_VecHeterogenize(const hv: TD3DHVector; _div: Boolean{$IFDEF VER4UP} = False{$ENDIF}): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  65. function D3DMath_VecHomogenize(const v: TD3DVector): TD3DHVector; {$IFDEF VER9UP}inline; {$ENDIF}
  66. function D3DMath_VecTransform(const a: TD3DHVector; const m: TD3DMATRIX): TD3DHVector; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  67. function D3DMath_VecTransform(const a: TD3DVector; const m: TD3DMATRIX): TD3DVector; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  68. function D3DMath_Vec3Length(const v: TD3DVector): TD3DValue; {$IFDEF VER9UP}inline; {$ENDIF}
  69. function D3DMath_Vec3LengthSq(const v: TD3DVector): TD3DValue; {$IFDEF VER9UP}inline; {$ENDIF}
  70. function D3DMath_Vec3Dot(const v1, v2: TD3DVector): TD3DValue; {$IFDEF VER9UP}inline; {$ENDIF}
  71. function D3DMath_Vec3Cross(const v1, v2: TD3DVector): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  72. function D3DMath_Vec3Add(const v1, v2: TD3DVector): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  73. function D3DMath_Vec3Subtract(const v1, v2: TD3DVector): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  74. function D3DMath_Vec3Minimize(const v1, v2: TD3DVector): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  75. function D3DMath_Vec3Maximize(const v1, v2: TD3DVector): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  76. function D3DMath_Vec3Scale(const v: TD3DVector; const s: TD3DValue): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  77. function D3DMath_Vec3Lerp(out vOut: TD3DVector; const v1, v2: TD3DVector; const s: TD3DValue): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  78.  
  79. function D3DMath_IsZero(a: Double; fTol: Double { = g_EPSILON}): Boolean; {$IFDEF VER9UP}inline; {$ENDIF}
  80.  
  81. procedure D3DMath_QuaternionFromRotation(var x, y, z, w: Double; const v: TD3DVector; fTheta: Double); overload; {$IFDEF VER9UP}inline; {$ENDIF}
  82. function D3DMath_QuaternionFromRotation(const axis: TD3DVector; const r: Double): TQuaternion; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  83. procedure D3DMath_RotationFromQuaternion(var v: TD3DVector; var fTheta: Double; x, y, z, w: Double); {$IFDEF VER9UP}inline; {$ENDIF}
  84. procedure D3DMath_QuaternionFromAngles(var x, y, z, w: Double; fYaw, fPitch, fRoll: Double); {$IFDEF VER9UP}inline; {$ENDIF}
  85. procedure D3DMath_MatrixFromQuaternion(var mat: TD3DMatrix; x, y, z, w: Double); overload; {$IFDEF VER9UP}inline; {$ENDIF}
  86. function D3DMath_MatrixFromQuaternion(q: TQuaternion): TD3DMatrix; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  87. procedure D3DMath_QuaternionFromMatrix(var x, y, z, w: Double; var mat: TD3DMatrix); {$IFDEF VER9UP}inline; {$ENDIF}
  88. procedure D3DMath_QuaternionMultiply(var Qx, Qy, Qz, Qw: Double; Ax, Ay, Az, Aw, Bx, By, Bz, Bw: Double); overload; {$IFDEF VER9UP}inline; {$ENDIF}
  89. function D3DMath_QuaternionMultiply(a, b: TQuaternion): TQuaternion; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  90. procedure D3DMath_QuaternionSlerp(var Qx, Qy, Qz, Qw: Double; Ax, Ay, Az, Aw, Bx, By, Bz, Bw, fAlpha: Double); overload; {$IFDEF VER9UP}inline; {$ENDIF}
  91. function D3DMath_QuaternionSlerp(A, B: TQuaternion; fAlpha: Double): TQuaternion; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  92.  
  93. procedure D3DUtil_InitSurfaceDesc(var ddsd: TDDSurfaceDesc2; dwFlags, dwCaps: DWORD); {$IFDEF VER9UP}inline; {$ENDIF}
  94. procedure D3DUtil_InitMaterial(var mtrl: TD3DMaterial7; r, g, b, a: Double); {$IFDEF VER9UP}inline; {$ENDIF}
  95. procedure D3DUtil_InitLight(var light: TD3DLight7; ltType: TD3DLightType; x, y, z: Double); {$IFDEF VER9UP}inline; {$ENDIF}
  96.  
  97. procedure D3DMath_MatrixMultiply(var q: TD3DMatrix; const a, b: TD3DMatrix); overload;
  98. function D3DMath_MatrixMultiply(const a, b: TD3DMatrix): TD3DMatrix; overload;
  99. function D3DMath_MatrixInvert(var q: TD3DMatrix; const a: TD3DMatrix): HResult; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  100. function D3DMath_MatrixInvert(const a: TD3DMatrix): TD3DMatrix; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  101. function D3DMath_VectorMatrixMultiply(var vDest: TD3DVector; const vSrc: TD3DVector; const mat: TD3DMatrix): HResult; {$IFDEF VER9UP}inline; {$ENDIF}
  102. function D3DMath_VertexMatrixMultiply(var vDest: TD3DVertex; const vSrc: TD3DVertex; const mat: TD3DMatrix): HResult; {$IFDEF VER9UP}inline; {$ENDIF}
  103. procedure D3DUtil_SetIdentityMatrix(out m: TD3DMatrix); overload; {$IFDEF VER9UP}inline; {$ENDIF}
  104. function D3DUtil_SetIdentityMatrix: TD3DMatrix; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  105. function D3DUtil_SetScaleMatrix(const x, y, z: Single): TD3DMatrix; {$IFDEF VER9UP}inline; {$ENDIF}
  106. function D3DUtil_SetViewMatrix(var mat: TD3DMatrix; const vFrom, vAt, vWorldUp: TD3DVector): HResult; {$IFDEF VER9UP}inline; {$ENDIF}
  107. function D3DUtil_SetProjectionMatrix(var mat: TD3DMatrix; fFOV, fAspect, fNearPlane, fFarPlane: Double): HResult; {$IFDEF VER9UP}inline; {$ENDIF}
  108. procedure D3DUtil_SetRotateXMatrix(var mat: TD3DMatrix; fRads: Double); overload; {$IFDEF VER9UP}inline; {$ENDIF}
  109. function D3DUtil_SetRotateXMatrix(fRads: Double): TD3DMatrix; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  110. procedure D3DUtil_SetRotateYMatrix(var mat: TD3DMatrix; fRads: Double); overload; {$IFDEF VER9UP}inline; {$ENDIF}
  111. function D3DUtil_SetRotateYMatrix(fRads: Double): TD3DMatrix; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  112. procedure D3DUtil_SetRotateZMatrix(var mat: TD3DMatrix; fRads: Double); overload; {$IFDEF VER9UP}inline; {$ENDIF}
  113. function D3DUtil_SetRotateZMatrix(fRads: Double): TD3DMatrix; overload; {$IFDEF VER9UP}inline; {$ENDIF}
  114. procedure D3DUtil_SetRotationMatrix(var mat: TD3DMatrix; var vDir: TD3DVector; fRads: Double); {$IFDEF VER9UP}inline; {$ENDIF}
  115. function D3DUtil_SetRotationMatrixByX(const a: TD3DVector; const r: Double): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  116. function D3DUtil_SetRotationMatrixByY(const a: TD3DVector; const r: Double): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  117. function D3DUtil_SetRotationMatrixByZ(const a: TD3DVector; const r: Double): TD3DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  118.  
  119. function D3DCOLOR_ARGB(a, r, g, b: Cardinal): TD3DColor; {$IFDEF VER9UP}inline; {$ENDIF}
  120. function D3DCOLOR_RGBA(r, g, b, a: Cardinal): TD3DColor; {$IFDEF VER9UP}inline; {$ENDIF}
  121. function D3DCOLOR_XRGB(r, g, b: Cardinal): TD3DColor; {$IFDEF VER9UP}inline; {$ENDIF}
  122. function D3DCOLOR_COLORVALUE(r, g, b, a: Single): TD3DColor; {$IFDEF VER9UP}inline; {$ENDIF}
  123.  
  124. // simple D2D operation
  125.  
  126. function D2DMath_VecAdd(const a: TD2DVector; const b: TD2DVector): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  127. function D2DMath_VecSub(const a: TD2DVector; const b: TD2DVector): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  128. function D2DMath_VecDotProduct(const a, b: TD2DVector): Single; {$IFDEF VER9UP}inline; {$ENDIF}
  129. function D2DMath_VecDistance(const a, b: TD2DVector): Single; {$IFDEF VER9UP}inline; {$ENDIF}
  130. function D2DMath_VecLength(const a: TD2DVector): Single; {$IFDEF VER9UP}inline; {$ENDIF}
  131. function D2DMath_VecNormalize(const a: TD2DVector): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  132. function D2DMath_VecToAngle(const a: TD2DVector): Double; {$IFDEF VER9UP}inline; {$ENDIF}
  133. function D2DMath_VecRot(const a: TD2DVector; const angle: Double): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  134. function D2DMath_VecScale(const a: TD2DVector; const scale: Double): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  135. function D2DMath_VecChangeLength(const a: TD2DVector; const k: Single): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  136. function D2DMath_VecLookAt(const pos: TD2DVector; const target: TD2DVector; const k: Single): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  137. function D2DMath_VecRandom2D(const k: Single): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  138.  
  139. function D2DMath_VecLerp(const a: TD2DVector; const b: TD2DVector; const rate: Single): TD2DVector; {$IFDEF VER9UP}inline; {$ENDIF}
  140.  
  141. implementation
  142.  
  143. //function RSin(val: Integer): Double; {$IFDEF VER9UP}inline; {$ENDIF}
  144. //begin
  145. //  Result := Sin(val / 2048.0 * Pi);
  146. //end;
  147. //
  148. //function RCos(val: Integer): Double; {$IFDEF VER9UP}inline; {$ENDIF}
  149. //begin
  150. //  Result := Cos(val / 2048.0 * Pi);
  151. //end;
  152.  
  153. function Quaternion(_w, _x, _y, _z: Single): TQuaternion;
  154. begin
  155.   Result.W := _w;
  156.   Result.X := _x;
  157.   Result.Y := _y;
  158.   Result.Z := _z;
  159. end;
  160.  
  161. function QuaternionLength(const a: TQuaternion): Single;
  162. begin
  163.   Result := Sqrt(a.w * a.w + a.x * a.x + a.y * a.y + a.z * a.z);
  164. end;
  165.  
  166. function QuaternionNormalize(const a: TQuaternion): TQuaternion;
  167. var
  168.   len: Single;
  169. begin
  170.   len := QuaternionLength(a);
  171.   if len = 0.0 then
  172.   begin
  173.     Result := Quaternion(1, 0, 0, 0);
  174.     Exit;
  175.   end;
  176.   Result.x := a.X / len;
  177.   Result.y := a.Y / len;
  178.   Result.z := a.Z / len;
  179.   Result.w := a.W / len;
  180. end;
  181.  
  182. function GetMatrixFromQuaternion(const a: TQuaternion): TD3DMatrix;
  183. begin
  184.  
  185. end;
  186.  
  187.  
  188. function D3DCOLOR_ARGB(a, r, g, b: Cardinal): TD3DColor;
  189. begin
  190.   Result := (a shl 24) or (r shl 16) or (g shl 8) or b;
  191. end;
  192.  
  193. function D3DCOLOR_RGBA(r, g, b, a: Cardinal): TD3DColor;
  194. begin
  195.   Result := D3DCOLOR_ARGB(a, r, g, b);
  196. end;
  197.  
  198. function D3DCOLOR_XRGB(r, g, b: Cardinal): TD3DColor;
  199. begin
  200.   Result := D3DCOLOR_ARGB($FF, r, g, b);
  201. end;
  202.  
  203. function D3DCOLOR_COLORVALUE(r, g, b, a: Single): TD3DColor;
  204. begin
  205.   Result := D3DCOLOR_RGBA(Byte(Round(r * 255)), Byte(Round(g * 255)), Byte(Round(b * 255)), Byte(Round(a * 255)))
  206. end;
  207.  
  208. function MakeD3DVector(x, y, z: TD3DValue): TD3DVector;
  209. begin
  210.   Result.x := x;
  211.   Result.y := y;
  212.   Result.z := z;
  213. end;
  214.  
  215. function MakeD2DVector(x, y: TD3DValue): TD2DVector;
  216. begin
  217.   Result.x := x;
  218.   Result.y := y;
  219. end;
  220.  
  221. function MakeD3DVertex(hv, nv: TD3DVector; tu, tv: TD3DValue): TD3DVertex;
  222. begin
  223.   Result.x := hv.x;
  224.   Result.y := hv.y;
  225.   Result.z := hv.z;
  226.   Result.nx := nv.x;
  227.   Result.ny := nv.y;
  228.   Result.nz := nv.z;
  229.   Result.tu := tu;
  230.   Result.tv := tv;
  231. end;
  232.  
  233. function MakeD3DVertex(hx, hy, hz, nx, ny, nz, tu, tv: TD3DValue): TD3DVertex;
  234. begin
  235.   Result.x := hx;
  236.   Result.y := hy;
  237.   Result.z := hz;
  238.   Result.nx := nx;
  239.   Result.ny := ny;
  240.   Result.nz := nz;
  241.   Result.tu := tu;
  242.   Result.tv := tv;
  243. end;
  244.  
  245. function MakeD3DLVertex(hv: TD3DVector; col, sp: DWORD; tu, tv: TD3DValue): TD3DLVertex;
  246. begin
  247.   FillChar(Result, SizeOf(Result), 0);
  248.   Result.x := hv.x;
  249.   Result.y := hv.y;
  250.   Result.z := hv.z;
  251.   Result.color := col;
  252.   Result.specular := sp;
  253.   Result.tu := tu;
  254.   Result.tv := tv;
  255. end;
  256.  
  257. function MakeD3DLVertex(hx, hy, hz: TD3DValue; col, sp: DWORD; tu, tv: TD3DValue): TD3DLVertex;
  258. begin
  259.   FillChar(Result, SizeOf(Result), 0);
  260.   Result.x := hx;
  261.   Result.y := hy;
  262.   Result.z := hz;
  263.   Result.color := col;
  264.   Result.specular := sp;
  265.   Result.tu := tu;
  266.   Result.tv := tv;
  267. end;
  268.  
  269. function MakeD3DTLVertex(hx, hy, hz, rhw: TD3DValue; col, sp: DWORD; tu, tv: TD3DValue): TD3DTLVERTEX;
  270. begin
  271.   Result.sx := hx;
  272.   Result.sy := hy;
  273.   Result.sz := hz;
  274.   Result.dvRHW := rhw;
  275.   Result.color := col;
  276.   Result.specular := sp;
  277.   Result.tu := tu;
  278.   Result.tv := tv;
  279. end;
  280.  
  281. function MakeD3DTLVertex(hv: TD3DVector; rhw: TD3DValue; col, sp: DWORD; tu, tv: TD3DValue): TD3DTLVERTEX;
  282. begin
  283.   Result.sx := hv.x;
  284.   Result.sy := hv.y;
  285.   Result.sz := hv.z;
  286.   Result.dvRHW := rhw;
  287.   Result.color := col;
  288.   Result.specular := sp;
  289.   Result.tu := tu;
  290.   Result.tv := tv;
  291. end;
  292.  
  293. function Vector2RGBA(const v: TD3DVector; fHeight: Single): DWord;
  294. var
  295.   r, g, b, a: DWord;
  296. begin
  297.   r := Round(127.0 * v.x + 128.0);
  298.   g := Round(127.0 * v.y + 128.0);
  299.   b := Round(127.0 * v.z + 128.0);
  300.   a := Round(255.0 * fHeight);
  301.   Result := ((a shl 24) + (r shl 16) + (g shl 8) + (b shl 0));
  302. end;
  303.  
  304. function VectorToRGB(NormalVector: TD3DVector): DWORD;
  305. var dwR, dwG, dwB: DWORD;
  306. begin
  307.   dwR := Round(127 * NormalVector.x + 128);
  308.   dwG := Round(127 * NormalVector.y + 128);
  309.   dwB := Round(127 * NormalVector.z + 128);
  310.   Result := $FF000000 + dwR shl 16 + dwG shl 8 + dwB;
  311. end;
  312.  
  313. function ProjectionMatrix(near_plane, // distance to near clipping plane
  314.   far_plane, // distance to far clipping plane
  315.   fov_horiz, // horizontal field of view angle, in radians
  316.   fov_vert: real): TD3DMatrix; // vertical field of view angle, in radians
  317. var h, w, Q: real;
  318. begin
  319.   Fov_horiz := g_Uhel * Fov_horiz;
  320.   Fov_Vert := g_Uhel * Fov_Vert;
  321.  
  322.   w := cotan(fov_horiz * 0.5);
  323.   h := cotan(fov_vert * 0.5);
  324.   Q := far_plane / (far_plane - near_plane);
  325.  
  326.   result._11 := w;
  327.   result._22 := h;
  328.   result._33 := Q;
  329.   result._43 := -Q * near_plane;
  330.   result._34 := 1;
  331. end;
  332.    // end of ProjectionMatrix()
  333.  
  334. //--------------------------
  335. // 3D Vector
  336. //--------------------------
  337.  
  338. function D3DMath_VecNormalize(const v: TD3DVector): TD3DVector;
  339. var
  340.   len: Single;
  341. begin
  342.   len := D3DMath_Vec3Length(v);
  343.   if len = 0 then
  344.     FillChar(Result, SizeOf(Result), 0)
  345.   else
  346.   begin
  347.     Result.X := v.X / len;
  348.     Result.Y := v.Y / len;
  349.     Result.Z := v.Z / len;
  350.   end;
  351. end;
  352.  
  353. function D3DMath_VecViewScreenize(const v: TD3DHVector): TD3DHVector;
  354. begin
  355.   with Result do
  356.   begin
  357.     if v.W <> 0.0 then
  358.     begin
  359.       W := 1.0 / v.W;
  360.       X := v.X * W;
  361.       Y := v.Y * W;
  362.       Z := v.Z * W;
  363.     end;
  364.   end;
  365. end;
  366.  
  367. function D3DMath_VecHeterogenize(const hv: TD3DHVector; _div: Boolean): TD3DVector;
  368. var
  369.   d: Single;
  370. begin
  371.   if not _div then
  372.   begin
  373.     Result.x := hv.X;
  374.     Result.y := hv.Y;
  375.     Result.z := hv.Z;
  376.   end
  377.   else
  378.   begin
  379.     d := 1.0 / hv.w;
  380.     Result.x := hv.x * d;
  381.     Result.y := hv.y * d;
  382.     Result.z := hv.z * d;
  383.   end;
  384. end;
  385.  
  386. function D3DMath_VecHomogenize(const v: TD3DVector): TD3DHVector;
  387. begin
  388.   Move(v, result, Sizeof(TD3DVector));
  389.   result.W := 1.0;
  390. end;
  391.  
  392. function D3DMath_VecTransform(const a: TD3DHVector; const m: TD3DMATRIX): TD3DHVector;
  393. begin
  394.   result.X := a.X * m._11 + a.Y * m._21 + a.Z * m._31 + a.W * m._41;
  395.   result.Y := a.X * m._12 + a.Y * m._22 + a.Z * m._32 + a.W * m._42;
  396.   result.Z := a.X * m._13 + a.Y * m._23 + a.Z * m._33 + a.W * m._43;
  397.   result.W := a.X * m._14 + a.Y * m._24 + a.Z * m._34 + a.W * m._44;
  398. end;
  399.  
  400. function D3DMath_VecTransform(const a: TD3DVector; const m: TD3DMATRIX): TD3DVector;
  401. begin
  402.   result.X := a.X * m._11 + a.Y * m._21 + a.Z * m._31 + m._41;
  403.   result.Y := a.X * m._12 + a.Y * m._22 + a.Z * m._32 + m._42;
  404.   result.Z := a.X * m._13 + a.Y * m._23 + a.Z * m._33 + m._43;
  405. end;
  406.  
  407. function D3DMath_Vec3Length(const v: TD3DVector): TD3DValue;
  408. begin
  409.   with v do Result := Sqrt(Sqr(x) + Sqr(y) + Sqr(z));
  410. end;
  411.  
  412. function D3DMath_Vec3LengthSq(const v: TD3DVector): TD3DValue;
  413. begin
  414.   with v do Result := Sqr(x) + Sqr(y) + Sqr(z);
  415. end;
  416.  
  417. function D3DMath_Vec3Dot(const v1, v2: TD3DVector): TD3DValue;
  418. begin
  419.   Result := v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  420. end;
  421.  
  422. function D3DMath_Vec3Cross(const v1, v2: TD3DVector): TD3DVector;
  423. begin
  424.   Result.x := v1.y * v2.z - v1.z * v2.y;
  425.   Result.y := v1.z * v2.x - v1.x * v2.z;
  426.   Result.z := v1.x * v2.y - v1.y * v2.x;
  427. end;
  428.  
  429. function D3DMath_Vec3Add(const v1, v2: TD3DVector): TD3DVector;
  430. begin
  431.   Result.x := v1.x + v2.x;
  432.   Result.y := v1.y + v2.y;
  433.   Result.z := v1.z + v2.z;
  434. end;
  435.  
  436. function D3DMath_Vec3Subtract(const v1, v2: TD3DVector): TD3DVector;
  437. begin
  438.   Result.x := v1.x - v2.x;
  439.   Result.y := v1.y - v2.y;
  440.   Result.z := v1.z - v2.z;
  441. end;
  442.  
  443. // Minimize each component.  x = min(x1, x2), y = min(y1, y2)
  444.  
  445. function D3DMath_Vec3Minimize(const v1, v2: TD3DVector): TD3DVector;
  446. begin
  447.   if v1.x < v2.x then Result.x := v1.x else Result.x := v2.x;
  448.   if v1.y < v2.y then Result.y := v1.y else Result.y := v2.y;
  449.   if v1.z < v2.z then Result.z := v1.z else Result.z := v2.z;
  450. end;
  451.  
  452. // Maximize each component.  x = max(x1, x2), y = max(y1, y2)
  453.  
  454. function D3DMath_Vec3Maximize(const v1, v2: TD3DVector): TD3DVector;
  455. begin
  456.   if v1.x > v2.x then Result.x := v1.x else Result.x := v2.x;
  457.   if v1.y > v2.y then Result.y := v1.y else Result.y := v2.y;
  458.   if v1.z > v2.z then Result.z := v1.z else Result.z := v2.z;
  459. end;
  460.  
  461. function D3DMath_Vec3Scale(const v: TD3DVector; const s: TD3DValue): TD3DVector;
  462. begin
  463.   Result.x := v.x * s;
  464.   Result.y := v.y * s;
  465.   Result.z := v.z * s;
  466. end;
  467.  
  468. // Linear interpolation. V1 + s(V2-V1)
  469.  
  470. function D3DMath_Vec3Lerp(out vOut: TD3DVector; const v1, v2: TD3DVector; const s: TD3DValue): TD3DVector;
  471. begin
  472.   Result.x := v1.x + s * (v2.x - v1.x);
  473.   Result.y := v1.y + s * (v2.y - v1.y);
  474.   Result.z := v1.z + s * (v2.z - v1.z);
  475. end;
  476.  
  477. //-----------------------------------------------------------------------------
  478. // File: D3DMath.cpp
  479. //
  480. // Desc: Shortcut macros and functions for using DX objects
  481. //
  482. // Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
  483. //-----------------------------------------------------------------------------
  484.  
  485. function D3DMath_IsZero(a: Double; fTol: Double { = g_EPSILON}): Boolean;
  486. begin
  487.   if a < 0 then
  488.     Result := a >= -fTol
  489.   else
  490.     Result := a <= fTol;
  491. end;
  492.  
  493. //-----------------------------------------------------------------------------
  494. // Name: D3DMath_MatrixMultiply()
  495. // Desc: Does the matrix operation: [Q] = [A] * [B]. Note that the order of
  496. //       this operation was changed from the previous version of the DXSDK.
  497. //-----------------------------------------------------------------------------
  498.  
  499. procedure D3DMath_MatrixMultiply(var q: TD3DMatrix; const a, b: TD3DMatrix);
  500. type
  501.   PArrayD3DValue = ^TArrayD3DValue;
  502.   TArrayD3DValue = array[0..15] of TD3DValue;
  503. var
  504.   pA, pB, pQ: PArrayD3DValue;
  505.   i, j, k: Integer;
  506.   qq: TD3DMatrix;
  507. begin
  508.   FillChar(qq, SizeOf(qq), 0);
  509.  
  510.   pA := @a;
  511.   pB := @b;
  512.   pQ := @qq;
  513.   for i := 0 to 3 do
  514.     for j := 0 to 3 do
  515.       for k := 0 to 3 do
  516.         pQ[4 * i + j] := pQ[4 * i + j] + pA[4 * i + k] * pB[4 * k + j];
  517.   q := qq; {== protect of recurrence}
  518. end;
  519.  
  520. function D3DMath_MatrixMultiply(const a, b: TD3DMatrix): TD3DMatrix;
  521. begin
  522.   D3DMath_MatrixMultiply(Result, a, b);
  523. end;
  524.  
  525. //-----------------------------------------------------------------------------
  526. // Name: D3DMath_MatrixInvert()
  527. // Desc: Does the matrix operation: [Q] = inv[A]. Note: this function only
  528. //       works for matrices with [0 0 0 1] for the 4th column.
  529. //-----------------------------------------------------------------------------
  530.  
  531. function D3DMath_MatrixInvert(var q: TD3DMatrix; const a: TD3DMatrix): HResult;
  532. var
  533.   fDetInv: Double;
  534. begin
  535.   if (abs(a._44 - 1.0) > 0.001) or (abs(a._14) > 0.001) or (abs(a._24) > 0.001) or (abs(a._34) > 0.001) then
  536.   begin
  537.     Result := E_INVALIDARG;
  538.     Exit;
  539.   end;
  540.  
  541.   fDetInv := 1.0 / (a._11 * (a._22 * a._33 - a._23 * a._32) -
  542.     a._12 * (a._21 * a._33 - a._23 * a._31) +
  543.     a._13 * (a._21 * a._32 - a._22 * a._31));
  544.  
  545.   q._11 := fDetInv * (a._22 * a._33 - a._23 * a._32);
  546.   q._12 := -fDetInv * (a._12 * a._33 - a._13 * a._32);
  547.   q._13 := fDetInv * (a._12 * a._23 - a._13 * a._22);
  548.   q._14 := 0.0;
  549.  
  550.   q._21 := -fDetInv * (a._21 * a._33 - a._23 * a._31);
  551.   q._22 := fDetInv * (a._11 * a._33 - a._13 * a._31);
  552.   q._23 := -fDetInv * (a._11 * a._23 - a._13 * a._21);
  553.   q._24 := 0.0;
  554.  
  555.   q._31 := fDetInv * (a._21 * a._32 - a._22 * a._31);
  556.   q._32 := -fDetInv * (a._11 * a._32 - a._12 * a._31);
  557.   q._33 := fDetInv * (a._11 * a._22 - a._12 * a._21);
  558.   q._34 := 0.0;
  559.  
  560.   q._41 := -(a._41 * q._11 + a._42 * q._21 + a._43 * q._31);
  561.   q._42 := -(a._41 * q._12 + a._42 * q._22 + a._43 * q._32);
  562.   q._43 := -(a._41 * q._13 + a._42 * q._23 + a._43 * q._33);
  563.   q._44 := 1.0;
  564.  
  565.   Result := S_OK;
  566. end;
  567.  
  568. function D3DMath_MatrixInvert(const a: TD3DMatrix): TD3DMatrix;
  569. begin
  570.   if D3DMath_MatrixInvert(Result, a) <> S_OK then
  571.     FillChar(Result, SizeOf(Result), 0);
  572. end;
  573.  
  574. //-----------------------------------------------------------------------------
  575. // Name: D3DMath_VectorMatrixMultiply()
  576. // Desc: Multiplies a vector by a matrix
  577. //-----------------------------------------------------------------------------
  578.  
  579. function D3DMath_VectorMatrixMultiply(var vDest: TD3DVector; const vSrc: TD3DVector;
  580.   const mat: TD3DMatrix): HResult;
  581. var
  582.   x, y, z, w: Double;
  583. begin
  584.   x := vSrc.x * mat._11 + vSrc.y * mat._21 + vSrc.z * mat._31 + mat._41;
  585.   y := vSrc.x * mat._12 + vSrc.y * mat._22 + vSrc.z * mat._32 + mat._42;
  586.   z := vSrc.x * mat._13 + vSrc.y * mat._23 + vSrc.z * mat._33 + mat._43;
  587.   w := vSrc.x * mat._14 + vSrc.y * mat._24 + vSrc.z * mat._34 + mat._44;
  588.  
  589.   if abs(w) < g_EPSILON then
  590.   begin
  591.     Result := E_INVALIDARG;
  592.     Exit;
  593.   end;
  594.  
  595.   vDest.x := x / w;
  596.   vDest.y := y / w;
  597.   vDest.z := z / w;
  598.  
  599.   Result := S_OK;
  600. end;
  601.  
  602. //-----------------------------------------------------------------------------
  603. // Name: D3DMath_VertexMatrixMultiply()
  604. // Desc: Multiplies a vertex by a matrix
  605. //-----------------------------------------------------------------------------
  606.  
  607. function D3DMath_VertexMatrixMultiply(var vDest: TD3DVertex; const vSrc: TD3DVertex;
  608.   const mat: TD3DMatrix): HResult;
  609. var
  610.   pSrcVec, pDestVec: PD3DVector;
  611. begin
  612.   pSrcVec := @vSrc.x;
  613.   pDestVec := @vDest.x;
  614.  
  615.   Result := D3DMath_VectorMatrixMultiply(pDestVec^, pSrcVec^, mat);
  616.   if SUCCEEDED(Result) then
  617.   begin
  618.     pSrcVec := @vSrc.nx;
  619.     pDestVec := @vDest.nx;
  620.     Result := D3DMath_VectorMatrixMultiply(pDestVec^, pSrcVec^, mat);
  621.   end;
  622. end;
  623.  
  624. //-----------------------------------------------------------------------------
  625. // Name: D3DMath_QuaternionFromRotation()
  626. // Desc: Converts a normalized axis and angle to a unit quaternion.
  627. //-----------------------------------------------------------------------------
  628.  
  629. procedure D3DMath_QuaternionFromRotation(var x, y, z, w: Double;
  630.   const v: TD3DVector; fTheta: Double);
  631. begin
  632.   x := sin(fTheta / 2.0) * v.x;
  633.   y := sin(fTheta / 2.0) * v.y;
  634.   z := sin(fTheta / 2.0) * v.z;
  635.   w := cos(fTheta / 2.0);
  636. end;
  637.  
  638. function D3DMath_QuaternionFromRotation(const axis: TD3DVector; const r: Double): TQuaternion;
  639. var
  640. //  r: Integer;
  641.   a: TD3DVector;
  642. begin
  643. //  r := (t div 2) and $FFF;
  644.   a := VectorNormalize(axis);
  645.   Result.X := a.X * Sin(R);
  646.   Result.Y := a.Y * Sin(R);
  647.   Result.Z := a.Z * Sin(R);
  648.   Result.W := Cos(R);
  649. end;
  650.  
  651. //-----------------------------------------------------------------------------
  652. // Name: D3DMath_RotationFromQuaternion()
  653. // Desc: Converts a normalized axis and angle to a unit quaternion.
  654. //-----------------------------------------------------------------------------
  655.  
  656. procedure D3DMath_RotationFromQuaternion(var v: TD3DVector; var fTheta: Double;
  657.   x, y, z, w: Double);
  658. begin
  659.   fTheta := ArcCos(w) * 2.0;
  660.   v.x := x / sin(fTheta / 2.0);
  661.   v.y := y / sin(fTheta / 2.0);
  662.   v.z := z / sin(fTheta / 2.0);
  663. end;
  664.  
  665. //-----------------------------------------------------------------------------
  666. // Name: D3DMath_QuaternionFromAngles()
  667. // Desc: Converts euler angles to a unit quaternion.
  668. //-----------------------------------------------------------------------------
  669.  
  670. procedure D3DMath_QuaternionFromAngles(var x, y, z, w: Double; fYaw, fPitch, fRoll: Double);
  671. var
  672.   fSinYaw, fSinPitch, fSinRoll, fCosYaw, fCosPitch, fCosRoll: Double;
  673. begin
  674.   fSinYaw := sin(fYaw / 2.0);
  675.   fSinPitch := sin(fPitch / 2.0);
  676.   fSinRoll := sin(fRoll / 2.0);
  677.   fCosYaw := cos(fYaw / 2.0);
  678.   fCosPitch := cos(fPitch / 2.0);
  679.   fCosRoll := cos(fRoll / 2.0);
  680.  
  681.   x := fSinRoll * fCosPitch * fCosYaw - fCosRoll * fSinPitch * fSinYaw;
  682.   y := fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
  683.   z := fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
  684.   w := fCosRoll * fCosPitch * fCosYaw + fSinRoll * fSinPitch * fSinYaw;
  685. end;
  686.  
  687. //-----------------------------------------------------------------------------
  688. // Name: D3DMath_MatrixFromQuaternion()
  689. // Desc: Converts a unit quaternion into a rotation matrix.
  690. //-----------------------------------------------------------------------------
  691.  
  692. procedure D3DMath_MatrixFromQuaternion(var mat: TD3DMatrix; x, y, z, w: Double);
  693. var
  694.   xx, yy, zz, xy, xz, yz, wx, wy, wz: Double;
  695. begin
  696.   xx := x * x; yy := y * y; zz := z * z;
  697.   xy := x * y; xz := x * z; yz := y * z;
  698.   wx := w * x; wy := w * y; wz := w * z;
  699.  
  700.   mat._11 := 1 - 2 * (yy + zz);
  701.   mat._12 := 2 * (xy - wz);
  702.   mat._13 := 2 * (xz + wy);
  703.  
  704.   mat._21 := 2 * (xy + wz);
  705.   mat._22 := 1 - 2 * (xx + zz);
  706.   mat._23 := 2 * (yz - wx);
  707.  
  708.   mat._31 := 2 * (xz - wy);
  709.   mat._32 := 2 * (yz + wx);
  710.   mat._33 := 1 - 2 * (xx + yy);
  711.  
  712.   mat._14 := 0.0; mat._24 := 0.0; mat._34 := 0.0;
  713.   mat._41 := 0.0; mat._42 := 0.0; mat._43 := 0.0;
  714.   mat._44 := 1.0;
  715. end;
  716.  
  717. function D3DMath_MatrixFromQuaternion(q: TQuaternion): TD3DMatrix;
  718. begin
  719.   D3DMath_MatrixFromQuaternion(Result, q.X, q.Y, q.Z, q.W)
  720. end;
  721.  
  722. //-----------------------------------------------------------------------------
  723. // Name: D3DMath_QuaternionFromMatrix()
  724. // Desc: Converts a rotation matrix into a unit quaternion.
  725. //-----------------------------------------------------------------------------
  726.  
  727. procedure D3DMath_QuaternionFromMatrix(var x, y, z, w: Double; var mat: TD3DMatrix);
  728. var
  729.   s: Double;
  730.   xx, yy, zz, xy, xz, yz, wx, wy, wz: Double;
  731. begin
  732.   if (mat._11 + mat._22 + mat._33 > 0.0) then
  733.   begin
  734.     s := sqrt(mat._11 + mat._22 + mat._33 + mat._44);
  735.  
  736.     x := (mat._23 - mat._32) / (2 * s);
  737.     y := (mat._31 - mat._13) / (2 * s);
  738.     z := (mat._12 - mat._21) / (2 * s);
  739.     w := 0.5 * s;
  740.   end;
  741.  
  742.   xx := x * x; yy := y * y; zz := z * z;
  743.   xy := x * y; xz := x * z; yz := y * z;
  744.   wx := w * x; wy := w * y; wz := w * z;
  745.  
  746.   mat._11 := 1 - 2 * (yy + zz);
  747.   mat._12 := 2 * (xy - wz);
  748.   mat._13 := 2 * (xz + wy);
  749.  
  750.   mat._21 := 2 * (xy + wz);
  751.   mat._22 := 1 - 2 * (xx + zz);
  752.   mat._23 := 2 * (yz - wx);
  753.  
  754.   mat._31 := 2 * (xz - wy);
  755.   mat._32 := 2 * (yz + wx);
  756.   mat._33 := 1 - 2 * (xx + yy);
  757.  
  758.   mat._14 := 0.0; mat._24 := 0.0; mat._34 := 0.0;
  759.   mat._41 := 0.0; mat._42 := 0.0; mat._43 := 0.0;
  760.   mat._44 := 1.0;
  761. end;
  762.  
  763. //-----------------------------------------------------------------------------
  764. // Name: D3DMath_QuaternionMultiply()
  765. // Desc: Mulitples two quaternions together as in {Q} = {A} * {B}.
  766. //-----------------------------------------------------------------------------
  767.  
  768. procedure D3DMath_QuaternionMultiply(var Qx, Qy, Qz, Qw: Double;
  769.   Ax, Ay, Az, Aw, Bx, By, Bz, Bw: Double);
  770. var
  771.   Dx, Dy, Dz, Dw: Double;
  772. begin
  773.   Dx := Ax * Bw + Ay * Bz - Az * By + Aw * Bx;
  774.   Dy := -Ax * Bz + Ay * Bw + Az * Bx + Aw * By;
  775.   Dz := Ax * By - Ay * Bx + Az * Bw + Aw * Bz;
  776.   Dw := -Ax * Bx - Ay * By - Az * Bz + Aw * Bw;
  777.  
  778.   Qx := Dx; Qy := Dy; Qz := Dz; Qw := Dw;
  779. end;
  780.  
  781. function D3DMath_QuaternionMultiply(a, b: TQuaternion): TQuaternion;
  782. var
  783.   Qx, Qy, Qz, Qw: Double;
  784. begin
  785.   D3DMath_QuaternionMultiply(Qx, Qy, Qz, Qw, A.x, A.y, A.z, A.w, B.x, B.y, B.z, B.w);
  786.   Result.X := Qx;
  787.   Result.Y := Qy;
  788.   Result.Z := Qz;
  789.   Result.W := Qw;
  790. end;
  791.  
  792. //-----------------------------------------------------------------------------
  793. // Name: D3DMath_SlerpQuaternions()
  794. // Desc: Compute a quaternion which is the spherical linear interpolation
  795. //       between two other quaternions by dvFraction.
  796. //-----------------------------------------------------------------------------
  797.  
  798. procedure D3DMath_QuaternionSlerp(var Qx, Qy, Qz, Qw: Double;
  799.   Ax, Ay, Az, Aw, Bx, By, Bz, Bw, fAlpha: Double);
  800. var
  801.   fCosTheta: Double;
  802.   fBeta: Double;
  803.   fTheta: Double;
  804. begin
  805.   // Compute dot product (equal to cosine of the angle between quaternions)
  806.   fCosTheta := Ax * Bx + Ay * By + Az * Bz + Aw * Bw;
  807.  
  808.   // Check angle to see if quaternions are in opposite hemispheres
  809.   if fCosTheta < 0.0 then
  810.   begin
  811.     // If so, flip one of the quaterions
  812.     fCosTheta := -fCosTheta;
  813.     Bx := -Bx; By := -By; Bz := -Bz; Bw := -Bw;
  814.   end;
  815.  
  816.   // Set factors to do linear interpolation, as a special case where the
  817.   // quaternions are close together.
  818.   fBeta := 1.0 - fAlpha;
  819.  
  820.   // If the quaternions aren't close, proceed with spherical interpolation
  821.   if 1.0 - fCosTheta > 0.001 then
  822.   begin
  823.     fTheta := arccos(fCosTheta);
  824.  
  825.     fBeta := sin(fTheta * fBeta) / sin(fTheta);
  826.     fAlpha := sin(fTheta * fAlpha) / sin(fTheta);
  827.   end;
  828.  
  829.   // Do the interpolation
  830.   Qx := fBeta * Ax + fAlpha * Bx;
  831.   Qy := fBeta * Ay + fAlpha * By;
  832.   Qz := fBeta * Az + fAlpha * Bz;
  833.   Qw := fBeta * Aw + fAlpha * Bw;
  834. end;
  835.  
  836. function D3DMath_QuaternionSlerp(A, B: TQuaternion; fAlpha: Double): TQuaternion;
  837. var
  838.   Qx, Qy, Qz, Qw: Double;
  839. begin
  840.   D3DMath_QuaternionSlerp(Qx, Qy, Qz, Qw, A.x, A.y, A.z, A.w, B.x, B.y, B.z, B.w, fAlpha);
  841.   Result.X := Qx;
  842.   Result.Y := Qy;
  843.   Result.Z := Qz;
  844.   Result.W := Qw;
  845. end;
  846.  
  847. //-----------------------------------------------------------------------------
  848. // File: D3DUtil.cpp
  849. //
  850. // Desc: Shortcut macros and functions for using DX objects
  851. //
  852. //
  853. // Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
  854. //-----------------------------------------------------------------------------
  855.  
  856. //-----------------------------------------------------------------------------
  857. // Name: D3DUtil_InitSurfaceDesc()
  858. // Desc: Helper function called to build a DDSURFACEDESC2 structure,
  859. //       typically before calling CreateSurface() or GetSurfaceDesc()
  860. //-----------------------------------------------------------------------------
  861.  
  862. procedure D3DUtil_InitSurfaceDesc(var ddsd: TDDSurfaceDesc2; dwFlags, dwCaps: DWORD);
  863. begin
  864.   FillChar(ddsd, SizeOf(ddsd), 0);
  865.   ddsd.dwSize := SizeOf(ddsd);
  866.   ddsd.dwFlags := dwFlags;
  867.   ddsd.ddsCaps.dwCaps := dwCaps;
  868.   ddsd.ddpfPixelFormat.dwSize := SizeOf(ddsd.ddpfPixelFormat);
  869. end;
  870.  
  871. //-----------------------------------------------------------------------------
  872. // Name: D3DUtil_InitMaterial()
  873. // Desc: Helper function called to build a D3DMATERIAL7 structure
  874. //-----------------------------------------------------------------------------
  875.  
  876. procedure D3DUtil_InitMaterial(var mtrl: TD3DMaterial7; r, g, b, a: Double);
  877. begin
  878.   FillChar(mtrl, SizeOf(mtrl), 0);
  879.   mtrl.dcvDiffuse.r := r; mtrl.dcvAmbient.r := r;
  880.   mtrl.dcvDiffuse.g := g; mtrl.dcvAmbient.g := g;
  881.   mtrl.dcvDiffuse.b := b; mtrl.dcvAmbient.b := b;
  882.   mtrl.dcvDiffuse.a := a; mtrl.dcvAmbient.a := a;
  883. end;
  884.  
  885. //-----------------------------------------------------------------------------
  886. // Name: D3DUtil_InitLight()
  887. // Desc: Initializes a D3DLIGHT7 structure
  888. //-----------------------------------------------------------------------------
  889.  
  890. procedure D3DUtil_InitLight(var light: TD3DLight7; ltType: TD3DLightType; x, y, z: Double);
  891. begin
  892.   FillChar(light, SizeOf(light), 0);
  893.   light.dltType := ltType;
  894.   light.dcvDiffuse.r := 1.0;
  895.   light.dcvDiffuse.g := 1.0;
  896.   light.dcvDiffuse.b := 1.0;
  897.   light.dcvSpecular := light.dcvDiffuse;
  898.   light.dvPosition.x := x; light.dvDirection.x := x;
  899.   light.dvPosition.y := y; light.dvDirection.y := y;
  900.   light.dvPosition.z := z; light.dvDirection.z := z;
  901.   light.dvAttenuation0 := 1.0;
  902.   light.dvRange := D3DLIGHT_RANGE_MAX;
  903. end;
  904.  
  905. procedure D3DUtil_SetIdentityMatrix(out m: TD3DMatrix);
  906. begin
  907.   m._12 := 0; m._13 := 0; m._14 := 0; m._21 := 0; m._23 := 0; m._24 := 0;
  908.   m._31 := 0; m._32 := 0; m._34 := 0; m._41 := 0; m._42 := 0; m._43 := 0;
  909.   m._11 := 1; m._22 := 1; m._33 := 1; m._44 := 1;
  910. end;
  911.  
  912. function D3DUtil_SetIdentityMatrix: TD3DMatrix;
  913. begin
  914.   D3DUtil_SetIdentityMatrix(Result);
  915. end;
  916.  
  917. function D3DUtil_SetScaleMatrix(const x, y, z: Single): TD3DMatrix;
  918. begin
  919.   with Result do
  920.   begin
  921.     _11 := x; _12 := 0; _13 := 0; _14 := 0;
  922.     _21 := 0; _22 := y; _23 := 0; _24 := 0;
  923.     _31 := 0; _32 := 0; _33 := z; _34 := 0;
  924.     _41 := 0; _42 := 0; _43 := 0; _44 := 1;
  925.   end;
  926. end;
  927.  
  928. //-----------------------------------------------------------------------------
  929. // Name: D3DUtil_SetViewMatrix()
  930. // Desc: Given an eye point, a lookat point, and an up vector, this
  931. //       function builds a 4x4 view matrix.
  932. //-----------------------------------------------------------------------------
  933.  
  934. function D3DUtil_SetViewMatrix(var mat: TD3DMatrix; const vFrom, vAt, vWorldUp: TD3DVector): HResult;
  935. var
  936.   vView: TD3DVector;
  937.   fLength: Double;
  938.   fDotProduct: Double;
  939.   vUp: TD3DVector;
  940.   vRight: TD3DVector;
  941. begin
  942.   // Get the z basis vector, which points straight ahead. This is the
  943.   // difference from the eyepoint to the lookat point.
  944.   vView := VectorSub(vAt, vFrom);
  945.  
  946.   fLength := VectorMagnitude(vView);
  947.   if fLength < 0.1E-6 then
  948.   begin
  949.     Result := E_INVALIDARG;
  950.     Exit;
  951.   end;
  952.  
  953.   // Normalize the z basis vector
  954.   vView := VectorDivS(vView, fLength);
  955.  
  956.   // Get the dot product, and calculate the projection of the z basis
  957.   // vector onto the up vector. The projection is the y basis vector.
  958.   fDotProduct := VectorDotProduct(vWorldUp, vView);
  959.  
  960.   vUp := VectorSub(vWorldUp, VectorMulS(vView, fDotProduct));
  961.  
  962.   // If this vector has near-zero length because the input specified a
  963.   // bogus up vector, let's try a default up vector
  964.   fLength := VectorMagnitude(vUp);
  965.   if 1E-6 > fLength then
  966.   begin
  967.     vUp := VectorSub(MakeD3DVector(0, 1, 0), VectorMulS(vView, vView.y));
  968.  
  969.     // If we still have near-zero length, resort to a different axis.
  970.     fLength := VectorMagnitude(vUp);
  971.     if 1E-6 > fLength then
  972.     begin
  973.       vUp := VectorSub(MakeD3DVector(0, 0, 1), VectorMulS(vView, vView.z));
  974.  
  975.       fLength := VectorMagnitude(vUp);
  976.       if 1E-6 > fLength then
  977.       begin
  978.         Result := E_INVALIDARG;
  979.         Exit;
  980.       end;
  981.     end;
  982.   end;
  983.  
  984.   // Normalize the y basis vector
  985.   vUp := VectorDivS(vUp, fLength);
  986.  
  987.   // The x basis vector is found simply with the cross product of the y
  988.   // and z basis vectors
  989.   vRight := VectorCrossProduct(vUp, vView);
  990.  
  991.   // Start building the matrix. The first three rows contains the basis
  992.   // vectors used to rotate the view to point at the lookat point
  993.   D3DUtil_SetIdentityMatrix(mat);
  994.   mat._11 := vRight.x; mat._12 := vUp.x; mat._13 := vView.x;
  995.   mat._21 := vRight.y; mat._22 := vUp.y; mat._23 := vView.y;
  996.   mat._31 := vRight.z; mat._32 := vUp.z; mat._33 := vView.z;
  997.  
  998.   // Do the translation values (rotations are still about the eyepoint)
  999.   mat._41 := -VectorDotProduct(vFrom, vRight);
  1000.   mat._42 := -VectorDotProduct(vFrom, vUp);
  1001.   mat._43 := -VectorDotProduct(vFrom, vView);
  1002.  
  1003.   Result := S_OK;
  1004. end;
  1005.  
  1006. //-----------------------------------------------------------------------------
  1007. // Name: D3DUtil_SetProjectionMatrix()
  1008. // Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
  1009. //       from the field-of-view (fov, in y), aspect ratio, near plane (D),
  1010. //       and far plane (F). Note that the projection matrix is normalized for
  1011. //       element [3][4] to be 1.0. This is performed so that W-based range fog
  1012. //       will work correctly.
  1013. //-----------------------------------------------------------------------------
  1014.  
  1015. function D3DUtil_SetProjectionMatrix(var mat: TD3DMatrix; fFOV, fAspect, fNearPlane, fFarPlane: Double): HResult;
  1016. var
  1017.   w, h, Q: Double;
  1018. begin
  1019.   if (abs(fFarPlane - fNearPlane) < 0.01) or (abs(sin(fFOV / 2)) < 0.01) then
  1020.   begin
  1021.     Result := E_INVALIDARG;
  1022.     Exit;
  1023.   end;
  1024.  
  1025.   w := fAspect * (cos(fFOV / 2) / sin(fFOV / 2));
  1026.   h := 1.0 * (cos(fFOV / 2) / sin(fFOV / 2));
  1027.   Q := fFarPlane / (fFarPlane - fNearPlane);
  1028.  
  1029.   FillChar(mat, SizeOf(mat), 0);
  1030.   mat._11 := w;
  1031.   mat._22 := h;
  1032.   mat._33 := Q;
  1033.   mat._34 := 1.0;
  1034.   mat._43 := -Q * fNearPlane;
  1035.  
  1036.   Result := S_OK;
  1037. end;
  1038.  
  1039. //-----------------------------------------------------------------------------
  1040. // Name: D3DUtil_SetRotateXMatrix()
  1041. // Desc: Create Rotation matrix about X axis
  1042. //-----------------------------------------------------------------------------
  1043.  
  1044. procedure D3DUtil_SetRotateXMatrix(var mat: TD3DMatrix; fRads: Double);
  1045. begin
  1046.   D3DUtil_SetIdentityMatrix(mat);
  1047.   mat._22 := cos(fRads);
  1048.   mat._23 := sin(fRads);
  1049.   mat._32 := -sin(fRads);
  1050.   mat._33 := cos(fRads);
  1051. end;
  1052.  
  1053. function D3DUtil_SetRotateXMatrix(fRads: Double): TD3DMatrix;
  1054. begin
  1055.   D3DUtil_SetRotateXMatrix(Result, fRads);
  1056. end;
  1057.  
  1058. //-----------------------------------------------------------------------------
  1059. // Name: D3DUtil_SetRotateYMatrix()
  1060. // Desc: Create Rotation matrix about Y axis
  1061. //-----------------------------------------------------------------------------
  1062.  
  1063. procedure D3DUtil_SetRotateYMatrix(var mat: TD3DMatrix; fRads: Double);
  1064. begin
  1065.   D3DUtil_SetIdentityMatrix(mat);
  1066.   mat._11 := cos(fRads);
  1067.   mat._13 := -sin(fRads);
  1068.   mat._31 := sin(fRads);
  1069.   mat._33 := cos(fRads);
  1070. end;
  1071.  
  1072. function D3DUtil_SetRotateYMatrix(fRads: Double): TD3DMatrix;
  1073. begin
  1074.   D3DUtil_SetRotateYMatrix(Result, fRads);
  1075. end;
  1076.  
  1077. //-----------------------------------------------------------------------------
  1078. // Name: D3DUtil_SetRotateZMatrix()
  1079. // Desc: Create Rotation matrix about Z axis
  1080. //-----------------------------------------------------------------------------
  1081.  
  1082. procedure D3DUtil_SetRotateZMatrix(var mat: TD3DMatrix; fRads: Double);
  1083. begin
  1084.   D3DUtil_SetIdentityMatrix(mat);
  1085.   mat._11 := cos(fRads);
  1086.   mat._12 := sin(fRads);
  1087.   mat._21 := -sin(fRads);
  1088.   mat._22 := cos(fRads);
  1089. end;
  1090.  
  1091. function D3DUtil_SetRotateZMatrix(fRads: Double): TD3DMatrix;
  1092. begin
  1093.   D3DUtil_SetRotateZMatrix(Result, fRads);
  1094. end;
  1095.  
  1096. //-----------------------------------------------------------------------------
  1097. // Name: D3DUtil_SetRotationMatrix
  1098. // Desc: Create a Rotation matrix about vector direction
  1099. //-----------------------------------------------------------------------------
  1100.  
  1101. procedure D3DUtil_SetRotationMatrix(var mat: TD3DMatrix; var vDir: TD3DVector; fRads: Double);
  1102. var
  1103.   fCos, fSin: Double;
  1104.   v: TD3DVector;
  1105. begin
  1106.   fCos := cos(fRads);
  1107.   fSin := sin(fRads);
  1108.   v := VectorNormalize(vDir);
  1109.  
  1110.   mat._11 := (v.x * v.x) * (1.0 - fCos) + fCos;
  1111.   mat._12 := (v.x * v.y) * (1.0 - fCos) - (v.z * fSin);
  1112.   mat._13 := (v.x * v.z) * (1.0 - fCos) + (v.y * fSin);
  1113.  
  1114.   mat._21 := (v.y * v.x) * (1.0 - fCos) + (v.z * fSin);
  1115.   mat._22 := (v.y * v.y) * (1.0 - fCos) + fCos;
  1116.   mat._23 := (v.y * v.z) * (1.0 - fCos) - (v.x * fSin);
  1117.  
  1118.   mat._31 := (v.z * v.x) * (1.0 - fCos) - (v.y * fSin);
  1119.   mat._32 := (v.z * v.y) * (1.0 - fCos) + (v.x * fSin);
  1120.   mat._33 := (v.z * v.z) * (1.0 - fCos) + fCos;
  1121.  
  1122.   mat._14 := 0; mat._24 := 0; mat._34 := 0;
  1123.   mat._41 := 0; mat._42 := 0; mat._43 := 0;
  1124.   mat._44 := 1.0;
  1125. end;
  1126.  
  1127. function D3DUtil_SetRotationMatrixByX(const a: TD3DVector; const r: Double): TD3DVector;
  1128. begin
  1129.   Result.X := a.X;
  1130.   Result.Y := a.Y * Cos(r) + a.Z * Sin(r);
  1131.   Result.Z := -a.Y * Sin(r) + a.Z * Cos(r);
  1132. end;
  1133.  
  1134. function D3DUtil_SetRotationMatrixByY(const a: TD3DVector; const r: Double): TD3DVector;
  1135. begin
  1136.   Result.X := a.X * Cos(r) - a.Z * Sin(r);
  1137.   Result.Y := a.Y;
  1138.   Result.Z := a.X * Sin(r) + a.Z * Cos(r);
  1139. end;
  1140.  
  1141. function D3DUtil_SetRotationMatrixByZ(const a: TD3DVector; const r: Double): TD3DVector;
  1142. begin
  1143.   Result.X := a.X * Cos(r) + a.Y * Sin(r);
  1144.   Result.Y := -a.X * Sin(r) + a.Y * Cos(r);
  1145.   Result.Z := a.Z;
  1146. end;
  1147.  
  1148. // simple D2D operation
  1149.  
  1150. function D2DMath_VecAdd(const a: TD2DVector; const b: TD2DVector): TD2DVector;
  1151. begin
  1152.   Result.X := a.X + b.X;
  1153.   Result.Y := a.Y + b.Y;
  1154. end;
  1155.  
  1156. function D2DMath_VecSub(const a: TD2DVector; const b: TD2DVector): TD2DVector;
  1157. begin
  1158.   Result.X := a.X - b.X;
  1159.   Result.Y := a.Y - b.Y;
  1160. end;
  1161.  
  1162. function D2DMath_VecDotProduct(const a, b: TD2DVector): Single;
  1163. begin
  1164.   Result := a.X * b.X + a.Y * b.Y;
  1165. end;
  1166.  
  1167. function D2DMath_VecDistance(const a, b: TD2DVector): Single;
  1168. begin
  1169.   Result := sqrt(SQR(a.X - b.X) + SQR(a.Y - b.Y));
  1170. end;
  1171.  
  1172. function D2DMath_VecLength(const a: TD2DVector): Single;
  1173. begin
  1174.   Result := sqrt(SQR(a.X) + SQR(a.Y));
  1175. end;
  1176.  
  1177. function D2DMath_VecNormalize(const a: TD2DVector): TD2DVector;
  1178. var
  1179.   len: Single;
  1180. begin
  1181.   len := D2DMath_VecLength(a);
  1182.   if len = 0 then
  1183.   begin
  1184.     result := MakeD2DVector(0, 0);
  1185.     Exit;
  1186.   end;
  1187.  
  1188.   result.X := a.X / len;
  1189.   result.Y := a.Y / len;
  1190. end;
  1191.  
  1192. function D2DMath_VecToAngle(const a: TD2DVector): Double;
  1193. var
  1194.   v: TD2DVector;
  1195.   sg: Integer;
  1196.   hi, lo, mid: Integer;
  1197. begin
  1198.   Result := 0.0;
  1199.  
  1200.   v := D2DMath_VecNormalize(a);
  1201.  
  1202.   if (v.y > 0) then
  1203.   begin
  1204.     if v.x > 0 then
  1205.       sg := 1
  1206.     else
  1207.     begin
  1208.       sg := 2;
  1209.       v.x := -v.x;
  1210.     end;
  1211.   end
  1212.   else
  1213.     if (v.y < 0) then
  1214.     begin
  1215.       if v.x >= 0 then
  1216.         sg := 4
  1217.       else
  1218.       begin
  1219.         sg := 3;
  1220.         v.x := -v.x;
  1221.       end;
  1222.     end
  1223.     else
  1224.     begin
  1225.       if v.x >= 0 then
  1226.         sg := 1
  1227.       else
  1228.       begin
  1229.         sg := 3;
  1230.         v.x := -v.x;
  1231.       end;
  1232.     end;
  1233.  
  1234.  
  1235.   hi := 1023;
  1236.   lo := 0;
  1237.   mid := 511;
  1238.  
  1239.   while hi > lo do
  1240.   begin
  1241.     if Cos(mid / 2048.0 * Pi) > v.x then
  1242.       lo := mid + 1
  1243.     else
  1244.       hi := mid;
  1245.     mid := (hi + lo) shr 1;
  1246.   end;
  1247.  
  1248.   case sg of
  1249.     1: result := mid;
  1250.     2: result := 2047 - mid;
  1251.     3: result := 2048 + mid;
  1252.     4: result := 4095 - mid;
  1253.   end;
  1254.  
  1255.   // to radians
  1256.   Result := Result * Pi / 2048.0;
  1257. end;
  1258.  
  1259. function D2DMath_VecRot(const a: TD2DVector; const angle: Double): TD2DVector;
  1260. begin
  1261.   Result.X := a.X * Cos(angle) - a.Y * Sin(angle);
  1262.   Result.Y := a.X * Sin(angle) + a.Y * Cos(angle);
  1263. end;
  1264.  
  1265.  
  1266. function D2DMath_VecScale(const a: TD2DVector; const scale: Double): TD2DVector;
  1267. begin
  1268.   Result.X := a.X * scale;
  1269.   Result.Y := a.Y * scale;
  1270. end;
  1271.  
  1272. function D2DMath_VecChangeLength(const a: TD2DVector; const k: Single): TD2DVector;
  1273. var
  1274.   len: Single;
  1275. begin
  1276.   len := D2DMath_VecLength(a);
  1277.   if len = 0 then
  1278.   begin
  1279.     Result := MakeD2DVector(0, 0);
  1280.     Exit;
  1281.   end;
  1282.  
  1283.   Result.X := a.X * k / len;
  1284.   Result.Y := a.Y * k / len;
  1285. end;
  1286.  
  1287. function D2DMath_VecLookAt(const pos: TD2DVector; const target: TD2DVector; const k: Single): TD2DVector;
  1288. var
  1289.   sub: TD2DVector;
  1290.   len: Single;
  1291. begin
  1292.   sub := D2DMath_VecSub(target, pos);
  1293.   len := D2DMath_VecLength(sub);
  1294.   if len = 0 then
  1295.   begin
  1296.     Result := MakeD2DVector(0, 0);
  1297.     Exit;
  1298.   end;
  1299.  
  1300.   Result.X := sub.X * k / len;
  1301.   Result.Y := sub.Y * k / len;
  1302. end;
  1303.  
  1304. function D2DMath_VecRandom2D(const k: Single): TD2DVector;
  1305. begin
  1306.   Result := D2DMath_VecChangeLength(MakeD2DVector(Random - 0.5, Random - 0.5), k);
  1307. end;
  1308.  
  1309. function D2DMath_VecLerp(const a: TD2DVector; const b: TD2DVector; const rate: Single): TD2DVector;
  1310. begin
  1311.   Result.x := rate * b.x + (1.0 - rate) * a.x;
  1312.   Result.y := rate * b.y + (1.0 - rate) * a.y;
  1313. end;
  1314.  
  1315.  
  1316. end.
  1317.  
  1318.