Docs

Complete Physics Engine Documentation

This document consolidates the entire source code documentation into one place, covering every variable and every method. It is organized by module (Math, Shapes, Body, Collision, Contact, Force, World, Graphics, Application, and Main Entry) to give you a clear reference.


Table of Contents

  1. Math Module – Vec2
  2. Shapes Module – Shape, CircleShape, PolygonShape, BoxShape
  3. Rigid Body – Body
  4. Collision Handling – CollisionDetection and Contact
  5. Constants (Constants.h)
  6. Force Generators – Force
  7. World Management – World
  8. Graphics and Rendering – Graphics
  9. Application Control – Application
  10. Main Entry Point – Main.cpp
  11. Use Cases and Examples
  12. Final Remarks

1. Math Module – Vec2

Files:

  • Vec2.h
  • Vec2.cpp

Overview

  • Purpose: Encapsulates 2D vector arithmetic used for positions, velocities, forces, etc.

Data Members

  • float x
  • float y

Constructors / Destructor

  1. Vec2()

    • Initializes x and y to 0.
  2. Vec2(float x, float y)

    • Initializes x and y to the provided arguments.
  3. ~Vec2() = default

    • Default destructor.

Methods

  • void Add(const Vec2& v)
    Adds v.x to this->x and v.y to this->y.

  • void Sub(const Vec2& v)
    Subtracts v.x from this->x and v.y from this->y.

  • void Scale(float n)
    Multiplies both x and y by n.

  • Vec2 Rotate(float angle) const
    Returns a new vector rotated by angle radians.

  • float Magnitude() const
    Returns the length of the vector, sqrt(x*x + y*y).

  • float MagnitudeSquared() const
    Returns the square of the vector length, (x*x + y*y).

  • Vec2& Normalize()
    Normalizes the vector in-place if its magnitude is not zero.

  • Vec2 UnitVector() const
    Returns a normalized copy of this vector.

  • Vec2 Normal() const
    Returns a perpendicular (rotated 90 degrees) version of this vector and normalizes it.

  • float Dot(const Vec2& v) const
    Returns the dot product of this vector and v.

  • float Cross(const Vec2& v) const
    Returns a scalar cross product result of this vector and v.

Operators

  • = (assignment)
  • == (equality) and != (inequality)
  • +, -, *, / (scalar multiply/divide)
  • +=, -=, *=, /=
  • unary - (negates both components)

These operators enable natural arithmetic syntax with Vec2.


2. Shapes Module – Shape, CircleShape, PolygonShape, BoxShape

Files:

  • Shape.h
  • Shape.cpp

2.1 Shape (Abstract)

Data / Methods

  • virtual ~Shape() = default
  • virtual ShapeType GetType() const = 0
    Returns an enum value: CIRCLE, POLYGON, or BOX.
  • virtual Shape* Clone() const = 0
    Creates a copy of the shape on the heap.
  • virtual void UpdateVertices(float angle, const Vec2& position) = 0
    Updates shape vertices in world space.
  • virtual float GetMomentOfInertia() const = 0
    Returns the shape’s base moment of inertia (before multiplying by mass).

2.2 CircleShape

Data Members

  • float radius

Constructor / Destructor

  • CircleShape(const float radius)
    Initializes radius.
  • ~CircleShape()
    Logs destruction.

Methods

  • ShapeType GetType() const
    Returns CIRCLE.
  • Shape* Clone() const
    Creates a new CircleShape with the same radius.
  • void UpdateVertices(float angle, const Vec2& position)
    No-op for circles (no vertices to update).
  • float GetMomentOfInertia() const
    Returns 0.5 * radius * radius (before multiplying by mass).

2.3 PolygonShape

Data Members

  • std::vector<Vec2> localVertices
  • std::vector<Vec2> worldVertices

Constructor / Destructor

  • PolygonShape(const std::vector<Vec2> vertices)
    Copies the input vertices into both localVertices and worldVertices.
  • ~PolygonShape()
    Logs destruction.

Methods

  • ShapeType GetType() const
    Returns POLYGON.
  • Shape* Clone() const
    Copies the polygon by duplicating localVertices.
  • void UpdateVertices(float angle, const Vec2& position)
    Rotates each local vertex by angle, then adds position to produce worldVertices.
  • float GetMomentOfInertia() const
    Returns 5000.0f (placeholder).
  • Vec2 EdgeAt(int index) const
    Returns the vector from worldVertices[index] to worldVertices[(index+1) % size].
  • float FindMinSeparation(const PolygonShape* other, Vec2& axis, Vec2& point) const
    Scans each edge, projects vertices of the other polygon to find minimal separation.

2.4 BoxShape

  • float width
  • float height

Constructor / Destructor

  • BoxShape(float width, float height)
    Fills localVertices with the four rectangle corners (centered at origin).
  • ~BoxShape()
    Currently empty, marked as TODO.

Methods

  • ShapeType GetType() const
    Returns BOX.
  • Shape* Clone() const
    Allocates a new BoxShape(width, height).
  • float GetMomentOfInertia() const
    Returns (1/12)*(width^2 + height^2) before mass multiplication, approximated by 0.083333*(width^2 + height^2).

