Run build.sh in the root directory to build and install the library. Include the main header in your source files:
#include <libgolf.hpp>
The library uses a phase-based flight simulation architecture that automatically transitions between aerial, bounce, and roll phases. A complete simulation requires two inputs: launch data and atmospheric conditions.
// {ballSpeedMph, launchAngleDeg, directionDeg, backspinRpm, sidespinRpm}
const LaunchData ball{160.0f, 11.0f, 0.0f, 3000.0f, 0.0f};
These fields match the output of a typical launch monitor. An optional start position can be provided in feet:
LaunchData ball{160.0f, 11.0f, 0.0f, 3000.0f, 0.0f};
ball.startX = 0.0f; // feet, lateral
ball.startY = 0.0f; // feet, downrange
ball.startZ = 0.0f; // feet, height above sea level
// {tempF, windX, windY, windZ, windDir, humidity, pressure}
const AtmosphericData atmos{70.0f, 0.0f, 0.0f, 0.0f, 0.0f, 50.0f, 29.92f};
Field definitions are documented in include/atmosphere.hpp.
GroundSurface ground; // Uses default fairway properties
// Or with custom values:
// GroundSurface green{0.0f, 0.35f, 0.4f, 0.12f, 0.95f, 0.85f};
// {height, restitution, frictionStatic, frictionDynamic, firmness, spinRetention}
For simulations requiring different ground types throughout the trajectory (e.g., fairway → rough → green), implement the GroundProvider interface:
class MyGroundProvider : public GroundProvider {
public:
GroundSurface getGroundAt(float x, float y) const override {
// Return different surfaces based on position
// x = lateral position (feet), y = downrange position (feet)
}
};
MyGroundProvider provider;
FlightSimulator sim(ball, atmos, provider);
See Ground Providers Guide for details.
FlightSimulator sim(ball, atmos, ground);
sim.run(); // uses default 10ms time step
LandingResult result = sim.getLandingResult();
printf("Distance: %.1f yards\n", result.distance);
printf("Bearing: %.1f degrees\n", result.bearing);
LandingResult contains:
xF, yF, zF — final position in yardsdistance — total distance in yardsbearing — direction in degreestimeOfFlight — total simulation time in secondsTo capture the complete flight path for visualization or analysis:
FlightSimulator sim(ball, atmos, ground);
auto trajectory = sim.runAndGetTrajectory(); // vector of BallState
for (const auto& state : trajectory) {
printf("%.1f %.1f %.1f\n",
state.position[0] / physics_constants::YARDS_TO_FEET,
state.position[1] / physics_constants::YARDS_TO_FEET,
state.position[2]);
}
See examples/calculate_ball_trajectory.cpp for a complete implementation.
Both run() and runAndGetTrajectory() accept an optional time step in seconds (default 0.01f):
sim.run(0.005f); // 5ms time step for higher resolution
After run(), the final ball state is available via getState():
const BallState& finalState = sim.getState();
// finalState.position — Vector3D in feet
// finalState.velocity — Vector3D in ft/s
// finalState.spinRate — rad/s
// finalState.currentTime — seconds
Physics variables computed at launch (air density, Reynolds number, etc.) are accessible via:
const GolfBallPhysicsVariables& vars = sim.getPhysicsVariables();
float rho = vars.getRhoImperial(); // slugs/ft³
The library uses a right-handed coordinate system:
All position and velocity components are in feet. Use physics_constants::YARDS_TO_FEET for unit conversion when needed.
The simulator automatically manages three flight phases:
The current phase can be queried using sim.getCurrentPhaseName(), which returns "aerial", "bounce", "roll", or "complete".
When using a GroundProvider instead of a single GroundSurface, the simulator automatically queries ground properties at the ball’s current position during phase transitions. This enables realistic modeling of:
Ground is queried before each bounce and periodically during rolling (every 0.1s), so the ball automatically picks up surface changes as it moves. See the Ground Providers Guide for details.
The examples/ directory contains complete working implementations: