Yasiu Math 1
Collection of mathematic functions that help create game mechanics and procedural tools
Loading...
Searching...
No Matches
YasiuMathLib.inl
1/*
2 * Copyright (c) 2025 Grzegorz Krug.
3 * All Rights Reserved.
4 */
5
6#pragma once
7
8#include "YasiuMathLib.h"
9
10
11using namespace YasiuMath::Types;
12
13
14namespace YasiuMath {
15 namespace Ballistics {
16 template<typename T>
18 const Vec3<T>& TargetPosition,
19 const Vec3<T>& TargetVelocity,
20 const T BulletSpeed,
21 Vec3<T>& InterceptLocation,
22 T& ImpactTime
23 )
24 {
25 T a = TargetVelocity.Dot(TargetVelocity) - BulletSpeed * BulletSpeed;
26 T b = 2.0f * TargetPosition.Dot(TargetVelocity);
27 T c = TargetPosition.Dot(TargetPosition);
28
29
30 if ( fabs(a) < 1e-6f ) {
31 // Bullet speed ~= target speed
32 if ( fabs(b) < 1e-6f )
33 return false; // No solution
34 ImpactTime = -c / b;
35 if ( ImpactTime < 0 )
36 return false;
37 }
38 else {
39 T discriminant = b * b - 4.0f * a * c;
40 if ( discriminant < 0 )
41 return false; // No real solution
42 T sqrtD = sqrtf(discriminant);
43 T t1 = (-b + sqrtD) / (2.0f * a);
44 T t2 = (-b - sqrtD) / (2.0f * a);
45
46 // Choose smallest positive t
47 ImpactTime = (t1 > 0 && t2 > 0) ? fminf(t1, t2) : (t1 > 0 ? t1 : t2);
48 if ( ImpactTime < 0 )
49 return false; // Both solutions negative
50 }
51 InterceptLocation = TargetPosition + TargetVelocity * ImpactTime;
52 return true;
53 }
54
55 template<typename T>
58 const InterceptorParams<T>& Interceptor,
59 const T MaxQueryTime,
60 const T StepTime,
61 const T AccurateStepTime,
62 Vec3<T>& HitLocation,
63 T& HitTime
64 )
65 {
66 bool calculationValid = false;
67 const auto HalfStepTime = StepTime / 2;
68 const auto HalfAccurateStepTime = AccurateStepTime / 2;
69
70 Vec3<T> InitialOffset = Interceptor.Position;
71 Target.Position -= InitialOffset;
72
73 T Velocity = Interceptor.InitialSpeed;
74 T Range = 0;
75
76 if ( StepTime < YasiuMath::Constants::EPSILON ) {
77 /* Too Small Eps */
78 // throw std::runtime_error("Delta time in Intercept is too small");
79 return false;
80 }
81
82 unsigned int StepsMax = static_cast<unsigned int>(floor(MaxQueryTime / StepTime));
83
84 /* 1-Indexed for time calculation */
85 unsigned int Steps = 0;
86 auto PrevMissile = Target;
87 T PrevRange = 0;
88 T PrevVelocity = Velocity;
89
90 for ( Steps = 1; Steps < (StepsMax + 1); Steps++ ) {
91 /* Missile update */
92 Target.DiscreteStep(StepTime);
93
94 /* Interceptor state update */
95 const auto OldVel = Velocity;
96 Velocity += Interceptor.Acceleration * StepTime;
97
98
99 if ( Interceptor.AirResistance > 0 ) {
100 /* Velocity is always positive */
101 const auto TrapezVelocity = (OldVel + Velocity) / 2;
102 const auto drag = TrapezVelocity * TrapezVelocity * Interceptor.AirResistance * StepTime;
103 Velocity -= drag;
104 if ( Velocity <= 0 ) {
105 return false;
106 }
107 }
108
109 if ( Velocity > Interceptor.MaxSpeed && Interceptor.MaxSpeed > 0 ) {
110 Velocity = Interceptor.MaxSpeed;
111 }
112
113 /* Must use velocity affected by drag */
114 Range += (Velocity + OldVel) * HalfStepTime;
115
116 if ( Target.Position.Length() <= Range ) {
117 calculationValid = true;
118 /* Reached estimation */
119 break;
120 }
121
122 PrevMissile = Target;
123 PrevRange = Range;
124 PrevVelocity = Velocity;
125 }
126
127 /* Phase 2 backward + Accurate estimation */
128 if ( AccurateStepTime > 0 && AccurateStepTime < StepTime ) {
129 Steps -= 1;
130 Target = PrevMissile;
131 Range = PrevRange;
132 Velocity = PrevVelocity;
133
134 /* SUBSTEP LOOP Duplicate */
135 unsigned int AccSteps = 1;
136 for ( AccSteps = 1; AccSteps < 100000; AccSteps++ ) {
137 /* Missile update */
138 Target.DiscreteStep(AccurateStepTime);
139
140 /* Interceptor state update */
141 const auto OldVel = Velocity;
142 Velocity += Interceptor.Acceleration * AccurateStepTime;
143
144
145 if ( Interceptor.AirResistance > 0 ) {
146 /* Velocity is always positive */
147 const auto TrapezVelocity = (OldVel + Velocity) / 2;
148 const auto drag = TrapezVelocity * TrapezVelocity * Interceptor.AirResistance * AccurateStepTime;
149 Velocity -= drag;
150 if ( Velocity <= 0 ) {
151 return false;
152 }
153 }
154
155 if ( Velocity > Interceptor.MaxSpeed && Interceptor.MaxSpeed > 0 ) {
156 Velocity = Interceptor.MaxSpeed;
157 }
158
159 /* Dynamic update must be iterative */
160 Range += (Velocity + OldVel) * HalfAccurateStepTime;
161
162 if ( Target.Position.Length() <= Range ) {
163 calculationValid = true;
164 /* Reached estimation */
165 break;
166 }
167 }
168 HitTime = Steps * StepTime + AccSteps * AccurateStepTime;
169 }
170 else {
171 HitTime = Steps * StepTime;
172 }
173
174 HitLocation = Target.Position + InitialOffset;
175 return calculationValid;
176 }
177 }
178};
Linear and dynamic objects simulation / prediction.
Definition YasiuMathLib.h:578
bool InterceptMissile_Dynamic(ProjectileDynamicState< T > Target, const InterceptorParams< T > &Interceptor, const T MaxQueryTime, const T StepTime, Types::Vec3< T > &PredictedLocation)
Iterative state prediction. Returns first possible intercept location and time.
Definition YasiuMathLib.h:885
bool InterceptMissile_Linear(const Types::Vec3< T > &MissilePosition, const Types::Vec3< T > &MissileVelocity, const T BulletSpeed, Types::Vec3< T > &InterceptLocation, T &ImpactTime)
Linear movement with linear velocity, Fast: O(1).
constexpr double EPSILON
Value used for number stability check.
Definition Constants.h:17
Generic Types used in library.
Definition YasiuMathDataTypes.h:24
Categorized name spaces.
Definition Constants.h:10
Params used for ballistics predictions.
Definition YasiuMathLib.h:812
Ballistic state. Can move in time with DiscreteStep function.
Definition YasiuMathLib.h:587
T Dot(const Vec3 &other) const
Dot product of 2 vectors.
Definition YasiuMathDataTypes.h:274