3. Rigid Body – Body

Files:

  • Body.h
  • Body.cpp

Data Members

  1. bool isColliding
  2. Vec2 position, velocity, acceleration
  3. float rotation, angularVelocity, angularAcceleration
  4. Vec2 sumForces
  5. float sumTorque
  6. float mass, invMass
  7. float I, invI
  8. float restitution
  9. float friction
  10. Shape* shape
  11. SDL_Texture* texture

Constructor / Destructor

  • Body(const Shape& shape, float x, float y, float mass)

    • Clones shape into this->shape.
    • Initializes position to (x, y), velocity and acceleration to zero.
    • Sets rotation, angularVelocity, angularAcceleration to zero.
    • Sets restitution = 1.0, friction = 0.7.
    • Computes invMass = (mass != 0) ? 1/mass : 0.
    • Computes moment of inertia I = shape.GetMomentOfInertia() * mass, and invI = (I != 0)?1/I:0.
    • Logs constructor call.
  • ~Body()

    • Deletes shape.
    • Destroys texture via SDL.
    • Logs destructor call.

Methods

  • bool IsStatic() const
    Returns true if invMass is near zero.

  • void AddForce(const Vec2& force)
    Accumulates an external force in sumForces.

  • void AddTorque(float torque)
    Accumulates torque in sumTorque.

  • void ClearForces() / void ClearTorque()
    Resets sumForces to (0,0) / sumTorque to 0.

  • void ApplyImpulse(const Vec2& j)
    If not static, changes velocity by j * invMass.

  • void ApplyImpulse(const Vec2& j, const Vec2& r)
    If not static, changes velocity by j * invMass and angularVelocity by r.Cross(j) * invI.

  • void SetTexture(const char* textureFileName)
    Uses SDL_image to load a texture. Logs an error if it fails.

  • void IntegrateLinear(float dt)

    • If the body is not static, updates acceleration = sumForces * invMass, then velocity += acceleration * dt, then position += velocity * dt, then clears forces.
  • void IntegrateAngular(float dt)

    • If not static, computes angularAcceleration = sumTorque * invI, updates angularVelocity += angularAcceleration * dt, then rotation += angularVelocity * dt, then clears torque.
  • void Update(float dt)

    • Calls IntegrateLinear(dt), IntegrateAngular(dt), and updates shape->UpdateVertices(rotation, position).

4. Collision Handling – CollisionDetection and Contact

4.1 CollisionDetection

Files:

  • CollisionDetection.h
  • CollisionDetection.cpp

Methods

  • static bool IsColliding(Body* a, Body* b, Contact& contact)
    Detects shape types and dispatches to appropriate collision function:

    • circle–circle
    • polygon–polygon (including box–box, box–polygon)
    • polygon–circle
  • static bool IsCollidingCircleCircle(Body* a, Body* b, Contact& contact)
    Checks distance between centers vs. sum of radii. If colliding, sets up contact.normal, contact.start/end near circle perimeters, and contact.depth.

  • static bool IsCollidingPolygonPolygon(Body* a, Body* b, Contact& contact)
    Uses each polygon’s FindMinSeparation method. If either separation is >= 0, no collision. Else, picks whichever side has the greatest overlap for contact data.

  • static bool IsCollidingPolygonCircle(Body* polygon, Body* circle, Contact& contact)
    Tests edges to see if circle center is outside or inside. Computes collision region (A/B/C). Sets contact with depth and normal if colliding.


4.2 Contact

Files:

  • Contact.h
  • Contact.cpp

Data Members

  • Body* a, *b
  • Vec2 start, end
  • Vec2 normal
  • float depth

Methods

  • void ResolvePenetration()

    • If both a and b are static, does nothing.
    • Calculates displacements da, db based on combined inverse mass and contact.depth.
    • Adjusts a->position and b->position along contact.normal by da * 0.8 and db * 0.8.
    • Updates shape vertices accordingly.
  • void ResolveCollision()

    • Calls ResolvePenetration().
    • Determines elasticity e = min(a->restitution, b->restitution) and friction f = min(a->friction, b->friction).
    • Computes relative velocity at contact points, calculates normal impulse, then friction impulse, applies them to a and b.

5. Constants (Constants.h)

File:

  • Constants.h

Defines:

  • FPS = 60
  • MILLISECS_PER_FRAME = 1000 / FPS
  • PIXELS_PER_METER = 50

Used for frame timing and scaling between meters and pixels.


6. Force Generators – Force

Files:

  • Force.h
  • Force.cpp

Methods

  • Vec2 GenerateDragForce(const Body& body, float k)
    If velocity is nonzero, returns a force opposite to velocity direction, magnitude proportional to |velocity|^2 * k.

  • Vec2 GenerateFrictionForce(const Body& body, float k)
    Returns a constant-magnitude force k, opposite to body’s velocity direction.

  • Vec2 GenerateSpringForce(const Body& body, const Vec2& anchor, float restLength, float k)
    Calculates displacement from body.position to anchor, then magnitude k * (distance - restLength), directed back toward anchor.

  • Vec2 GenerateSpringForce(const Body& a, const Body& b, float restLength, float k)
    Similar, but uses positions of two bodies as endpoints.

  • Vec2 GenerateGravitationalForce(const Body& a, const Body& b, float G, float minDistance, float maxDistance)
    Clamps distance-squared between minDistance and maxDistance. Direction is from a to b. Magnitude is G*(a.mass*b.mass)/(distance^2).


