Last active
January 29, 2023 01:45
-
-
Save RaheelYawar/a75000f735dd1cca43cb49bb2fe7e8a1 to your computer and use it in GitHub Desktop.
Projectile Motion Trajectory Prediction: Use the Newton's Kinematic formula to find the the projectile distance covered and the time taken
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct QueryResult | |
{ | |
QueryResult(): m_HitPos(0.0f), m_ValidHit(false) {} | |
Vec3 m_HitPos; | |
bool m_ValidHit; | |
}; | |
QueryResult Raycast( const Vec3& p0, const Vec3& p1 ); | |
struct Plane | |
{ | |
Plane() : normal( 0.0f ), d( 0.0f ) {} | |
Plane( float a, float b, float c, float pd ) : normal( a, b, c ), d( pd ) {} | |
Plane( Vec3 pnormal, float pd ) : normal( pnormal ), d( pd ) {} | |
Vec3 normal; | |
float d; | |
}; | |
void ResetPlanes(); | |
void AddPlane( const Plane& plane ); | |
void PrintPlanes(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct TrajectoryResult | |
{ | |
Vec3 m_EndPoint; | |
float m_Time; | |
bool m_ValidHit; | |
}; | |
Vec3 getNextPositionInTrajectory(const Vec3& position, const Vec3& velocity, const Vec3& up_vector, float gravity_accel, float time) { | |
return Vec3( | |
position.x + velocity.x * time + 0.5f * (up_vector.x * gravity_accel * time * time), | |
position.y + velocity.y * time + 0.5f * (up_vector.y * gravity_accel * time * time), | |
position.z + velocity.z * time + 0.5f * (up_vector.z * gravity_accel * time * time) | |
); | |
} | |
Vec3 getNextVelocityInTrajectory(const Vec3& velocity, const Vec3& up_vector, float gravity_accel, float time) { | |
return Vec3( | |
velocity.x + up_vector.x * gravity_accel * time, | |
velocity.y + up_vector.y * gravity_accel * time, | |
velocity.z + up_vector.z * gravity_accel * time | |
); | |
} | |
float solveQuadraticEquationForTime(float a, float b, float c) { | |
float r1 = (-b + Sqrtf(b * b - (4.0f * a * c))) / (2 * a); | |
float r2 = (-b - Sqrtf(b * b - (4.0f * a * c))) / (2 * a); | |
// Debug("Quadartic Sol: %f %f", r1, r2); | |
if (r1 > 0 && r2 > 0) { | |
return Minf(r1, r2); | |
} | |
else { | |
return Maxf(r1, r2); | |
} | |
} | |
float getEuclideanDistance(const Vec3& v1, const Vec3& v2) { | |
return Sqrtf((v2.x - v1.x) * (v2.x - v1.x) + (v2.y - v1.y) * (v2.y - v1.y) + (v2.z - v1.z) * (v2.z - v1.z)); | |
} | |
TrajectoryResult PredictTrajectory(const Vec3& start_position, const Vec3& start_velocity, const Vec3& up_vector, float gravity_accel, float raycast_time_step, float max_time) | |
{ | |
float delta = raycast_time_step; | |
TrajectoryResult result; | |
result.m_ValidHit = false; | |
result.m_Time = max_time; | |
Physics::QueryResult rayResult; | |
float elapsedTime = delta; | |
Vec3 lastPosition; | |
Vec3 position = start_position; | |
Vec3 lastVelocity; | |
Vec3 velocity = start_velocity; | |
while (elapsedTime < max_time) { | |
lastPosition = position; | |
lastVelocity = velocity; | |
position = getNextPositionInTrajectory(position, velocity, up_vector, gravity_accel, delta); | |
velocity = getNextVelocityInTrajectory(velocity, up_vector, gravity_accel, delta); | |
// Collision Detection | |
rayResult = Physics::Raycast(lastPosition, position); | |
if (rayResult.m_ValidHit) { | |
position = rayResult.m_HitPos; | |
if (raycast_time_step == delta) { | |
elapsedTime -= raycast_time_step; | |
} | |
// Debug("%f", elapsedTime); | |
float t = 0.0f; | |
if (!IsEqualf(getEuclideanDistance(lastPosition, position), 0.0f, kZeroTolTime)) { | |
t = solveQuadraticEquationForTime(0.5f * gravity_accel * up_vector.y, lastVelocity.y, lastPosition.y - position.y); | |
} | |
result.m_Time = elapsedTime + t; | |
result.m_ValidHit = true; | |
break; | |
} | |
// Step time correction at last iteration | |
elapsedTime += delta; | |
if (elapsedTime > max_time) { | |
elapsedTime -= delta; | |
delta = max_time - elapsedTime; | |
} | |
}// end of while | |
result.m_EndPoint = position; | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Vec3 | |
{ | |
public: | |
// Data Members | |
float x; | |
float y; | |
float z; | |
// Default Constructor | |
inline Vec3() = default; | |
// Explicit Constructors | |
constexpr explicit Vec3( float f ) : x( f ), y( f ), z( f ) {} | |
constexpr explicit Vec3( const float* f ) : x( f[0] ), y( f[1] ), z( f[2] ) {} | |
constexpr Vec3( float vx, float vy, float vz ) : x( vx ), y( vy ), z( vz ) {} | |
constexpr Vec3( const Vec3& v ) = default; | |
// Arithmetic Operators | |
inline Vec3 operator+ ( const float f ) const { return Vec3( x + f, y + f, z + f ); } | |
constexpr Vec3 operator+ ( const Vec3& v ) const { return Vec3( x + v.x, y + v.y, z + v.z ); } | |
inline Vec3 operator- ( const float f ) const { return Vec3( x - f, y - f, z - f ); } | |
constexpr Vec3 operator- ( const Vec3& v ) const { return Vec3( x - v.x, y - v.y, z - v.z ); } | |
constexpr Vec3 operator* ( const float f ) const { return Vec3( x * f, y * f, z * f ); } | |
inline Vec3 operator* ( const Vec3& v ) const { return Vec3( x * v.x, y * v.y, z * v.z ); } | |
inline Vec3 operator/ ( const float f ) const { float inv_f = 1.0f / f; return Vec3( x * inv_f, y * inv_f, z * inv_f ); } | |
inline Vec3 operator/ ( const Vec3& v ) const { return Vec3( x / v.x, y / v.y, z / v.z ); } | |
// Comparison Operators | |
inline bool operator== ( const Vec3& v ) const { return (x == v.x) && (y == v.y) && (z == v.z); } | |
inline bool operator!= ( const Vec3& v ) const { return (x != v.x) || (y != v.y) || (z != v.z); } | |
// Set functions | |
inline Vec3& Set( float vx, float vy, float vz ) { x = vx; y = vy; z = vz; return *this; } | |
inline Vec3& SetToZero() { x = 0.0f; y = 0.0f; z = 0.0f; return *this; } | |
inline Vec3& SetToUnit() { x = 1.0f; y = 1.0f; z = 1.0f; return *this; } | |
inline Vec3& SetToXAxis() { x = 1.0f; y = 0.0f; z = 0.0f; return *this; } | |
inline Vec3& SetToYAxis() { x = 0.0f; y = 1.0f; z = 0.0f; return *this; } | |
inline Vec3& SetToZAxis() { x = 0.0f; y = 0.0f; z = 1.0f; return *this; } | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment