Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_Math3D.c
Go to the documentation of this file.
1
3{
4 //------------------------------------------------------------------------------------------------
8 static vector GetFixedAxisVector(vector toFlip)
9 {
10 return { toFlip[1], toFlip[0], toFlip[2] };
11 }
12
13 //------------------------------------------------------------------------------------------------
19 static void RotateTowards(out float result[4], float from[4], float to[4], float maxDegreesDelta)
20 {
21 float num = Math3D.QuatAngle(from, to);
22 if (float.AlmostEqual(num, 0.0))
23 {
24 Math3D.QuatCopy(to, result);
25 return;
26 }
27
28 float t = Math.Min(1, maxDegreesDelta / num);
29 Math3D.QuatLerp(result, from, to, t);
30 }
31
32 //------------------------------------------------------------------------------------------------
38 static vector MoveTowards(vector start, vector target, float maxDistanceDelta)
39 {
40 vector diff = target - start;
41 float magnitude = diff.Length();
42 if (magnitude <= maxDistanceDelta || magnitude == 0)
43 return target;
44
45 return start + diff / magnitude * maxDistanceDelta;
46 }
47
48 //------------------------------------------------------------------------------------------------
56 static vector FixEulerVector(vector angles, float units = Math.PI)
57 {
58 for (int i; i < 3; ++i)
59 {
60 angles[i] = Math.Repeat(units + angles[i], units * 2) - units;
61 }
62
63 return angles;
64 }
65
66 //------------------------------------------------------------------------------------------------
73 static vector FixEulerVector180(vector angles)
74 {
75 for (int i; i < 3; i++)
76 {
77 angles[i] = Math.Repeat(180 + angles[i], 360) - 180;
78 }
79
80 return angles;
81 }
82
83 //------------------------------------------------------------------------------------------------
95 static void Extrapolate(IEntity entity, Physics physics, vector netPosition, vector netVelocityLinear, float netTeleportDistance, float netRotation[4], vector netVelocityAngular, float netTeleportAng, float timeSinceLastTick, float timeSlice, float netTickInterval)
96 {
97 float scale = entity.GetScale();
98 vector currentMatrix[4];
99 entity.GetWorldTransform(currentMatrix);
100
101 // Lerp to positions/rotations received
102 vector position = currentMatrix[3];
103 float rotation[4];
104 Math3D.MatrixToQuat(currentMatrix, rotation);
105
106 // Static object, ensure exact rotation/position
107 if (!physics || !physics.IsDynamic())
108 {
109 if (rotation != netRotation)
110 Math3D.QuatToMatrix(netRotation, currentMatrix);
111
112 currentMatrix[3] = netPosition;
113
114 entity.SetWorldTransform(currentMatrix);
115 entity.SetScale(scale);
116 return;
117 }
118
119 // Dynamic object, so calculate projected position/rotation based on last tick
120 vector projectedPos = netPosition + netVelocityLinear * timeSinceLastTick;
121
122 vector netVelocityAngularFlipped = GetFixedAxisVector(netVelocityAngular * timeSinceLastTick);
123 float projectedRotation[4];
124 float netVelocityAngularQuat[4];
125 netVelocityAngularFlipped.QuatFromAngles(netVelocityAngularQuat);
126 Math3D.QuatMultiply(projectedRotation, netRotation, netVelocityAngularQuat);
127
128 // Calculate the position and rotation error
129 float posError = vector.Distance(projectedPos, position);
130 float rotError = Math3D.QuatAngle(projectedRotation, rotation);
131
132 // If too far off position, teleport
133 if (posError > netTeleportDistance)
134 {
135 entity.SetOrigin(netPosition);
136 posError = 0;
137 }
138
139 // If too far off rotation, teleport
140 if (rotError > netTeleportAng)
141 {
142 Math3D.QuatToMatrix(netRotation, currentMatrix);
143 currentMatrix[3] = entity.GetOrigin();
144 entity.SetWorldTransform(currentMatrix);
145 rotError = 0;
146 }
147
148 float timeStep = timeSlice / netTickInterval;
149 float timeStepTick = Math.Clamp(timeSlice / netTickInterval, 0, 1);
150
151 // Adjust to account for errors in position/rotation
152 if (posError > 0.01)
153 {
154 entity.SetOrigin(MoveTowards(position, projectedPos, posError * timeStep));
155 physics.SetVelocity(physics.GetVelocity() + (projectedPos - position) * timeStepTick);
156 }
157
158 if (rotError > 0.01)
159 {
160 float outRot[4];
161 Math3D.QuatRotateTowards(outRot, rotation, projectedRotation, (rotError * timeStep) * Math.RAD2DEG);
162 Math3D.QuatToMatrix(outRot, currentMatrix);
163 currentMatrix[3] = entity.GetOrigin();
164 entity.SetWorldTransform(currentMatrix);
165
166 float rotDiff[4];
167 float rotInv[4];
168 Math3D.QuatInverse(rotInv, rotation);
169 Math3D.QuatMultiply(rotDiff, projectedRotation, rotInv);
170 vector angularVelocity = Math3D.QuatToAngles(rotDiff);
171 angularVelocity = FixEulerVector180(angularVelocity) * Math.DEG2RAD * timeStepTick;
172 angularVelocity += physics.GetAngularVelocity();
173 physics.SetAngularVelocity(angularVelocity);
174 }
175
176 entity.SetScale(scale);
177 }
178
179 //------------------------------------------------------------------------------------------------
186 static vector IntersectPlane(vector rayPos, vector rayVector, vector planePos, vector planeNormal)
187 {
188 return rayPos - rayVector * (vector.Dot(rayPos - planePos, planeNormal) / vector.Dot(rayVector, planeNormal));
189 }
190
191 //------------------------------------------------------------------------------------------------
196 static bool MatrixEqual(vector matrixA[4], vector matrixB[4])
197 {
198 return matrixA[3] == matrixB[3]
199 && matrixA[2] == matrixB[2]
200 && matrixA[1] == matrixB[1]
201 && matrixA[0] == matrixB[0];
202 }
203
204 //------------------------------------------------------------------------------------------------
208 static bool IsMatrixEmpty(vector matrix[4])
209 {
210 return matrix[3] == vector.Zero
211 && matrix[2] == vector.Zero
212 && matrix[1] == vector.Zero
213 && matrix[0] == vector.Zero;
214 }
215
216 //------------------------------------------------------------------------------------------------
220 static bool IsMatrixIdentity(vector matrix[4])
221 {
222 return matrix[3] == vector.Zero
223 && matrix[2] == vector.Forward
224 && matrix[1] == vector.Up
225 && matrix[0] == vector.Right;
226 }
227
228 //------------------------------------------------------------------------------------------------
236 static vector Min(vector vA, vector vB)
237 {
238 return {
239 Math.Min(vA[0], vB[0]),
240 Math.Min(vA[1], vB[1]),
241 Math.Min(vA[2], vB[2])
242 };
243 }
244
245 //------------------------------------------------------------------------------------------------
253 static vector Max(vector vA, vector vB)
254 {
255 return {
256 Math.Max(vA[0], vB[0]),
257 Math.Max(vA[1], vB[1]),
258 Math.Max(vA[2], vB[2])
259 };
260 }
261
262 //------------------------------------------------------------------------------------------------
267 static float GetDistanceFromSpline(notnull array<vector> points, vector point)
268 {
269 int count = points.Count();
270 if (count < 1)
271 return -1;
272
273 if (count == 1)
274 return vector.Distance(point, points[0]);
275
276 float tempDistanceSq;
277 vector segmentStart = points[0];
278 float minDistanceSq = vector.DistanceSq(point, segmentStart);
279
280 foreach (int i, vector segmentEnd : points)
281 {
282 if (i == 0)
283 continue;
284
285 tempDistanceSq = Math3D.PointLineSegmentDistanceSqr(point, segmentStart, segmentEnd);
286 if (tempDistanceSq < minDistanceSq)
287 minDistanceSq = tempDistanceSq;
288
289 segmentStart = segmentEnd;
290 }
291
292 return Math.Sqrt(minDistanceSq);
293 }
294
295 //------------------------------------------------------------------------------------------------
300 static float GetDistanceFromSplineXZ(notnull array<vector> points, vector point)
301 {
302 int count = points.Count();
303 if (count < 1)
304 return -1;
305
306 if (count == 1)
307 return vector.DistanceXZ(point, points[0]);
308
309 float tempDistanceSq;
310 vector segmentStart = points[0];
311 float minDistanceSq = vector.DistanceSqXZ(point, segmentStart);
312 segmentStart[1] = 0; // 2D conversion
313 point[1] = 0; // 2D conversion
314
315 foreach (int i, vector segmentEnd : points)
316 {
317 if (i == 0)
318 continue;
319
320 segmentEnd[1] = 0;
321
322 tempDistanceSq = Math3D.PointLineSegmentDistanceSqr(point, segmentStart, segmentEnd);
323 if (tempDistanceSq < minDistanceSq)
324 minDistanceSq = tempDistanceSq;
325
326 segmentStart = segmentEnd;
327 }
328
329 return Math.Sqrt(minDistanceSq);
330 }
331
332 //------------------------------------------------------------------------------------------------
338 static bool IsPointWithinSplineDistance(notnull array<vector> points, vector point, float distance)
339 {
340 int count = points.Count();
341 if (count < 1)
342 return -1;
343
344 if (count == 1)
345 return vector.Distance(point, points[0]) <= distance;
346
347 distance *= distance; // variable reuse
348 vector segmentStart = points[0];
349
350 foreach (int i, vector segmentEnd : points)
351 {
352 if (i == 0)
353 continue;
354
355 if (Math3D.PointLineSegmentDistanceSqr(point, segmentStart, segmentEnd) < distance)
356 return true;
357
358 segmentStart = segmentEnd;
359 }
360
361 return false;
362 }
363
364 //------------------------------------------------------------------------------------------------
370 static bool IsPointWithinSplineDistanceXZ(notnull array<vector> points, vector point, float distance)
371 {
372 int count = points.Count();
373 if (count < 1)
374 return false;
375
376 if (count == 1)
377 return vector.DistanceXZ(point, points[0]) <= distance;
378
379 distance *= distance; // variable reuse
380 vector segmentStart = points[0];
381 segmentStart[1] = 0; // 2D conversion
382 point[1] = 0; // 2D conversion
383
384 foreach (int i, vector segmentEnd : points)
385 {
386 if (i == 0)
387 continue;
388
389 segmentEnd[1] = 0; // 2D conversion
390
391 if (Math3D.PointLineSegmentDistanceSqr(point, segmentStart, segmentEnd) < distance)
392 return true;
393
394 segmentStart = segmentEnd;
395 }
396
397 return false;
398 }
399
400 //------------------------------------------------------------------------------------------------
412 static void QuatAngleAxis(float angle, vector axis, out float quat[4])
413 {
414 angle *= 0.5;
415 float sin = Math.Sin(angle);
416
417 axis.Normalize();
418 quat[0] = axis[0] * sin;
419 quat[1] = axis[1] * sin;
420 quat[2] = axis[2] * sin;
421 quat[3] = Math.Cos(angle);
422 }
423
424 //------------------------------------------------------------------------------------------------
429 static vector QuatMultiply(float quat[4], vector vec)
430 {
431 vector xyz = { quat[0], quat[1], quat[2] };
432 vector t = 2.0 * (xyz * vec);
433 return vec + quat[3] * t + (xyz * t);
434 }
435
436 //------------------------------------------------------------------------------------------------
443 static void RotateAround(vector transform[4], vector pivot, vector axis, float angle, out vector result[4])
444 {
445 float q[4];
446 QuatAngleAxis(angle, axis, q);
447 result[3] = QuatMultiply(q, (transform[3] - pivot)) + pivot;
448
449 float qt[4];
450 Math3D.MatrixToQuat(transform, qt);
451 Math3D.QuatMultiply(qt, q, qt);
452 Math3D.QuatToMatrix(qt, result);
453 }
454
455 //------------------------------------------------------------------------------------------------
461 static void LookAt(vector source, vector destination, vector up, out vector rotMat[4])
462 {
463 Math3D.DirectionAndUpMatrix(vector.Direction(source, destination).Normalized(), up.Normalized(), rotMat);
464 }
465
466 //------------------------------------------------------------------------------------------------
471 static vector ClampMagnitude(vector v, float magnitude)
472 {
473 if (v.LengthSq() > magnitude * magnitude)
474 return v.Normalized() * magnitude;
475
476 return v;
477 }
478
479 //------------------------------------------------------------------------------------------------
485 static vector Cross(vector first, vector second, bool normalizeVectors = false)
486 {
487 if (normalizeVectors)
488 {
489 first.Normalize();
490 second.Normalize();
491 }
492
493 return { first[1] * second[2] - first[2] * second[1],
494 first[2] * second[0] - first[0] * second[2],
495 first[0] * second[1] - first[1] * second[0]};
496 }
497}
vector scale
ref array< string > angles
float distance
vector position
proto external float GetScale()
proto external void SetOrigin(vector orig)
proto external vector GetOrigin()
proto external void GetWorldTransform(out vector mat[])
See IEntity::GetTransform.
proto external bool SetWorldTransform(vector mat[4])
See IEntity::SetTransform. Returns false, if there is no change in transformation.
proto external void SetScale(float scale)
Definition Math.c:13
Contains various scripted 3D math functions.
Definition SCR_Math3D.c:3
@ Max
RespawnSystemComponentClass GameComponentClass vector vector rotation