7. World Management – World

Files:

  • World.h
  • World.cpp

Data Members

  1. float G
  2. std::vector<Body*> bodies
  3. std::vector<Vec2> forces
  4. std::vector<float> torques

Constructor / Destructor

  • World(float gravity)
    • Sets G = -gravity (expect negative input to produce a downward force).
    • Logs creation.
  • ~World()
    • Deletes all Body* in bodies.
    • Logs destruction.

Methods

  • void AddBody(Body* body)
    Appends to bodies.

  • std::vector<Body*>& GetBodies()
    Returns reference to bodies.

  • void AddForce(const Vec2& force)
    Appends force to a list of global forces.

  • void AddTorque(float torque)
    Appends global torque to a list.

  • void Update(float dt)

    1. For each Body* in bodies, apply gravity as Vec2(0, mass * G * PIXELS_PER_METER).
    2. Apply any global forces/torques from forces / torques.
    3. Call body->Update(dt) for each.
    4. Perform multiple passes of collision detection/resolution (calls CheckCollisions() up to 10 times).
  • void CheckCollisions()
    Double loop over bodies. For each pair (i, j), resets a->isColliding = false and b->isColliding = false. If CollisionDetection::IsColliding(...), obtains a Contact and calls contact.ResolveCollision().


8. Graphics and Rendering – Graphics

Files:

  • Graphics.h
  • Graphics.cpp

Data Members

  • static int windowWidth, windowHeight
  • static SDL_Window* window
  • static SDL_Renderer* renderer

Methods

  • static bool OpenWindow()
    Initializes SDL, uses full-screen borderless mode, sets up renderer. Returns false on error.

  • static void CloseWindow()
    Destroys the renderer and window, calls SDL_Quit().

  • static int Width(), static int Height()
    Return windowWidth and windowHeight.

  • static void ClearScreen(Uint32 color)
    Sets draw color and clears the current rendering target.

  • static void RenderFrame()
    Presents the current frame (SDL double-buffer swap).

  • static void DrawLine(int x0, int y0, int x1, int y1, Uint32 color)
    Draws a line using SDL2_gfx’s lineColor.

  • static void DrawCircle(int x, int y, int radius, float angle, Uint32 color)
    Renders a circle, plus a line from center in the direction angle.

  • static void DrawFillCircle(int x, int y, int radius, Uint32 color)
    Renders a filled circle.

  • static void DrawRect(int x, int y, int width, int height, Uint32 color)
    Renders an unfilled rectangle, using lines.

  • static void DrawFillRect(int x, int y, int width, int height, Uint32 color)
    Renders a filled rectangle.

  • static void DrawPolygon(int x, int y, const std::vector<Vec2>& vertices, Uint32 color)
    Connects consecutive vertices with lines, plus a filled circle at (x, y).

  • static void DrawFillPolygon(int x, int y, const std::vector<Vec2>& vertices, Uint32 color)
    Uses filledPolygonColor from SDL2_gfx. Draws a 1-pixel circle at (x, y) in a darker color.

  • static void DrawTexture(int x, int y, int width, int height, float rotation, SDL_Texture* texture)
    Copies an SDL_Texture to the renderer, applying rotation (converted to degrees).


9. Application Control – Application

Files:

  • Application.h
  • Application.cpp

Data Members

  1. bool debug
  2. bool running
  3. World* world

Methods

  • bool IsRunning()
    Returns running.

  • void Setup()

    1. Calls Graphics::OpenWindow(), assigns result to running.
    2. Creates world = new World(-9.8).
    3. Adds floor, walls, a large static box to the world.
    4. Applies a wind force as a global force.
  • void Input()
    Polls SDL events.

    • On SDL_QUIT, sets running = false.
    • On SDL_KEYDOWN with Escape, sets running = false, or toggles debug with d.
    • On SDL_MOUSEBUTTONDOWN, depending on button (left/right/middle), spawns a circle or box body with different textures (basketball, crate, bowling ball).
  • void Update()

    1. Clears the screen with a background color.
    2. Manages frame timing to target MILLISECS_PER_FRAME.
    3. Computes deltaTime.
    4. Calls world->Update(deltaTime) to step physics.
  • void Render()

    1. Loops over world->GetBodies().
    2. Checks shape type. If debug is false and texture exists, draws texture; otherwise, draws wireframe or polygon fill.
    3. Calls Graphics::RenderFrame() at the end.
  • void Destroy()
    Deletes world and closes the SDL window.


10. Main Entry Point – Main.cpp

File:

  • Main.cpp

Overview

int main(int argc, char* args[]) {
    Application app;
 
    app.Setup();
 
    while (app.IsRunning()) {
        app.Input();
        app.Update();
        app.Render();
    }
 
    app.Destroy();
    return 0;
}