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 |