6 static vector GetFixedAxisVector(vector toFlip)
8 return { toFlip[1], toFlip[0], toFlip[2] };
13 static void RotateTowards(out
float result[4],
float from[4],
float to[4],
float maxDegreesDelta)
15 float num = Math3D.QuatAngle(from, to);
16 if (
float.AlmostEqual(num, 0.0))
18 Math3D.QuatCopy(to, result);
22 float t = Math.Min(1, maxDegreesDelta / num);
23 Math3D.QuatLerp(result, from, to, t);
28 static vector MoveTowards(vector start, vector target,
float maxDistanceDelta)
30 vector diff = target - start;
31 float magnitude = diff.Length();
32 if (magnitude <= maxDistanceDelta || magnitude == 0)
35 return start + diff / magnitude * maxDistanceDelta;
44 static vector FixEulerVector180(vector angles)
46 for (
int i = 0; i < 3; i++)
48 if (angles[i] < -180 || angles[i] > 180)
49 angles[i] = Math.Repeat(180 + angles[i], 360) - 180;
66 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)
68 float scale = entity.GetScale();
69 vector currentMatrix[4];
70 entity.GetWorldTransform(currentMatrix);
75 Math3D.MatrixToQuat(currentMatrix,
rotation);
78 if (!physics || !physics.IsDynamic())
81 Math3D.QuatToMatrix(netRotation, currentMatrix);
83 currentMatrix[3] = netPosition;
85 entity.SetWorldTransform(currentMatrix);
86 entity.SetScale(scale);
91 vector projectedPos = netPosition + netVelocityLinear * timeSinceLastTick;
93 vector netVelocityAngularFlipped =
SCR_Math3D.GetFixedAxisVector(netVelocityAngular * timeSinceLastTick);
94 float projectedRotation[4];
95 float netVelocityAngularQuat[4];
96 netVelocityAngularFlipped.QuatFromAngles(netVelocityAngularQuat);
97 Math3D.QuatMultiply(projectedRotation, netRotation, netVelocityAngularQuat);
100 float posError = vector.Distance(projectedPos,
position);
101 float rotError = Math3D.QuatAngle(projectedRotation,
rotation);
104 if (posError > netTeleportDistance)
106 entity.SetOrigin(netPosition);
111 if (rotError > netTeleportAng)
113 Math3D.QuatToMatrix(netRotation, currentMatrix);
114 currentMatrix[3] = entity.GetOrigin();
115 entity.SetWorldTransform(currentMatrix);
119 float timeStep = timeSlice / netTickInterval;
120 float timeStepTick = Math.Clamp(timeSlice / netTickInterval, 0, 1);
125 entity.SetOrigin(
SCR_Math3D.MoveTowards(
position, projectedPos, posError * timeStep));
126 physics.SetVelocity(physics.GetVelocity() + (projectedPos -
position) * timeStepTick);
132 Math3D.QuatRotateTowards(outRot,
rotation, projectedRotation, (rotError * timeStep) * Math.RAD2DEG);
133 Math3D.QuatToMatrix(outRot, currentMatrix);
134 currentMatrix[3] = entity.GetOrigin();
135 entity.SetWorldTransform(currentMatrix);
139 Math3D.QuatInverse(rotInv,
rotation);
140 Math3D.QuatMultiply(rotDiff, projectedRotation, rotInv);
141 vector angularVelocity = Math3D.QuatToAngles(rotDiff);
142 angularVelocity =
SCR_Math3D.FixEulerVector180(angularVelocity) * Math.DEG2RAD * timeStepTick;
143 angularVelocity += physics.GetAngularVelocity();
144 physics.SetAngularVelocity(angularVelocity);
147 entity.SetScale(scale);
159 static vector IntersectPlane(vector rayPos, vector rayVector, vector planePos, vector planeNormal)
161 return rayPos - rayVector * (vector.Dot(rayPos - planePos, planeNormal) / vector.Dot(rayVector, planeNormal));
171 static bool MatrixEqual(vector matrixA[4], vector matrixB[4])
173 return matrixA[3] == matrixB[3]
174 && matrixA[2] == matrixB[2]
175 && matrixA[1] == matrixB[1]
176 && matrixA[0] == matrixB[0];
185 static bool IsMatrixEmpty(vector matrix[4])
187 return matrix[3] == vector.Zero
188 && matrix[2] == vector.Zero
189 && matrix[1] == vector.Zero
190 && matrix[0] == vector.Zero;
199 static bool IsMatrixIdentity(vector matrix[4])
201 return matrix[3] == vector.Zero
202 && matrix[2] == vector.Forward
203 && matrix[1] == vector.Up
204 && matrix[0] == vector.Right;
217 static vector Min(vector vA, vector vB)
220 Math.Min(vA[0], vB[0]),
221 Math.Min(vA[1], vB[1]),
222 Math.Min(vA[2], vB[2])
236 static vector
Max(vector vA, vector vB)
239 Math.Max(vA[0], vB[0]),
240 Math.Max(vA[1], vB[1]),
241 Math.Max(vA[2], vB[2])
250 static float GetDistanceFromSpline(notnull array<vector> points, vector point)
252 int count = points.Count();
257 return vector.Distance(point, points[0]);
259 float tempDistanceSq;
260 vector segmentStart = points[0];
261 float minDistanceSq = vector.DistanceSq(point, segmentStart);
263 foreach (
int i, vector segmentEnd : points)
268 tempDistanceSq = Math3D.PointLineSegmentDistanceSqr(point, segmentStart, segmentEnd);
269 if (tempDistanceSq < minDistanceSq)
270 minDistanceSq = tempDistanceSq;
272 segmentStart = segmentEnd;
275 return Math.Sqrt(minDistanceSq);
283 static float GetDistanceFromSplineXZ(notnull array<vector> points, vector point)
285 int count = points.Count();
290 return vector.DistanceXZ(point, points[0]);
292 float tempDistanceSq;
293 vector segmentStart = points[0];
294 float minDistanceSq = vector.DistanceSqXZ(point, segmentStart);
298 foreach (
int i, vector segmentEnd : points)
305 tempDistanceSq = Math3D.PointLineSegmentDistanceSqr(point, segmentStart, segmentEnd);
306 if (tempDistanceSq < minDistanceSq)
307 minDistanceSq = tempDistanceSq;
309 segmentStart = segmentEnd;
312 return Math.Sqrt(minDistanceSq);
321 static bool IsPointWithinSplineDistance(notnull array<vector> points, vector point,
float distance)
323 int count = points.Count();
328 return vector.Distance(point, points[0]) <=
distance;
331 vector segmentStart = points[0];
333 foreach (
int i, vector segmentEnd : points)
338 if (Math3D.PointLineSegmentDistanceSqr(point, segmentStart, segmentEnd) <
distance)
341 segmentStart = segmentEnd;
353 static bool IsPointWithinSplineDistanceXZ(notnull array<vector> points, vector point,
float distance)
355 int count = points.Count();
360 return vector.DistanceXZ(point, points[0]) <=
distance;
363 vector segmentStart = points[0];
367 foreach (
int i, vector segmentEnd : points)
374 if (Math3D.PointLineSegmentDistanceSqr(point, segmentStart, segmentEnd) <
distance)
377 segmentStart = segmentEnd;
397 static void QuatAngleAxis(
float angle, vector axis, out
float quat[4])
400 float sin = Math.Sin(angle);
403 quat[0] = axis[0] * sin;
404 quat[1] = axis[1] * sin;
405 quat[2] = axis[2] * sin;
406 quat[3] = Math.Cos(angle);
416 static vector QuatMultiply(
float quat[4], vector vec)
418 vector xyz = Vector(quat[0], quat[1], quat[2]);
419 vector t = 2.0 * (xyz * vec);
420 return vec + quat[3] * t + (xyz * t);
432 static void RotateAround(vector transform[4], vector pivot, vector axis,
float angle, out vector result[4])
435 QuatAngleAxis(angle, axis, q);
436 result[3] = QuatMultiply(q, (transform[3] - pivot)) + pivot;
439 Math3D.MatrixToQuat(transform, qt);
440 Math3D.QuatMultiply(qt, q, qt);
441 Math3D.QuatToMatrix(qt, result);
452 static void LookAt(vector source, vector destination, vector up, out vector rotMat[4])
454 vector lookDir = destination - source;
455 Math3D.DirectionAndUpMatrix(lookDir.Normalized(), up.Normalized(), rotMat);
465 static vector ClampMagnitude(vector v,
float magnitude)
467 if (v.LengthSq() > magnitude * magnitude)
468 return v.Normalized() * magnitude;