feather

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2025 License: Apache-2.0 Imports: 9 Imported by: 0

README

Feather

GitHub go.mod Go version License Go Reference Go Report Card Tests Codecov GitHub Issues or Pull Requests GitHub Issues or Pull Requests

A Go physic library, based on the XPBD solver algorithm.

XPBD

The current implementation simplifies the initial algorithm found on the internet:

while simulating do
    CollectCollisionPairs();
    h ← Δt/numSubsteps;
    for numSubsteps do
        for n bodies and particles do
            x_prev ← x;
            v ← v + h*f_ext/m;
            x ← x + h*v;
        end
        for numPosIters do
            SolvePositions(x₁,...,xₙ);
        end
        for n bodies and particles do
            v ← (x - x_prev)/h;
        end
        SolveVelocities(v₁,...,vₙ);
    end
end

In the papers, the CollectCollisionPairs is applies once, and seems to use some Continuous Collision Detection.

while simulating do
    h ← Δt/numSubsteps;

    for numSubsteps do
        for n bodies and particles do
            x_prev ← x;
            v ← v + h*f_ext/m;
            x ← x + h*v;
        end
        
        cp ← BroadPhaseCollectCollisionPairs();
        contacts ← CollectCollisionPairs(cp);

        SolvePositions(contacts);
        
        for n bodies and particles do
            v ← (x - x_prev)/h;
        end
        
        SolveVelocities(v₁,...,vₙ);
    end
end

As explained in https://matthias-research.github.io/pages/publications/PBDBodies.pdf: "Finally, the concern regarding slow convergence was addressed most recently in [MSL∗19]. By replacing solver iterations with substeps, Gauss-Seidel and Jacobi methods become competitors of global solvers in terms of convergence. Substepping in combination with one NPGS iteration per substep yields a method that looks computationally almost identical to an explicit integration step, but with the advantage of being unconditionally stable due to the usage of compliance. We call it a quasi-explicit method.".

  • It means we can remove the iterations of the solver, using substepping.
  • We also apply the velocity/forces first, per body, and then look at if any constraint/collision.

Note: XPBD computes the position, with an implicit velocity. But this paradigm stops for the friction and the restitution forces. The last computation in the substeps is SolveVelocities, a dedicated and required step to compute any optional force. This given velocity is computed by the constraints, and then used in the next world.Step.

Constraints
  • ContactConstraint: temporary constraint, generated when a collision is detected between two rigid bodies.

A not exhaustive list of possible constraints (not implemented yet):

  • Friction: Opposes tangential motion at contact points. Usage: Realistic sliding, grip, objects staying on slopes
  • Manifold (multi point contact): multiple contact points. Usage: Stacking stable, boxes
  • Distance: Maintains constant distance between two points. Usage: Ropes, chains, rigid connections, ragdoll bones
  • Distance Range: Keeps distance within [min, max] range. Usage: Elastic ropes, springs with limits, telescopic joints
  • Hinge: Allows rotation around one axis only (like a door). Usage: Doors, wheels, joints, rotating platforms
  • Angular Range: limits rotation within [min/max]. Usage: articulation

GJK

EPA

Sources

Contributing Guidelines

See how to contribute.

Licence

This project is distributed under the Apache 2.0 licence.

Documentation

Index

Constants

View Source
const (
	CONCRETE_COMPLIANCE = 0.04e-9
	WOOD_COMPLIANCE     = 0.16e-9
	LEATHER_COMPLIANCE  = 14e-8
	TENDON_COMPLIANCE   = 0.2e-7
	RUBBER_COMPLIANCE   = 1e-6
	MUSCLE_COMPLIANCE   = 0.2e-3
	FAT_COMPLIANCE      = 1e-3
)
View Source
const DEFAULT_WORKERS = 1
View Source
const STIFF_COMPLIANCE = CONCRETE_COMPLIANCE

Variables

This section is empty.

Functions

func BroadPhase

func BroadPhase(spatialGrid *SpatialGrid, bodies []*actor.RigidBody, workersCount int) <-chan Pair

BroadPhase performs broad-phase collision detection using AABB overlap tests It returns pairs of bodies whose AABBs overlap and might be colliding This is an O(n²) brute-force approach suitable for small numbers of bodies

func EPA

func EPA(p <-chan CollisionPair, workersCount int) <-chan *constraint.ContactConstraint

func GJK

func GJK(pairChan <-chan Pair, workersCount int) <-chan CollisionPair

func NarrowPhase

func NarrowPhase(pairs <-chan Pair, workersCount int) []*constraint.ContactConstraint

Types

type Cell

type Cell struct {
	// contains filtered or unexported fields
}

Cell - Container of body indices in a cell

type CellKey

type CellKey struct {
	X, Y, Z int
}

CellKey - Coordinates of a cell in 3D space

type CollisionEnterEvent added in v0.2.0

type CollisionEnterEvent struct {
	BodyA *actor.RigidBody
	BodyB *actor.RigidBody
}

Collision events

func (CollisionEnterEvent) Type added in v0.2.0

func (e CollisionEnterEvent) Type() EventType

