Subversion Repositories spacemission

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 daniel-mar 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