type CollisionExitEvent added in v0.2.0

type CollisionExitEvent struct {
	BodyA *actor.RigidBody
	BodyB *actor.RigidBody
}

func (CollisionExitEvent) Type added in v0.2.0

func (e CollisionExitEvent) Type() EventType

type CollisionPair

type CollisionPair struct {
	BodyA *actor.RigidBody
	BodyB *actor.RigidBody
	// contains filtered or unexported fields
}

CollisionPair represents a pair of rigid bodies that potentially collide

type CollisionStayEvent added in v0.2.0

type CollisionStayEvent struct {
	BodyA *actor.RigidBody
	BodyB *actor.RigidBody
}

func (CollisionStayEvent) Type added in v0.2.0

func (e CollisionStayEvent) Type() EventType

type Event added in v0.2.0

type Event interface {
	Type() EventType
}

Event interface - all events implement this

type EventListener added in v0.2.0

type EventListener func(event Event)

EventListener - callback for events

type EventType added in v0.2.0

type EventType uint8
const (
	TRIGGER_ENTER EventType = iota
	COLLISION_ENTER
	TRIGGER_STAY
	COLLISION_STAY
	TRIGGER_EXIT
	COLLISION_EXIT
	ON_SLEEP
	ON_WAKE
)

type Events added in v0.2.0

type Events struct {
	// contains filtered or unexported fields
}

Events manager

func NewEvents added in v0.2.0

func NewEvents() Events

func (*Events) Subscribe added in v0.2.0

func (e *Events) Subscribe(eventType EventType, listener EventListener)

Subscribe adds a listener for an event type

type Pair

type Pair struct {
	BodyA *actor.RigidBody
	BodyB *actor.RigidBody
}

Pair - Pair of bodies potentially in collision

type SleepEvent added in v0.2.0

type SleepEvent struct {
	Body *actor.RigidBody
}

Sleep/Wake events

func (SleepEvent) Type added in v0.2.0

func (e SleepEvent) Type() EventType

type SpatialGrid

type SpatialGrid struct {
	// contains filtered or unexported fields
}

SpatialGrid - Uniform spatial grid with hashing for broad phase

func NewSpatialGrid

func NewSpatialGrid(cellSize float64, numCells int) *SpatialGrid

NewSpatialGrid - Creates a new spatial grid

func (*SpatialGrid) Clear

func (sg *SpatialGrid) Clear()

Clear - Resets the spatial grid by clearing all body indices from cells and planes

func (*SpatialGrid) FindPairsParallel

func (sg *SpatialGrid) FindPairsParallel(bodies []*actor.RigidBody, workersCount int) <-chan Pair

FindPairsParallel - Parallel version returning a channel

func (*SpatialGrid) Insert

func (sg *SpatialGrid) Insert(bodyIndex int, body *actor.RigidBody)

Insert - Inserts a body into all cells it occupies

func (*SpatialGrid) SortCells

func (sg *SpatialGrid) SortCells()

SortCells - Sorts body indices within each cell for optimized collision detection

type TriggerEnterEvent added in v0.2.0

type TriggerEnterEvent struct {
	BodyA *actor.RigidBody
	BodyB *actor.RigidBody
}

Trigger events

func (TriggerEnterEvent) Type added in v0.2.0

func (e TriggerEnterEvent) Type() EventType

type TriggerExitEvent added in v0.2.0

type TriggerExitEvent struct {
	BodyA *actor.RigidBody
	BodyB *actor.RigidBody
}

func (TriggerExitEvent) Type added in v0.2.0

func (e TriggerExitEvent) Type() EventType

type TriggerStayEvent added in v0.2.0

type TriggerStayEvent struct {
	BodyA *actor.RigidBody
	BodyB *actor.RigidBody
}

func (TriggerStayEvent) Type added in v0.2.0

func (e TriggerStayEvent) Type() EventType

type WakeEvent added in v0.2.0

type WakeEvent struct {
	Body *actor.RigidBody
}

func (WakeEvent) Type added in v0.2.0

func (e WakeEvent) Type() EventType

type World

type World struct {
	// List of all rigid bodies in the world
	Bodies []*actor.RigidBody
	// Gravity acceleration (m/s², or N/kg)
	Gravity     mgl64.Vec3
	Substeps    int
	SpatialGrid *SpatialGrid
	Workers     int

	Events Events
}

func (*World) AddBody

func (w *World) AddBody(body *actor.RigidBody)

AddBody adds a rigid body to the world

func (*World) RemoveBody

func (w *World) RemoveBody(body *actor.RigidBody)

RemoveBody removes a rigid body from the world

func (*World) Step

func (w *World) Step(dt float64)

Directories

Path Synopsis
Package epa implements the Expanding Polytope Algorithm for computing penetration depth.
Package epa implements the Expanding Polytope Algorithm for computing penetration depth.
Package gjk implements the Gilbert-Johnson-Keerthi (GJK) algorithm for collision detection.
Package gjk implements the Gilbert-Johnson-Keerthi (GJK) algorithm for collision detection.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL