Help us shape the future of Go! Take the 2026 Go Developer Survey

dbox2d

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2026 License: MIT Imports: 4 Imported by: 0

README

dbox2d

dbox2d is a deterministic 2D rigid body solver for Go. It computes with signed Q32.32 fixed-point arithmetic from fixed, so equal inputs produce the same result bits on every supported architecture, on every run.

The module is pre-v1. Its import path and its API may change before the first stable release. It requires Go 1.26.4 or newer.

The port covers its foundation, the narrowphase and the scalar contact solver: worlds, bodies, shapes, mass computation, a determinism checksum, contact manifolds for every shape pair, the distance solver, the shape casts and the time of impact, the contact bookkeeping, the islands with sleep and wake, the constraint graph, the soft-step contact solver, the body and contact events, the dynamic trees, the broadphase and the AABB, ray, shape and mover queries of the world. Step finds the new pairs, updates the contacts, solves the joints and the contacts, sweeps the fast bodies and the bullets against the world so they stop at their first time of impact, and puts resting islands to sleep. Sensors and the character mover wait. PORTING.md tracks what has landed.

Fidelity contract

dbox2d is a port of Box2D v3.1.1, not a rewrite. It keeps the upstream file decomposition, the upstream names without the b2 prefix, and the upstream order of operations. Years of edge-case work are the reason the port exists, and a faithful port lets each function be compared against its upstream counterpart.

The port preserves the upstream formulation, not its output bits. Box2D computes in floating point; dbox2d computes in fixed point, so the two produce different trajectories. Every place where fixed-point arithmetic forbids the original line is a divergence, and every divergence carries a reason and a test in DIVERGENCES.md. PORTING.md maps each upstream file to its Go counterpart and to how faithful that port is.

dbox2d is not affiliated with the Box2D project, and it is neither endorsed nor supported by its author. Report defects here, never upstream.

Install

go get github.com/dhannyell/dbox2d

Performance

Fixed point buys determinism and pays in speed. The repository measures that price with eight benchmark pairs and one bullet composite in bench_test.go. Each pair runs the Q32.32 code against a line-by-line float64 mirror of the same code, which stands in for the floating-point formulation of the reference.

Benchmark (amd64) Median time Allocations
Pyramid Step, 210 boxes, 590 contacts, 4 sub-steps, Q32.32 ~2.1 ms 0
Pyramid Step, 210 boxes, 590 contacts, 4 sub-steps, float64 mirror ~0.64 ms 0
Free-fall Step, 1024 bodies, 4 sub-steps, Q32.32 ~0.36 ms 0
Free-fall Step, 1024 bodies, 4 sub-steps, float64 mirror ~0.11 ms 0
Velocity integration only, 1024 bodies, Q32.32 ~31 µs 0
Velocity integration only, 1024 bodies, float64 mirror ~4.4 µs 0
One CollidePolygons, two boxes, Q32.32 ~0.40 µs 0
One CollidePolygons, two boxes, float64 mirror ~0.091 µs 0
Broadphase pair update, pyramid, every proxy moved, Q32.32 ~75 µs 0
Broadphase pair update, pyramid, every proxy moved, float64 mirror ~79 µs 0
One tree query, 100 boxes, four hits, Q32.32 ~0.14 µs 0
One tree query, 100 boxes, four hits, float64 mirror ~0.14 µs 0
One ShapeDistance, two rotated boxes, cold cache, Q32.32 ~0.33 µs 0
One ShapeDistance, two rotated boxes, cold cache, float64 mirror ~0.082 µs 0
One TimeOfImpact, a turning box that hits, Q32.32 ~2.5 µs 0
One TimeOfImpact, a turning box that hits, float64 mirror ~0.46 µs 0
Bullet Step, 64 fast boxes bouncing between two walls, half bullets, 4 sub-steps, Q32.32 ~59 µs 0
Pyramid step, solver probe on a Q16.16 grid with Q48.16 sums, test only ~1.7 ms 0
Pyramid step, solver probe on a Q20.12 grid with 64-bit sums, test only ~1.4 ms 0
Pyramid step, solver probe with the state in Q32.32 and each contact in Q16.16 lanes, test only ~2.5 ms 0
Pyramid step, the same probe with the contacts colored and solved through the Q16 batch functions, scalar kernels, test only ~1.9 ms 0
Pyramid step, the same probe on the AVX2 kernels (GOEXPERIMENT=simd, Go 1.27), test only ~1.6 ms 0

The composite numbers are the honest ones. The pyramid, a settled stack that collides and solves every contact on every step, runs about 3.3× slower than its float64 mirror and allocates nothing once its contacts are active. The first step that activates contacts grows the graph colors, the arena and the event buffers once, as the reference does; every step after that allocates nothing. The free-fall step, with no contacts, pays about 3.4×. The micro pairs explain where the cost lives: the velocity integrator alone pays about 7×, because each Q division is a 128-by-64-bit hardware divide and the damping factor takes three of them per body, and the polygon collider pays about 4.4×. The rest of the pipeline, with its bookkeeping, square roots and bounds work, dilutes those hot spots. The pyramid mirror keeps one constraint list instead of the graph colors and skips the island and event bookkeeping, so its ratio is an upper bound. The broadphase pays nothing: the tree walks compare bounds and sum perimeters, which cost the same in both formats, so the pair update and the tree query run at parity. The pyramid mirror takes its pairs from a float64 mirror of the tree. The iterative geometry pays about 4× on the distance solver and about 5× on the time of impact: each iteration normalizes a direction and the root finder divides. The bullet composite has no mirror; it pins the cost and the allocation contract of the continuous stage, at less than a microsecond per fast body.

The probe lines run the contact solver of the pyramid on narrower grids inside probe_q16_test.go and probe_wide_test.go. The first two keep the state on the narrow grid. The third keeps the state and the impulse sums in Q32.32, reads them into Q16.16 lanes for each contact, and writes back only the delta. The last two color the contacts so that no two in one color share a dynamic body, and run each color as slices through the Batch*16 functions of fixed; the scalar and the AVX2 kernels give the same bits. The probe measures the behaviour and the throughput of those grids only; the library keeps Q32.32.

The fixed v0.3.0 release moved these numbers: its Q32.Mul now inlines, and its Normalize skips two divisions when the length is already one. The integrator dropped about a quarter and the collider about a third against the previous snapshot, with the same result bits.

These numbers come from one machine (Ryzen 7 5800X3D) and one snapshot of the code. Run go test -run "^$" -bench . -benchmem for your own.

Reference source

The upstream C source sits in this repository on the branch reference/box2d-v3.1.1, with the upstream history up to that tag. The branch never merges into main, it never builds, and no Go file imports it. It exists so that the porting work has one pinned, versioned reference that still answers why a line looks the way it does:

git show reference/box2d-v3.1.1:src/manifold.c
git blame reference/box2d-v3.1.1 -- src/manifold.c

The upstream tags are deliberately absent. Go derives module versions from tags, so an upstream tag here would publish a version of this module that points at C source.

The Go module zip contains only the tagged tree, so go get never downloads the reference source.

License

MIT. This is a derivative work of Box2D, which is also MIT. See LICENSE.

Documentation

Overview

Package dbox2d implements a deterministic 2D rigid body solver.

The package computes with the Q32.32 fixed-point arithmetic of github.com/dhannyell/fixed. Equal inputs produce the same result bits on every supported architecture, on every run. A world therefore survives a snapshot, a replay and a rollback without drift.

Fidelity

The package is a port of Box2D v3.1.1. It keeps the upstream file decomposition, the upstream names without the b2 prefix, and the upstream order of operations. The port preserves the upstream formulation, not its output bits. Box2D computes in floating point, so the two libraries produce different trajectories.

Fixed-point arithmetic forbids some upstream lines, such as an epsilon tuned for float or a stopping criterion that depends on it. Each such place is a recorded divergence with a reason and a test.

Angles

An angle is a turn, not a radian, because a turn reduces without pi. The solver stores an orientation as a github.com/dhannyell/fixed.Rot sine and cosine pair, never as an angle.

IDs

WorldId, BodyId, ShapeId, ChainId and JointId are opaque handles. Their zero values are null, and IDs of the same type can be compared with ==. Pass them by value and obtain them from package functions; constructing a packed value by hand may make it refer to whatever occupies that slot.

Accumulation

Saturated addition is not associative near the range limits. The solver keeps a fixed accumulation order for that reason. An executor that changes the order changes the result bits, so it must prove bit equality against the scalar path.

Index

Examples

Constants

View Source
const (
	DefaultCategoryBits uint64 = 1
	DefaultMaskBits     uint64 = math.MaxUint64
)

Default filter bits. upstream B2_DEFAULT_CATEGORY_BITS, B2_DEFAULT_MASK_BITS

View Source
const MaxPolygonVertices = 8

MaxPolygonVertices is the vertex limit of a convex polygon. Raising it costs performance even for shapes that use fewer vertices.

Variables

This section is empty.

Functions

func AABBContains

func AABBContains(a, b AABB) bool

AABBContains reports whether a fully contains b.

func AABBOverlaps

func AABBOverlaps(a, b AABB) bool

AABBOverlaps reports whether a and b overlap.

func Checksum

func Checksum(worldId WorldId) uint64

Checksum folds the complete deterministic state of a world into one integer. Application data and internal ids are excluded because they do not affect simulation. Bodies, shapes, contacts and joints use commutative folds, so equivalent worlds do not depend on creation order.

func ClampInt

func ClampInt(a, lower, upper int) int

ClampInt returns a limited to the range [lower, upper].

func DestroyBody

func DestroyBody(bodyId BodyId)

DestroyBody destroys a body. Every shape attached to it goes away too.

func DestroyJoint added in v0.3.0

func DestroyJoint(jointId JointId)

DestroyJoint destroys a joint and wakes the two bodies.

func DestroyShape

func DestroyShape(shapeId ShapeId, updateBodyMass bool)

DestroyShape destroys a shape. Pass updateBodyMass true to recompute the mass of the body from the remaining shapes.

func DestroyWorld

func DestroyWorld(worldId WorldId)

DestroyWorld destroys a world and every body and shape in it.

func GetLengthAndNormalize

func GetLengthAndNormalize(v Vec2) (Q, Vec2)

GetLengthAndNormalize returns the length of v and the unit vector with the same direction. The zero vector returns a zero length and the zero vector.

func IsNormalized

func IsNormalized(a Vec2) bool

IsNormalized reports whether a has unit length.

func IsNormalizedRot

func IsNormalizedRot(q Rot) bool

IsNormalizedRot reports whether q has unit length.

func IsValidAABB

func IsValidAABB(a AABB) bool

IsValidAABB reports whether a is usable and not inverted.

func IsValidPlane

func IsValidPlane(a Plane) bool

IsValidPlane reports whether a has a unit normal and a usable offset.

func IsValidQ

func IsValidQ(a Q) bool

IsValidQ reports whether a is a usable value. Fixed-point arithmetic has no NaN and no infinity; it saturates instead, so a saturated value is the signal that a computation left the representable range.

func IsValidRay

func IsValidRay(input *RayCastInput) bool

IsValidRay reports whether a ray cast input is usable.

func IsValidRotation

func IsValidRotation(q Rot) bool

IsValidRotation reports whether q is a usable and normalized rotation.

func IsValidVec2

func IsValidVec2(v Vec2) bool

IsValidVec2 reports whether v is a usable vector.

func PointInCapsule

func PointInCapsule(point Vec2, shape *Capsule) bool

PointInCapsule reports whether a point overlaps a capsule in local space.

func PointInCircle

func PointInCircle(point Vec2, shape *Circle) bool

PointInCircle reports whether a point overlaps a circle in local space.

func Step

func Step(worldId WorldId, timeStep Q, subStepCount int)

Step advances the simulation by timeStep, split into subStepCount sub-steps. The reference recommends a fixed time step and 4 sub-steps. It corresponds to b2World_Step in src/world.c.

func StoreBodyId

func StoreBodyId(id BodyId) uint64

StoreBodyId packs a body id into a uint64.

func StoreChainId

func StoreChainId(id ChainId) uint64

StoreChainId packs a chain id into a uint64.

func StoreJointId

func StoreJointId(id JointId) uint64

StoreJointId packs a joint id into a uint64.

func StoreShapeId

func StoreShapeId(id ShapeId) uint64

StoreShapeId packs a shape id into a uint64.

func StoreWorldId

func StoreWorldId(id WorldId) uint32

StoreWorldId packs a world id into a uint32.

func ValidateHull

func ValidateHull(hull *Hull) bool

ValidateHull reports whether a hull is convex and free of collinear points. It is expensive, so it does not belong in a running simulation.

Types

type AABB

type AABB struct {
	LowerBound Vec2
	UpperBound Vec2
}

AABB is an axis-aligned bounding box.

func AABBUnion

func AABBUnion(a, b AABB) AABB

AABBUnion returns the smallest box that contains a and b.

func ComputeCapsuleAABB

func ComputeCapsuleAABB(shape *Capsule, xf Transform) AABB

ComputeCapsuleAABB returns the bounding box of a transformed capsule.

func ComputeCircleAABB

func ComputeCircleAABB(shape *Circle, xf Transform) AABB

ComputeCircleAABB returns the bounding box of a transformed circle.

func ComputePolygonAABB

func ComputePolygonAABB(shape *Polygon, xf Transform) AABB

ComputePolygonAABB returns the bounding box of a transformed polygon.

func ComputeSegmentAABB

func ComputeSegmentAABB(shape *Segment, xf Transform) AABB

ComputeSegmentAABB returns the bounding box of a transformed segment.

func MakeAABB

func MakeAABB(points []Vec2, radius Q) AABB

MakeAABB returns the box that bounds a set of circles of the given radius. It panics when points is empty.

type BodyDef

type BodyDef struct {
	// The body type: static, kinematic or dynamic.
	Type BodyType

	// The initial world position. Create a body at its final position:
	// creating it at the origin and moving it costs nearly twice as much.
	Position Vec2

	// The initial world rotation. Use MakeRot for an angle in turns.
	Rotation Rot

	// The initial linear velocity of the body origin, usually in meters per
	// second.
	LinearVelocity Vec2

	// The initial angular velocity, in turns per second. The reference uses
	// radians per second; an angle is a turn in this package.
	AngularVelocity Q

	// Linear damping reduces the linear velocity. A value larger than 1 is
	// valid but grows sensitive to the time step. Usually undesirable,
	// because it makes bodies move as if they float.
	LinearDamping Q

	// Angular damping reduces the angular velocity. A value larger than 1 is
	// valid but grows sensitive to the time step.
	AngularDamping Q

	// Scale of the gravity on this body, non-dimensional.
	GravityScale Q

	// Sleep speed threshold, default 0.05 meters per second.
	SleepThreshold Q

	// Optional body name for debugging, up to 31 bytes.
	Name string

	// Application data attached to the body.
	UserData any

	// Set this to false if the body must never fall asleep.
	EnableSleep bool

	// Whether the body starts awake.
	IsAwake bool

	// Prevent the body from rotating. Useful for characters.
	FixedRotation bool

	// Treat the body as a high speed object that performs continuous
	// collision against dynamic and kinematic bodies, but not against other
	// bullets. Use sparingly: bullets solve no general dynamic-versus-dynamic
	// case and may interfere with joints.
	IsBullet bool

	// A disabled body does not move and does not collide.
	IsEnabled bool

	// Let the body bypass the rotational speed limit. Only for circular
	// bodies, like wheels.
	AllowFastRotation bool
	// contains filtered or unexported fields
}

BodyDef holds the data to construct a rigid body. It is a temporary bundle of creation parameters; shapes come after construction. Initialize it with DefaultBodyDef.

func DefaultBodyDef

func DefaultBodyDef() BodyDef

DefaultBodyDef returns the default body definition.

type BodyEvents added in v0.3.0

type BodyEvents struct {
	MoveEvents []BodyMoveEvent
}

BodyEvents holds the body events of the last step. The slice stays valid until the next step; a body destroy makes its entry stale.

func GetBodyEvents added in v0.3.0

func GetBodyEvents(worldId WorldId) BodyEvents

GetBodyEvents returns the move events of the last step. It corresponds to b2World_GetBodyEvents in src/world.c.

type BodyId

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

BodyId identifies a body. Its zero value is null.

func CreateBody

func CreateBody(worldId WorldId, def *BodyDef) BodyId

CreateBody creates a rigid body from a definition. The definition must come from DefaultBodyDef and is not retained.

func LoadBodyId

func LoadBodyId(x uint64) BodyId

LoadBodyId unpacks a body id from a uint64.

func (BodyId) IsNull

func (id BodyId) IsNull() bool

IsNull reports whether the id references nothing.

func (BodyId) IsValid

func (id BodyId) IsValid() bool

IsValid reports whether the id references a live body.

func (BodyId) Mass

func (bodyId BodyId) Mass() Q

Mass returns the mass of the body, usually in kilograms.

func (BodyId) Position

func (bodyId BodyId) Position() Vec2

Position returns the world position of the body origin.

func (BodyId) Rotation

func (bodyId BodyId) Rotation() Rot

Rotation returns the world rotation of the body.

func (BodyId) ShapeCount

func (bodyId BodyId) ShapeCount() int

ShapeCount returns the number of shapes on the body.

type BodyMoveEvent added in v0.3.0

type BodyMoveEvent struct {
	Transform  Transform
	BodyId     BodyId
	UserData   any
	FellAsleep bool
}

BodyMoveEvent reports a body that the simulation moved. A body that the user moves does not report one. FellAsleep tells the application that it can sleep the object of the body. With sleep disabled, every dynamic and kinematic body reports on every step.

type BodyType

type BodyType int

BodyType selects how the solver treats a body.

const (
	// StaticBody has zero mass and zero velocity. An application may move it
	// manually.
	StaticBody BodyType = 0

	// KinematicBody has zero mass. The application sets the velocity and the
	// solver moves it.
	KinematicBody BodyType = 1

	// DynamicBody has positive mass. Forces determine the velocity and the
	// solver moves it.
	DynamicBody BodyType = 2

	// BodyTypeCount is the number of body types.
	BodyTypeCount = 3
)

type Capsule

type Capsule struct {
	// Center1 is the local center of the first semicircle.
	Center1 Vec2

	// Center2 is the local center of the second semicircle.
	Center2 Vec2

	// Radius is the radius of both semicircles.
	Radius Q
}

Capsule is a solid capsule: two semicircles joined by a rectangle.

type CastOutput

type CastOutput struct {
	// Normal is the surface normal at the hit point.
	Normal Vec2

	// Point is the surface hit point.
	Point Vec2

	// Fraction is the part of the input translation at the collision.
	Fraction Q

	// Iterations is the number of iterations the cast used.
	Iterations int

	// Hit reports whether the cast hit.
	Hit bool
}

CastOutput is the output of a ray cast or of a shape cast. An initial overlap returns a zero fraction and a zero normal.

func RayCastCapsule

func RayCastCapsule(input *RayCastInput, shape *Capsule) CastOutput

RayCastCapsule casts a ray against a capsule in local space. An initial overlap reports a hit at the ray origin with a zero fraction.

func RayCastCircle

func RayCastCircle(input *RayCastInput, shape *Circle) CastOutput

RayCastCircle casts a ray against a circle in local space. An initial overlap reports a hit at the ray origin with a zero fraction.

func RayCastPolygon

func RayCastPolygon(input *RayCastInput, shape *Polygon) CastOutput

RayCastPolygon casts a ray against a convex polygon in local space. An initial overlap reports a hit at the ray origin with a zero fraction.

A rounded polygon needs the shape cast, which arrives with the distance stage, so this function accepts only a polygon with a zero radius.

func RayCastSegment

func RayCastSegment(input *RayCastInput, shape *Segment, oneSided bool) CastOutput

RayCastSegment casts a ray against a segment in local space. A one-sided segment reports a miss for a ray that arrives from the left.

func ShapeCast added in v0.3.0

func ShapeCast(input *ShapeCastPairInput) CastOutput

ShapeCast casts shape B against a fixed shape A by conservative advancement and reports the hit point, the normal and the fraction of the translation. Shapes that start in contact report a hit at a zero fraction unless the input allows an encroach. It corresponds to b2ShapeCast in src/distance.c.

func ShapeCastCapsule added in v0.3.0

func ShapeCastCapsule(input *ShapeCastInput, shape *Capsule) CastOutput

ShapeCastCapsule casts a proxy against a capsule in the local frame of the capsule. It corresponds to b2ShapeCastCapsule in src/geometry.c.

func ShapeCastCircle added in v0.3.0

func ShapeCastCircle(input *ShapeCastInput, shape *Circle) CastOutput

ShapeCastCircle casts a proxy against a circle in the local frame of the circle. It corresponds to b2ShapeCastCircle in src/geometry.c.

func ShapeCastPolygon added in v0.3.0

func ShapeCastPolygon(input *ShapeCastInput, shape *Polygon) CastOutput

ShapeCastPolygon casts a proxy against a polygon in the local frame of the polygon. It corresponds to b2ShapeCastPolygon in src/geometry.c.

func ShapeCastSegment added in v0.3.0

func ShapeCastSegment(input *ShapeCastInput, shape *Segment) CastOutput

ShapeCastSegment casts a proxy against a segment in the local frame of the segment. It corresponds to b2ShapeCastSegment in src/geometry.c.

type CastResultFcn added in v0.3.0

type CastResultFcn func(shapeId ShapeId, point, normal Vec2, fraction Q) Q

CastResultFcn receives each hit of a ray cast. Return -1 to skip the shape, 0 to stop, the fraction to clip the ray for the closest hit, or 1 to continue. It corresponds to b2CastResultFcn in include/box2d/types.h; the closure carries the context.

type ChainId

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

ChainId identifies a chain. Its zero value is null.

func LoadChainId

func LoadChainId(x uint64) ChainId

LoadChainId unpacks a chain id from a uint64.

func (ChainId) IsNull

func (id ChainId) IsNull() bool

IsNull reports whether the id references nothing.

type ChainSegment

type ChainSegment struct {
	// Ghost1 is the tail ghost vertex.
	Ghost1 Vec2

	// Segment is the colliding part.
	Segment Segment

	// Ghost2 is the head ghost vertex.
	Ghost2 Vec2

	// ChainId is the owning chain shape. It is internal bookkeeping.
	ChainId int
}

ChainSegment is a line segment with one-sided collision. It collides only on the right side. A chain shape generates several of them, in the order ghost1, point1, point2, ghost2.

type Circle

type Circle struct {
	Center Vec2
	Radius Q
}

Circle is a solid circle.

type ContactBeginTouchEvent added in v0.3.0

type ContactBeginTouchEvent struct {
	// ShapeIdA is the first shape.
	ShapeIdA ShapeId

	// ShapeIdB is the second shape.
	ShapeIdB ShapeId

	// Manifold is the initial contact manifold. The world records it
	// before the solver runs, so every impulse is zero.
	Manifold Manifold
}

ContactBeginTouchEvent reports that two shapes started to touch.

type ContactEndTouchEvent added in v0.3.0

type ContactEndTouchEvent struct {
	// ShapeIdA is the first shape. It may be destroyed; see IsValid.
	ShapeIdA ShapeId

	// ShapeIdB is the second shape. It may be destroyed; see IsValid.
	ShapeIdB ShapeId
}

ContactEndTouchEvent reports that two shapes stopped touching. Any action that destroys a contact between steps also reports one, such as a transform change, a body or shape destroy, or a body type change.

type ContactEvents added in v0.3.0

type ContactEvents struct {
	BeginEvents []ContactBeginTouchEvent
	EndEvents   []ContactEndTouchEvent
	HitEvents   []ContactHitEvent
}

ContactEvents holds the contact events of the last step. The slices stay valid until the next step; a body or shape destroy may make an id in them stale.

func GetContactEvents added in v0.3.0

func GetContactEvents(worldId WorldId) ContactEvents

GetContactEvents returns the contact events of the last step. It corresponds to b2World_GetContactEvents in src/world.c.

type ContactHitEvent added in v0.3.0

type ContactHitEvent struct {
	// ShapeIdA is the first shape.
	ShapeIdA ShapeId

	// ShapeIdB is the second shape.
	ShapeIdB ShapeId

	// Point is where the shapes hit at the start of the step. It is the
	// mid-point between the two surfaces.
	Point Vec2

	// Normal points from shape A to shape B.
	Normal Vec2

	// ApproachSpeed is the closing speed of the shapes. It is positive.
	ApproachSpeed Q
}

ContactHitEvent reports that two shapes collided faster than the hit event threshold. A speculative contact with a confirmed impulse also reports one.

type DistanceInput added in v0.3.0

type DistanceInput struct {
	// ProxyA is the proxy of shape A.
	ProxyA ShapeProxy

	// ProxyB is the proxy of shape B.
	ProxyB ShapeProxy

	// TransformA is the world transform of shape A.
	TransformA Transform

	// TransformB is the world transform of shape B.
	TransformB Transform

	// UseRadii asks the solver to subtract the proxy radii.
	UseRadii bool
}

DistanceInput is the input of ShapeDistance. It corresponds to b2DistanceInput in include/box2d/collision.h.

type DistanceJointDef added in v0.3.0

type DistanceJointDef struct {
	// The first attached body.
	BodyIdA BodyId

	// The second attached body.
	BodyIdB BodyId

	// The local anchor point relative to the origin of body A.
	LocalAnchorA Vec2

	// The local anchor point relative to the origin of body B.
	LocalAnchorB Vec2

	// The rest length of the joint. Clamped to a stable minimum value.
	Length Q

	// Enable the distance constraint to behave like a spring. If false the
	// distance joint is rigid, otherwise the limit and the motor apply.
	EnableSpring bool

	// The spring linear stiffness in cycles per second.
	Hertz Q

	// The spring linear damping ratio, non-dimensional.
	DampingRatio Q

	// Enable and disable the joint limit.
	EnableLimit bool

	// The minimum length. Clamped to a stable minimum value.
	MinLength Q

	// The maximum length. Must be greater than or equal to the minimum
	// length.
	MaxLength Q

	// Enable and disable the joint motor.
	EnableMotor bool

	// The maximum motor force, usually in newtons.
	MaxMotorForce Q

	// The desired motor speed, usually in meters per second.
	MotorSpeed Q

	// Set this flag to true if the attached bodies should collide.
	CollideConnected bool

	// Application data attached to the joint.
	UserData any
	// contains filtered or unexported fields
}

DistanceJointDef configures a distance joint: a point on each body kept at a fixed length, or within a length range. Initialize it with DefaultDistanceJointDef.

func DefaultDistanceJointDef added in v0.3.0

func DefaultDistanceJointDef() DistanceJointDef

DefaultDistanceJointDef returns the default distance joint definition.

type DistanceOutput added in v0.3.0

type DistanceOutput struct {
	// PointA is the closest point on shape A.
	PointA Vec2

	// PointB is the closest point on shape B.
	PointB Vec2

	// Normal points from A to B. It is invalid when the distance is zero.
	Normal Vec2

	// Distance is the final distance, zero when the shapes overlap.
	Distance Q

	// Iterations counts the GJK iterations used.
	Iterations int

	// SimplexCount is the number of simplexes stored in the debug slice.
	SimplexCount int
}

DistanceOutput is the output of ShapeDistance. It corresponds to b2DistanceOutput in include/box2d/collision.h.

func ShapeDistance added in v0.3.0

func ShapeDistance(input *DistanceInput, cache *SimplexCache, simplexes []Simplex) DistanceOutput

ShapeDistance computes the closest points between two convex proxies with GJK. The cache is input and output; start with the zero value. The simplexes slice receives the simplex of each iteration for debugging; pass nil to skip it. It corresponds to b2ShapeDistance in src/distance.c, https://box2d.org/files/ErinCatto_GJK_GDC2010.pdf.

The reference stops on a search direction shorter than FLT_EPSILON; the port stops on a squared length of exactly zero (D-012).

type Filter

type Filter struct {
	// The collision category bits of this shape. Normally one bit per
	// application object type.
	CategoryBits uint64

	// The categories that this shape accepts for collision.
	MaskBits uint64

	// Shapes in the same negative group never collide; in the same positive
	// group they always collide. Zero has no effect. A non-zero group wins
	// against the mask bits.
	GroupIndex int
}

Filter controls collision between shapes, and between queries and shapes.

func DefaultFilter

func DefaultFilter() Filter

DefaultFilter returns the default filter: category 1, every mask bit set, no group.

type FilterJointDef added in v0.3.0

type FilterJointDef struct {
	// The first attached body.
	BodyIdA BodyId

	// The second attached body.
	BodyIdB BodyId

	// Application data attached to the joint.
	UserData any
	// contains filtered or unexported fields
}

FilterJointDef configures a filter joint: it only disables collision between two bodies. Initialize it with DefaultFilterJointDef.

func DefaultFilterJointDef added in v0.3.0

func DefaultFilterJointDef() FilterJointDef

DefaultFilterJointDef returns the default filter joint definition.

type Hull

type Hull struct {
	// Points holds the hull corners. Only the first Count entries are valid.
	Points [MaxPolygonVertices]Vec2

	// Count is the number of points.
	Count int
}

Hull is a convex hull. It feeds the polygon constructors. Build one with ComputeHull and do not modify it afterwards.

func ComputeHull

func ComputeHull(points []Vec2) Hull

ComputeHull returns the convex hull of a set of points. It welds points that are closer than four linear slops and it drops collinear points. It returns an empty hull on failure: fewer than three points, more than MaxPolygonVertices points, points all very close, or points all on a line.

type JointId

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

JointId identifies a joint. Its zero value is null.

func CreateDistanceJoint added in v0.3.0

func CreateDistanceJoint(worldId WorldId, def *DistanceJointDef) JointId

CreateDistanceJoint creates a distance joint. The definition must come from DefaultDistanceJointDef.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/dbox2d"
	"github.com/dhannyell/fixed"
)

// exampleWorld builds a world with a static ground body and one dynamic
// box above it. The examples hang joints between the two.
func exampleWorld() (dbox2d.WorldId, dbox2d.BodyId, dbox2d.BodyId) {
	worldDef := dbox2d.DefaultWorldDef()
	worldId := dbox2d.CreateWorld(&worldDef)

	groundDef := dbox2d.DefaultBodyDef()
	groundId := dbox2d.CreateBody(worldId, &groundDef)

	boxDef := dbox2d.DefaultBodyDef()
	boxDef.Type = dbox2d.DynamicBody
	boxDef.Position = dbox2d.Vec2{Y: fixed.Q32FromInt(2)}
	boxId := dbox2d.CreateBody(worldId, &boxDef)
	shapeDef := dbox2d.DefaultShapeDef()
	box := dbox2d.MakeSquare(fixed.Q32Half())
	dbox2d.CreatePolygonShape(boxId, &shapeDef, &box)

	return worldId, groundId, boxId
}

func main() {
	worldId, groundId, boxId := exampleWorld()
	defer dbox2d.DestroyWorld(worldId)

	// A rope of length two from the ground origin to the box center.
	def := dbox2d.DefaultDistanceJointDef()
	def.BodyIdA = groundId
	def.BodyIdB = boxId
	def.Length = fixed.Q32FromInt(2)
	jointId := dbox2d.CreateDistanceJoint(worldId, &def)

	fmt.Println(jointId.IsNull())
}
Output:
false

func CreateFilterJoint added in v0.3.0

func CreateFilterJoint(worldId WorldId, def *FilterJointDef) JointId

CreateFilterJoint creates a filter joint. The joint only disables collision between the two bodies. The definition must come from DefaultFilterJointDef.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/dbox2d"
	"github.com/dhannyell/fixed"
)

// exampleWorld builds a world with a static ground body and one dynamic
// box above it. The examples hang joints between the two.
func exampleWorld() (dbox2d.WorldId, dbox2d.BodyId, dbox2d.BodyId) {
	worldDef := dbox2d.DefaultWorldDef()
	worldId := dbox2d.CreateWorld(&worldDef)

	groundDef := dbox2d.DefaultBodyDef()
	groundId := dbox2d.CreateBody(worldId, &groundDef)

	boxDef := dbox2d.DefaultBodyDef()
	boxDef.Type = dbox2d.DynamicBody
	boxDef.Position = dbox2d.Vec2{Y: fixed.Q32FromInt(2)}
	boxId := dbox2d.CreateBody(worldId, &boxDef)
	shapeDef := dbox2d.DefaultShapeDef()
	box := dbox2d.MakeSquare(fixed.Q32Half())
	dbox2d.CreatePolygonShape(boxId, &shapeDef, &box)

	return worldId, groundId, boxId
}

func main() {
	worldId, groundId, boxId := exampleWorld()
	defer dbox2d.DestroyWorld(worldId)

	// The box falls through the ground; the filter joint disables the
	// collision between the two bodies.
	def := dbox2d.DefaultFilterJointDef()
	def.BodyIdA = groundId
	def.BodyIdB = boxId
	jointId := dbox2d.CreateFilterJoint(worldId, &def)

	fmt.Println(jointId.IsNull())
}
Output:
false

func CreateMotorJoint added in v0.3.0

func CreateMotorJoint(worldId WorldId, def *MotorJointDef) JointId

CreateMotorJoint creates a motor joint. The definition must come from DefaultMotorJointDef.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/dbox2d"
	"github.com/dhannyell/fixed"
)

// exampleWorld builds a world with a static ground body and one dynamic
// box above it. The examples hang joints between the two.
func exampleWorld() (dbox2d.WorldId, dbox2d.BodyId, dbox2d.BodyId) {
	worldDef := dbox2d.DefaultWorldDef()
	worldId := dbox2d.CreateWorld(&worldDef)

	groundDef := dbox2d.DefaultBodyDef()
	groundId := dbox2d.CreateBody(worldId, &groundDef)

	boxDef := dbox2d.DefaultBodyDef()
	boxDef.Type = dbox2d.DynamicBody
	boxDef.Position = dbox2d.Vec2{Y: fixed.Q32FromInt(2)}
	boxId := dbox2d.CreateBody(worldId, &boxDef)
	shapeDef := dbox2d.DefaultShapeDef()
	box := dbox2d.MakeSquare(fixed.Q32Half())
	dbox2d.CreatePolygonShape(boxId, &shapeDef, &box)

	return worldId, groundId, boxId
}

func main() {
	worldId, groundId, boxId := exampleWorld()
	defer dbox2d.DestroyWorld(worldId)

	// The motor drives the box toward an offset of (1, 2) from the ground.
	def := dbox2d.DefaultMotorJointDef()
	def.BodyIdA = groundId
	def.BodyIdB = boxId
	def.LinearOffset = dbox2d.Vec2{X: fixed.Q32One(), Y: fixed.Q32FromInt(2)}
	def.MaxForce = fixed.Q32FromInt(100)
	jointId := dbox2d.CreateMotorJoint(worldId, &def)

	fmt.Println(jointId.IsNull())
}
Output:
false

func CreateMouseJoint added in v0.3.0

func CreateMouseJoint(worldId WorldId, def *MouseJointDef) JointId

CreateMouseJoint creates a mouse joint. The definition must come from DefaultMouseJointDef.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/dbox2d"
	"github.com/dhannyell/fixed"
)

// exampleWorld builds a world with a static ground body and one dynamic
// box above it. The examples hang joints between the two.
func exampleWorld() (dbox2d.WorldId, dbox2d.BodyId, dbox2d.BodyId) {
	worldDef := dbox2d.DefaultWorldDef()
	worldId := dbox2d.CreateWorld(&worldDef)

	groundDef := dbox2d.DefaultBodyDef()
	groundId := dbox2d.CreateBody(worldId, &groundDef)

	boxDef := dbox2d.DefaultBodyDef()
	boxDef.Type = dbox2d.DynamicBody
	boxDef.Position = dbox2d.Vec2{Y: fixed.Q32FromInt(2)}
	boxId := dbox2d.CreateBody(worldId, &boxDef)
	shapeDef := dbox2d.DefaultShapeDef()
	box := dbox2d.MakeSquare(fixed.Q32Half())
	dbox2d.CreatePolygonShape(boxId, &shapeDef, &box)

	return worldId, groundId, boxId
}

func main() {
	worldId, groundId, boxId := exampleWorld()
	defer dbox2d.DestroyWorld(worldId)

	// The target is a world point; the joint pulls the box toward it.
	def := dbox2d.DefaultMouseJointDef()
	def.BodyIdA = groundId
	def.BodyIdB = boxId
	def.Target = dbox2d.Vec2{X: fixed.Q32One(), Y: fixed.Q32FromInt(2)}
	def.MaxForce = fixed.Q32FromInt(500)
	jointId := dbox2d.CreateMouseJoint(worldId, &def)

	fmt.Println(jointId.IsNull())
}
Output:
false

func CreatePrismaticJoint added in v0.3.0

func CreatePrismaticJoint(worldId WorldId, def *PrismaticJointDef) JointId

CreatePrismaticJoint creates a prismatic joint. The definition must come from DefaultPrismaticJointDef.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/dbox2d"
	"github.com/dhannyell/fixed"
)

// exampleWorld builds a world with a static ground body and one dynamic
// box above it. The examples hang joints between the two.
func exampleWorld() (dbox2d.WorldId, dbox2d.BodyId, dbox2d.BodyId) {
	worldDef := dbox2d.DefaultWorldDef()
	worldId := dbox2d.CreateWorld(&worldDef)

	groundDef := dbox2d.DefaultBodyDef()
	groundId := dbox2d.CreateBody(worldId, &groundDef)

	boxDef := dbox2d.DefaultBodyDef()
	boxDef.Type = dbox2d.DynamicBody
	boxDef.Position = dbox2d.Vec2{Y: fixed.Q32FromInt(2)}
	boxId := dbox2d.CreateBody(worldId, &boxDef)
	shapeDef := dbox2d.DefaultShapeDef()
	box := dbox2d.MakeSquare(fixed.Q32Half())
	dbox2d.CreatePolygonShape(boxId, &shapeDef, &box)

	return worldId, groundId, boxId
}

func main() {
	worldId, groundId, boxId := exampleWorld()
	defer dbox2d.DestroyWorld(worldId)

	// The box slides along the vertical axis of the ground, between
	// zero and three units.
	def := dbox2d.DefaultPrismaticJointDef()
	def.BodyIdA = groundId
	def.BodyIdB = boxId
	def.LocalAxisA = dbox2d.Vec2{Y: fixed.Q32One()}
	def.EnableLimit = true
	def.LowerTranslation = fixed.Q32Zero()
	def.UpperTranslation = fixed.Q32FromInt(3)
	jointId := dbox2d.CreatePrismaticJoint(worldId, &def)

	fmt.Println(jointId.IsNull())
}
Output:
false

func CreateRevoluteJoint added in v0.3.0

func CreateRevoluteJoint(worldId WorldId, def *RevoluteJointDef) JointId

CreateRevoluteJoint creates a revolute joint. The definition must come from DefaultRevoluteJointDef. The angles are in turns.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/dbox2d"
	"github.com/dhannyell/fixed"
)

// exampleWorld builds a world with a static ground body and one dynamic
// box above it. The examples hang joints between the two.
func exampleWorld() (dbox2d.WorldId, dbox2d.BodyId, dbox2d.BodyId) {
	worldDef := dbox2d.DefaultWorldDef()
	worldId := dbox2d.CreateWorld(&worldDef)

	groundDef := dbox2d.DefaultBodyDef()
	groundId := dbox2d.CreateBody(worldId, &groundDef)

	boxDef := dbox2d.DefaultBodyDef()
	boxDef.Type = dbox2d.DynamicBody
	boxDef.Position = dbox2d.Vec2{Y: fixed.Q32FromInt(2)}
	boxId := dbox2d.CreateBody(worldId, &boxDef)
	shapeDef := dbox2d.DefaultShapeDef()
	box := dbox2d.MakeSquare(fixed.Q32Half())
	dbox2d.CreatePolygonShape(boxId, &shapeDef, &box)

	return worldId, groundId, boxId
}

func main() {
	worldId, groundId, boxId := exampleWorld()
	defer dbox2d.DestroyWorld(worldId)

	// A pendulum: the pivot is the ground origin, two units below the
	// box center. The angles are in turns; a quarter turn is 0.25.
	def := dbox2d.DefaultRevoluteJointDef()
	def.BodyIdA = groundId
	def.BodyIdB = boxId
	def.LocalAnchorB = dbox2d.Vec2{Y: fixed.Q32FromInt(-2)}
	def.EnableLimit = true
	def.LowerAngle = fixed.Q32MustParse("-0.25")
	def.UpperAngle = fixed.Q32MustParse("0.25")
	jointId := dbox2d.CreateRevoluteJoint(worldId, &def)

	fmt.Println(jointId.IsNull())
}
Output:
false

func CreateWeldJoint added in v0.3.0

func CreateWeldJoint(worldId WorldId, def *WeldJointDef) JointId

CreateWeldJoint creates a weld joint. The definition must come from DefaultWeldJointDef.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/dbox2d"
	"github.com/dhannyell/fixed"
)

// exampleWorld builds a world with a static ground body and one dynamic
// box above it. The examples hang joints between the two.
func exampleWorld() (dbox2d.WorldId, dbox2d.BodyId, dbox2d.BodyId) {
	worldDef := dbox2d.DefaultWorldDef()
	worldId := dbox2d.CreateWorld(&worldDef)

	groundDef := dbox2d.DefaultBodyDef()
	groundId := dbox2d.CreateBody(worldId, &groundDef)

	boxDef := dbox2d.DefaultBodyDef()
	boxDef.Type = dbox2d.DynamicBody
	boxDef.Position = dbox2d.Vec2{Y: fixed.Q32FromInt(2)}
	boxId := dbox2d.CreateBody(worldId, &boxDef)
	shapeDef := dbox2d.DefaultShapeDef()
	box := dbox2d.MakeSquare(fixed.Q32Half())
	dbox2d.CreatePolygonShape(boxId, &shapeDef, &box)

	return worldId, groundId, boxId
}

func main() {
	worldId, groundId, boxId := exampleWorld()
	defer dbox2d.DestroyWorld(worldId)

	// A weld with a soft angular spring holds the box in place.
	def := dbox2d.DefaultWeldJointDef()
	def.BodyIdA = groundId
	def.BodyIdB = boxId
	def.LocalAnchorB = dbox2d.Vec2{Y: fixed.Q32FromInt(-2)}
	def.AngularHertz = fixed.Q32FromInt(2)
	def.AngularDampingRatio = fixed.Q32Half()
	jointId := dbox2d.CreateWeldJoint(worldId, &def)

	fmt.Println(jointId.IsNull())
}
Output:
false

func CreateWheelJoint added in v0.3.0

func CreateWheelJoint(worldId WorldId, def *WheelJointDef) JointId

CreateWheelJoint creates a wheel joint. The definition must come from DefaultWheelJointDef.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/dbox2d"
	"github.com/dhannyell/fixed"
)

// exampleWorld builds a world with a static ground body and one dynamic
// box above it. The examples hang joints between the two.
func exampleWorld() (dbox2d.WorldId, dbox2d.BodyId, dbox2d.BodyId) {
	worldDef := dbox2d.DefaultWorldDef()
	worldId := dbox2d.CreateWorld(&worldDef)

	groundDef := dbox2d.DefaultBodyDef()
	groundId := dbox2d.CreateBody(worldId, &groundDef)

	boxDef := dbox2d.DefaultBodyDef()
	boxDef.Type = dbox2d.DynamicBody
	boxDef.Position = dbox2d.Vec2{Y: fixed.Q32FromInt(2)}
	boxId := dbox2d.CreateBody(worldId, &boxDef)
	shapeDef := dbox2d.DefaultShapeDef()
	box := dbox2d.MakeSquare(fixed.Q32Half())
	dbox2d.CreatePolygonShape(boxId, &shapeDef, &box)

	return worldId, groundId, boxId
}

func main() {
	worldId, groundId, boxId := exampleWorld()
	defer dbox2d.DestroyWorld(worldId)

	// A suspension: the box rides the vertical axis on a spring and its
	// motor spins it at one turn per second.
	def := dbox2d.DefaultWheelJointDef()
	def.BodyIdA = groundId
	def.BodyIdB = boxId
	def.EnableMotor = true
	def.MotorSpeed = fixed.Q32One()
	def.MaxMotorTorque = fixed.Q32FromInt(10)
	jointId := dbox2d.CreateWheelJoint(worldId, &def)

	fmt.Println(jointId.IsNull())
}
Output:
false

func LoadJointId

func LoadJointId(x uint64) JointId

LoadJointId unpacks a joint id from a uint64.

func (JointId) IsNull

func (id JointId) IsNull() bool

IsNull reports whether the id references nothing.

type JointType added in v0.3.0

type JointType int

JointType selects the joint of a joint definition.

const (
	DistanceJoint JointType = iota
	FilterJoint
	MotorJoint
	MouseJoint
	PrismaticJoint
	RevoluteJoint
	WeldJoint
	WheelJoint
)

Joint types. upstream b2JointType

type Manifold

type Manifold struct {
	// Normal is the unit normal in world space. It points from A to B.
	Normal Vec2

	// RollingImpulse is the angular impulse of the rolling resistance.
	RollingImpulse Q

	// Points holds the contact points. Two are possible in 2D.
	Points [2]ManifoldPoint

	// PointCount is zero, one or two.
	PointCount int
}

Manifold describes the contact points between two colliding shapes. The solver uses speculative collision, so a point may still be separated.

func CollideCapsuleAndCircle added in v0.2.0

func CollideCapsuleAndCircle(capsuleA *Capsule, xfA Transform, circleB *Circle, xfB Transform) Manifold

CollideCapsuleAndCircle computes the contact manifold of a capsule and a circle. It corresponds to b2CollideCapsuleAndCircle in src/manifold.c.

func CollideCapsules added in v0.2.0

func CollideCapsules(capsuleA *Capsule, xfA Transform, capsuleB *Capsule, xfB Transform) Manifold

CollideCapsules computes the contact manifold of two capsules. It follows Ericson 5.1.9 with clipping for a second contact point and corresponds to b2CollideCapsules in src/manifold.c.

func CollideChainSegmentAndCapsule added in v0.3.0

func CollideChainSegmentAndCapsule(segmentA *ChainSegment, xfA Transform, capsuleB *Capsule, xfB Transform, cache *SimplexCache) Manifold

CollideChainSegmentAndCapsule treats the capsule as a rounded polygon and defers to the polygon routine. It corresponds to b2CollideChainSegmentAndCapsule in src/manifold.c.

func CollideChainSegmentAndCircle added in v0.2.0

func CollideChainSegmentAndCircle(segmentA *ChainSegment, xfA Transform, circleB *Circle, xfB Transform) Manifold

CollideChainSegmentAndCircle computes the contact manifold of a one-sided chain segment and a circle. It corresponds to b2CollideChainSegmentAndCircle in src/manifold.c.

func CollideChainSegmentAndPolygon added in v0.3.0

func CollideChainSegmentAndPolygon(segmentA *ChainSegment, xfA Transform, polygonB *Polygon, xfB Transform, cache *SimplexCache) Manifold

CollideChainSegmentAndPolygon computes the manifold between a chain segment and a polygon. The cache warm starts the distance solver between calls. It corresponds to b2CollideChainSegmentAndPolygon in src/manifold.c.

func CollideCircles added in v0.2.0

func CollideCircles(circleA *Circle, xfA Transform, circleB *Circle, xfB Transform) Manifold

CollideCircles computes the contact manifold of two circles. It corresponds to b2CollideCircles in src/manifold.c.

func CollidePolygonAndCapsule added in v0.2.0

func CollidePolygonAndCapsule(polygonA *Polygon, xfA Transform, capsuleB *Capsule, xfB Transform) Manifold

CollidePolygonAndCapsule computes the contact manifold of a polygon and a capsule. It corresponds to b2CollidePolygonAndCapsule in src/manifold.c.

func CollidePolygonAndCircle added in v0.2.0

func CollidePolygonAndCircle(polygonA *Polygon, xfA Transform, circleB *Circle, xfB Transform) Manifold

CollidePolygonAndCircle computes the contact manifold of a polygon and a circle. It corresponds to b2CollidePolygonAndCircle in src/manifold.c.

func CollidePolygons added in v0.2.0

func CollidePolygons(polygonA *Polygon, xfA Transform, polygonB *Polygon, xfB Transform) Manifold

CollidePolygons computes the contact manifold of two rounded polygons with the separating axis test and edge clipping. It corresponds to b2CollidePolygons in src/manifold.c.

func CollideSegmentAndCapsule added in v0.2.0

func CollideSegmentAndCapsule(segmentA *Segment, xfA Transform, capsuleB *Capsule, xfB Transform) Manifold

CollideSegmentAndCapsule computes the contact manifold of a segment and a capsule. It corresponds to b2CollideSegmentAndCapsule in src/manifold.c.

func CollideSegmentAndCircle added in v0.2.0

func CollideSegmentAndCircle(segmentA *Segment, xfA Transform, circleB *Circle, xfB Transform) Manifold

CollideSegmentAndCircle computes the contact manifold of a segment and a circle. It corresponds to b2CollideSegmentAndCircle in src/manifold.c.

func CollideSegmentAndPolygon added in v0.2.0

func CollideSegmentAndPolygon(segmentA *Segment, xfA Transform, polygonB *Polygon, xfB Transform) Manifold

CollideSegmentAndPolygon computes the contact manifold of a segment and a polygon. It corresponds to b2CollideSegmentAndPolygon in src/manifold.c.

type ManifoldPoint

type ManifoldPoint struct {
	// Point is the contact point in world space. Use it for debugging only,
	// because it loses precision far from the origin.
	Point Vec2

	// AnchorA is the contact point relative to the origin of shape A, in
	// world space. Inside the solver it is relative to the center of mass.
	AnchorA Vec2

	// AnchorB is the contact point relative to the origin of shape B, in
	// world space. Inside the solver it is relative to the center of mass.
	AnchorB Vec2

	// Separation is negative when the shapes penetrate.
	Separation Q

	// NormalImpulse is the impulse along the manifold normal.
	NormalImpulse Q

	// TangentImpulse is the friction impulse.
	TangentImpulse Q

	// TotalNormalImpulse accumulates over the substeps and the restitution
	// pass. It tells a speculative point that acted from one that did not.
	TotalNormalImpulse Q

	// NormalVelocity is the relative normal velocity before the solve. It
	// feeds the hit events. A negative value means the shapes approach.
	NormalVelocity Q

	// Id identifies the contact point between the two shapes.
	Id uint16

	// Persisted reports whether the point existed in the previous step.
	Persisted bool
}

ManifoldPoint is one contact point of a contact manifold. The solver uses speculative collision, so a point may still be separated.

type MassData

type MassData struct {
	// Mass is the mass of the shape, usually in kilograms.
	Mass Q

	// Center is the centroid of the shape, relative to the shape origin.
	Center Vec2

	// RotationalInertia is measured about the local origin.
	RotationalInertia Q
}

MassData holds the mass properties of a shape.

func ComputeCapsuleMass

func ComputeCapsuleMass(shape *Capsule, density Q) MassData

ComputeCapsuleMass returns the mass properties of a capsule.

func ComputeCircleMass

func ComputeCircleMass(shape *Circle, density Q) MassData

ComputeCircleMass returns the mass properties of a circle.

func ComputePolygonMass

func ComputePolygonMass(shape *Polygon, density Q) MassData

ComputePolygonMass returns the mass properties of a convex polygon. It approximates a rounded polygon by pushing the vertices outward.

type Mat22

type Mat22 struct {
	Cx, Cy Vec2
}

Mat22 is a 2-by-2 matrix, stored as its columns.

func GetInverse22

func GetInverse22(m Mat22) Mat22

GetInverse22 returns the inverse of m. A singular matrix returns the zero matrix.

Each entry divides by the determinant, because a fixed-point reciprocal loses the precision that the division keeps. See DIVERGENCES.md.

func Mat22Zero

func Mat22Zero() Mat22

Mat22Zero returns the zero matrix.

type MotorJointDef added in v0.3.0

type MotorJointDef struct {
	// The first attached body.
	BodyIdA BodyId

	// The second attached body.
	BodyIdB BodyId

	// Position of body B minus the position of body A, in the frame of
	// body A, in meters.
	LinearOffset Vec2

	// The angle of body B minus the angle of body A, in turns.
	AngularOffset Q

	// The maximum motor force in newtons.
	MaxForce Q

	// The maximum motor torque in newton-meters.
	MaxTorque Q

	// Position correction factor in the range [0, 1].
	CorrectionFactor Q

	// Set this flag to true if the attached bodies should collide.
	CollideConnected bool

	// Application data attached to the joint.
	UserData any
	// contains filtered or unexported fields
}

MotorJointDef configures a motor joint: it drives the relative transform of two bodies toward an offset. Initialize it with DefaultMotorJointDef.

func DefaultMotorJointDef added in v0.3.0

func DefaultMotorJointDef() MotorJointDef

DefaultMotorJointDef returns the default motor joint definition.

type MouseJointDef added in v0.3.0

type MouseJointDef struct {
	// The first attached body. It is unused here, but it plays a role in
	// the solver order.
	BodyIdA BodyId

	// The second attached body.
	BodyIdB BodyId

	// The initial target point in world space.
	Target Vec2

	// Stiffness in cycles per second.
	Hertz Q

	// Damping ratio, non-dimensional.
	DampingRatio Q

	// Maximum force, usually in newtons.
	MaxForce Q

	// Set this flag to true if the attached bodies should collide.
	CollideConnected bool

	// Application data attached to the joint.
	UserData any
	// contains filtered or unexported fields
}

MouseJointDef configures a mouse joint: it drags a point on body B toward a world target with a spring. Body A is a ground reference and gets no reaction. Initialize it with DefaultMouseJointDef.

func DefaultMouseJointDef added in v0.3.0

func DefaultMouseJointDef() MouseJointDef

DefaultMouseJointDef returns the default mouse joint definition.

type OverlapResultFcn added in v0.3.0

type OverlapResultFcn func(shapeId ShapeId) bool

OverlapResultFcn receives each shape that an overlap query finds. Return false to stop the walk of the current tree; the query goes on with the next body type, as the reference does. It corresponds to b2OverlapResultFcn in include/box2d/types.h; the closure carries the context.

type Plane

type Plane struct {
	Normal Vec2
	Offset Q
}

Plane separates space. The separation of a point is dot(normal, point) - offset.

type Polygon

type Polygon struct {
	// Vertices holds the corners. Only the first Count entries are valid.
	Vertices [MaxPolygonVertices]Vec2

	// Normals holds the outward normal of each side.
	Normals [MaxPolygonVertices]Vec2

	// Centroid is the area centroid of the polygon.
	Centroid Vec2

	// Radius is the external radius of a rounded polygon.
	Radius Q

	// Count is the number of vertices.
	Count int
}

Polygon is a solid convex polygon. The interior lies to the left of every edge. Build one with MakePolygon or MakeBox; never fill the fields by hand.

func MakeBox

func MakeBox(halfWidth, halfHeight Q) Polygon

MakeBox returns a rectangle polygon of the given half-extents, without a hull. It panics on a half-extent that is not positive.

func MakeOffsetBox

func MakeOffsetBox(halfWidth, halfHeight Q, center Vec2, rotation Rot) Polygon

MakeOffsetBox returns a rectangle polygon placed at a center and a rotation, without a hull.

func MakeOffsetPolygon

func MakeOffsetPolygon(hull *Hull, position Vec2, rotation Rot) Polygon

MakeOffsetPolygon returns a convex polygon built from a hull and placed at a position and a rotation.

func MakeOffsetRoundedBox

func MakeOffsetRoundedBox(halfWidth, halfHeight Q, center Vec2, rotation Rot, radius Q) Polygon

MakeOffsetRoundedBox returns a rectangle polygon with rounded corners, placed at a center and a rotation, without a hull.

func MakeOffsetRoundedPolygon

func MakeOffsetRoundedPolygon(hull *Hull, position Vec2, rotation Rot, radius Q) Polygon

MakeOffsetRoundedPolygon returns a convex polygon built from a hull, placed at a position and a rotation, with rounded corners of the given radius.

func MakePolygon

func MakePolygon(hull *Hull, radius Q) Polygon

MakePolygon returns a convex polygon built from a hull. The radius rounds the corners. It panics on a hull that ValidateHull rejects.

func MakeRoundedBox

func MakeRoundedBox(halfWidth, halfHeight, radius Q) Polygon

MakeRoundedBox returns a rectangle polygon with rounded corners, without a hull.

func MakeSquare

func MakeSquare(halfWidth Q) Polygon

MakeSquare returns a square polygon of the given half-width, without a hull.

func TransformPolygon

func TransformPolygon(transform Transform, polygon *Polygon) Polygon

TransformPolygon returns the polygon moved by a transform. It moves a shape from one body to another.

type PrismaticJointDef added in v0.3.0

type PrismaticJointDef struct {
	// The first attached body.
	BodyIdA BodyId

	// The second attached body.
	BodyIdB BodyId

	// The local anchor point relative to the origin of body A.
	LocalAnchorA Vec2

	// The local anchor point relative to the origin of body B.
	LocalAnchorB Vec2

	// The local translation unit axis in body A.
	LocalAxisA Vec2

	// The constrained angle between the bodies: angle of B minus angle of
	// A, in turns.
	ReferenceAngle Q

	// The target translation for the joint in meters. The spring-damper
	// pulls toward this translation.
	TargetTranslation Q

	// Enable a linear spring along the prismatic joint axis.
	EnableSpring bool

	// The spring stiffness in cycles per second.
	Hertz Q

	// The spring damping ratio, non-dimensional.
	DampingRatio Q

	// Enable and disable the joint limit.
	EnableLimit bool

	// The lower translation limit.
	LowerTranslation Q

	// The upper translation limit.
	UpperTranslation Q

	// Enable and disable the joint motor.
	EnableMotor bool

	// The maximum motor force, usually in newtons.
	MaxMotorForce Q

	// The desired motor speed, usually in meters per second.
	MotorSpeed Q

	// Set this flag to true if the attached bodies should collide.
	CollideConnected bool

	// Application data attached to the joint.
	UserData any
	// contains filtered or unexported fields
}

PrismaticJointDef configures a prismatic joint: body B translates along an axis fixed in body A, with no relative rotation. Initialize it with DefaultPrismaticJointDef.

func DefaultPrismaticJointDef added in v0.3.0

func DefaultPrismaticJointDef() PrismaticJointDef

DefaultPrismaticJointDef returns the default prismatic joint definition.

type Q

type Q = fixed.Q32

Q is a signed Q32.32 fixed-point number.

func AABBMargin

func AABBMargin() Q

AABBMargin fattens the bounds in the dynamic tree, in meters. A proxy that moves less than the margin triggers no tree adjustment.

Changing it has a significant effect on performance.

func CastMover added in v0.3.0

func CastMover(worldId WorldId, mover *Capsule, translation Vec2, filter QueryFilter) Q

CastMover sweeps a capsule through the world and returns the fraction of the translation it may travel. Shapes it already overlaps do not stop it; a capsule that already touches may move a little closer. A locked world panics. It corresponds to b2World_CastMover in src/world.c.

func ComputeAngularVelocity

func ComputeAngularVelocity(q1, q2 Rot, invH Q) Q

ComputeAngularVelocity returns the angular velocity, in turns per second, that rotates q1 into q2 over one step. invH is the inverse time step.

func Cross

func Cross(a, b Vec2) Q

Cross returns the 2D cross product, which is a scalar.

func JointConstraintDampingRatio

func JointConstraintDampingRatio() Q

JointConstraintDampingRatio is the default damping of a joint constraint.

func JointConstraintHertz

func JointConstraintHertz() Q

JointConstraintHertz is the default stiffness of a joint constraint.

func LinearSlop

func LinearSlop() Q

LinearSlop is the collision and constraint tolerance in meters. It is numerically significant and visually insignificant.

Changing it has a significant effect on stability.

func MaxRotation

func MaxRotation() Q

MaxRotation is the largest rotation of a body in one time step, in turns. The limit prevents numerical problems.

Raising it to 0.25 turns or more breaks continuous collision.

func Pi

func Pi() Q

Pi is the ratio of a circumference to its diameter. An angle is a turn in this package; Pi serves the formulas that the reference writes in radians.

func PlaneSeparation

func PlaneSeparation(plane Plane, point Vec2) Q

PlaneSeparation returns the signed distance of a point from a plane.

func RelativeAngle

func RelativeAngle(b, a Rot) Q

RelativeAngle returns the angle of b relative to a, in turns.

func RotGetAngle

func RotGetAngle(q Rot) Q

RotGetAngle returns the angle of q in turns, in the range [-0.5, 0.5].

func SpeculativeDistance

func SpeculativeDistance() Q

SpeculativeDistance is the range of limited speculative collision, in meters. It reduces jitter.

Changing it has a significant effect on performance and stability.

func SpringDamper

func SpringDamper(hertz, dampingRatio, position, velocity, timeStep Q) Q

SpringDamper simulates a one-dimensional mass-spring-damper and returns the new velocity. The caller then computes the new position:

position += timeStep * newVelocity

It drives towards a zero position. Implicit integration makes the solution stable and free of transcendental functions.

func TimeToSleep

func TimeToSleep() Q

TimeToSleep is how long a body must stay still before it sleeps, in seconds.

func UnwindAngle

func UnwindAngle(t Q) Q

UnwindAngle reduces an angle in turns to the range [-0.5, 0.5]. One turn is one unit here, so the reduction is exact and needs no remainder of pi.

type QueryFilter

type QueryFilter struct {
	// The collision category bits of this query. Normally one bit.
	CategoryBits uint64

	// The shape categories that this query accepts for collision.
	MaskBits uint64
}

QueryFilter controls collision between a query and the shapes it visits.

func DefaultQueryFilter

func DefaultQueryFilter() QueryFilter

DefaultQueryFilter returns the default query filter: category 1, every mask bit set.

type RayCastInput

type RayCastInput struct {
	// Origin is the start point of the ray.
	Origin Vec2

	// Translation is the displacement of the ray.
	Translation Vec2

	// MaxFraction limits the translation to consider. It is usually one.
	MaxFraction Q
}

RayCastInput is the input of a ray cast in the local frame of a shape.

type RayResult added in v0.3.0

type RayResult struct {
	ShapeId    ShapeId
	Point      Vec2
	Normal     Vec2
	Fraction   Q
	NodeVisits int
	LeafVisits int
	Hit        bool
}

RayResult is the answer of CastRayClosest. On an initial overlap the fraction and the normal are zero and the point is an arbitrary point of the overlap region. It corresponds to b2RayResult in include/box2d/types.h.

func CastRayClosest added in v0.3.0

func CastRayClosest(worldId WorldId, origin, translation Vec2, filter QueryFilter) RayResult

CastRayClosest reports the closest hit of a ray, the most common cast in games. An initial overlap does not count as a hit. A locked world panics. It corresponds to b2World_CastRayClosest in src/world.c; the closure replaces b2RayCastClosestFcn.

type RevoluteJointDef added in v0.3.0

type RevoluteJointDef struct {
	// The first attached body.
	BodyIdA BodyId

	// The second attached body.
	BodyIdB BodyId

	// The local anchor point relative to the origin of body A.
	LocalAnchorA Vec2

	// The local anchor point relative to the origin of body B.
	LocalAnchorB Vec2

	// The angle of body B minus the angle of body A in the reference
	// state, in turns. It is clamped to [-0.5, 0.5] turns.
	ReferenceAngle Q

	// The target angle for the joint in turns. The spring-damper pulls
	// toward this angle.
	TargetAngle Q

	// Enable a rotational spring on the revolute hinge axis.
	EnableSpring bool

	// The spring stiffness in cycles per second.
	Hertz Q

	// The spring damping ratio, non-dimensional.
	DampingRatio Q

	// Enable and disable the joint limit.
	EnableLimit bool

	// The lower angle for the joint limit in turns. Must be greater than
	// -0.495 turns.
	LowerAngle Q

	// The upper angle for the joint limit in turns. Must be less than
	// 0.495 turns.
	UpperAngle Q

	// Enable and disable the joint motor.
	EnableMotor bool

	// The maximum motor torque, usually in newton-meters.
	MaxMotorTorque Q

	// The desired motor speed in turns per second.
	MotorSpeed Q

	// Set this flag to true if the attached bodies should collide.
	CollideConnected bool

	// Application data attached to the joint.
	UserData any
	// contains filtered or unexported fields
}

RevoluteJointDef configures a revolute joint: a shared anchor point with free relative rotation. Initialize it with DefaultRevoluteJointDef.

func DefaultRevoluteJointDef added in v0.3.0

func DefaultRevoluteJointDef() RevoluteJointDef

DefaultRevoluteJointDef returns the default revolute joint definition.

type Rot

type Rot = fixed.Rot

Rot is a 2D rotation, stored as a sine and cosine pair.

func ComputeRotationBetweenUnitVectors

func ComputeRotationBetweenUnitVectors(v1, v2 Vec2) Rot

ComputeRotationBetweenUnitVectors returns the rotation that carries the unit vector v1 onto the unit vector v2. It panics when either vector is not a unit vector, because the result would be a rotation of the wrong scale.

func IntegrateRotation

func IntegrateRotation(q1 Rot, deltaAngle Q) Rot

IntegrateRotation advances q1 by the angular displacement deltaAngle, in turns, and renormalizes. The first-order step below needs radians, so the displacement scales by one turn.

func InvMulRot

func InvMulRot(q, r Rot) Rot

InvMulRot returns the rotation transpose(q) * r.

[ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
[-qs qc]   [rs  rc]   [-qs*rc+qc*rs qs*rs+qc*rc]
s(q - r) = qc * rs - qs * rc
c(q - r) = qc * rc + qs * rs

func MakeRot

func MakeRot(t Q) Rot

MakeRot returns the rotation by the angle t, in turns.

func MulRot

func MulRot(q, r Rot) Rot

MulRot returns the rotation q * r.

[qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
[qs  qc]   [rs  rc]   [qs*rc+qc*rs -qs*rs+qc*rc]
s(q + r) = qs * rc + qc * rs
c(q + r) = qc * rc - qs * rs

func NLerp

func NLerp(q1, q2 Rot, t Q) Rot

NLerp interpolates between q1 and q2 by t and renormalizes.

func NormalizeRot

func NormalizeRot(q Rot) Rot

NormalizeRot rescales q to unit length.

A zero q returns a zero rotation, as the reference does. The zero rotation is invalid, so IsValidRotation reports the bad state instead of hiding it behind the identity.

func RotIdentity

func RotIdentity() Rot

RotIdentity returns the rotation by zero turns.

type Segment

type Segment struct {
	Point1 Vec2
	Point2 Vec2
}

Segment is a line segment with two-sided collision.

type SegmentDistanceResult added in v0.2.0

type SegmentDistanceResult struct {
	// Closest1 is the closest point on the first segment.
	Closest1 Vec2

	// Closest2 is the closest point on the second segment.
	Closest2 Vec2

	// Fraction1 is the barycentric coordinate on the first segment.
	Fraction1 Q

	// Fraction2 is the barycentric coordinate on the second segment.
	Fraction2 Q

	// DistanceSquared is the squared distance between the closest points.
	DistanceSquared Q
}

SegmentDistanceResult is the output of SegmentDistance. It corresponds to b2SegmentDistanceResult in include/box2d/collision.h.

func SegmentDistance added in v0.2.0

func SegmentDistance(p1, q1, p2, q2 Vec2) SegmentDistanceResult

SegmentDistance computes the closest points of two line segments, clamping at the end points when needed. It follows Ericson 5.1.9 and corresponds to b2SegmentDistance in src/distance.c.

type ShapeCastInput

type ShapeCastInput struct {
	Proxy       ShapeProxy
	Translation Vec2

	// MaxFraction limits the translation to consider. It is usually one.
	MaxFraction Q

	// CanEncroach lets a cast that starts in contact advance. It applies
	// only when the radius is greater than zero.
	CanEncroach bool
}

ShapeCastInput is the input of a shape cast in generic form.

type ShapeCastPairInput added in v0.3.0

type ShapeCastPairInput struct {
	// ProxyA is the proxy of shape A.
	ProxyA ShapeProxy

	// ProxyB is the proxy of shape B.
	ProxyB ShapeProxy

	// TransformA is the world transform of shape A.
	TransformA Transform

	// TransformB is the world transform of shape B.
	TransformB Transform

	// TranslationB is the translation of shape B.
	TranslationB Vec2

	// MaxFraction is the fraction of the translation to consider. It is
	// usually one.
	MaxFraction Q

	// CanEncroach lets shapes with a radius move a little closer when
	// they already touch.
	CanEncroach bool
}

ShapeCastPairInput is the input of ShapeCast. It corresponds to b2ShapeCastPairInput in include/box2d/collision.h.

type ShapeDef

type ShapeDef struct {
	// Application data attached to the shape.
	UserData any

	// The surface material of this shape.
	Material SurfaceMaterial

	// The density, usually in kg/m^2. It stays out of the material because
	// it describes the interior, which may be hollow.
	Density Q

	// Collision filtering data.
	Filter Filter

	// A sensor generates overlap events and never a collision response.
	// Warning: sensors are not ported yet. Creating a shape with IsSensor set
	// panics.
	IsSensor bool

	// Enable sensor events for this shape. False by default, even for
	// sensors.
	EnableSensorEvents bool

	// Enable contact events. Only for kinematic and dynamic bodies. Ignored
	// for sensors.
	EnableContactEvents bool

	// Enable hit events. Only for kinematic and dynamic bodies. Ignored for
	// sensors.
	EnableHitEvents bool

	// Enable pre-solve contact events. Only for dynamic bodies. Ignored for
	// sensors.
	EnablePreSolveEvents bool

	// A new shape scans the environment for collision on the next step. This
	// flag skips the scan on a static body, where the scan is the dominant
	// creation cost. Dynamic and kinematic shapes ignore the flag.
	InvokeContactCreation bool

	// Update the mass of the body when this shape is created. Default true.
	UpdateBodyMass bool
	// contains filtered or unexported fields
}

ShapeDef holds the data to create a shape. It is a temporary bundle of creation parameters; one definition may create many shapes. Initialize it with DefaultShapeDef.

func DefaultShapeDef

func DefaultShapeDef() ShapeDef

DefaultShapeDef returns the default shape definition.

type ShapeId

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

ShapeId identifies a shape. Its zero value is null.

func CreateCapsuleShape

func CreateCapsuleShape(bodyId BodyId, def *ShapeDef, capsule *Capsule) ShapeId

CreateCapsuleShape creates a capsule shape on a body. A capsule shorter than the linear slop becomes a circle at its midpoint.

func CreateCircleShape

func CreateCircleShape(bodyId BodyId, def *ShapeDef, circle *Circle) ShapeId

CreateCircleShape creates a circle shape on a body. The definition must come from DefaultShapeDef and is not retained.

func CreatePolygonShape

func CreatePolygonShape(bodyId BodyId, def *ShapeDef, polygon *Polygon) ShapeId

CreatePolygonShape creates a polygon shape on a body. Build the polygon with MakePolygon or MakeBox.

func CreateSegmentShape

func CreateSegmentShape(bodyId BodyId, def *ShapeDef, segment *Segment) ShapeId

CreateSegmentShape creates a segment shape on a body. It panics on a segment shorter than the linear slop.

func LoadShapeId

func LoadShapeId(x uint64) ShapeId

LoadShapeId unpacks a shape id from a uint64.

func (ShapeId) IsNull

func (id ShapeId) IsNull() bool

IsNull reports whether the id references nothing.

func (ShapeId) IsValid

func (id ShapeId) IsValid() bool

IsValid reports whether the id references a live shape.

type ShapeProxy

type ShapeProxy struct {
	// Points holds the cloud. Only the first Count entries are valid.
	Points [MaxPolygonVertices]Vec2

	// Count is the number of points. It is greater than zero.
	Count int

	// Radius is the external radius of the cloud. It may be zero.
	Radius Q
}

ShapeProxy is a point cloud with an external radius. It stands for any shape in the distance and cast routines.

func MakeOffsetProxy added in v0.3.0

func MakeOffsetProxy(points []Vec2, radius Q, position Vec2, rotation Rot) ShapeProxy

MakeOffsetProxy makes a proxy with the points transformed by a position and a rotation. The slice replaces the pointer and count pair of b2MakeOffsetProxy in src/distance.c.

func MakeProxy added in v0.2.0

func MakeProxy(points []Vec2, radius Q) ShapeProxy

MakeProxy makes a proxy for the overlap and distance routines. The slice replaces the pointer and count pair of b2MakeProxy in src/distance.c; extra points beyond the polygon limit do not enter.

type ShapeType

type ShapeType int

ShapeType identifies the geometry of a shape.

const (
	// CircleShape is a circle with an offset.
	CircleShape ShapeType = iota

	// CapsuleShape is an extruded circle.
	CapsuleShape

	// SegmentShape is a line segment.
	SegmentShape

	// PolygonShape is a convex polygon.
	PolygonShape

	// ChainSegmentShape is a line segment owned by a chain shape.
	ChainSegmentShape

	// ShapeTypeCount is the number of shape types.
	ShapeTypeCount
)

type Simplex added in v0.3.0

type Simplex struct {
	// V1, V2 and V3 are the vertices.
	V1, V2, V3 SimplexVertex

	// Count is the number of valid vertices.
	Count int
}

Simplex is the simplex of the GJK algorithm. It corresponds to b2Simplex in include/box2d/collision.h.

type SimplexCache added in v0.2.0

type SimplexCache struct {
	// Count is the number of stored simplex vertices.
	Count uint16

	// IndexA holds the vertices of shape A on the simplex.
	IndexA [3]uint8

	// IndexB holds the vertices of shape B on the simplex.
	IndexB [3]uint8
}

SimplexCache warm starts the distance solver between two calls. The zero value is an empty cache; ShapeDistance fills it. It corresponds to b2SimplexCache in include/box2d/collision.h.

type SimplexVertex added in v0.3.0

type SimplexVertex struct {
	// WA is the support point in proxy A.
	WA Vec2

	// WB is the support point in proxy B.
	WB Vec2

	// W is wA - wB.
	W Vec2

	// A is the barycentric coordinate of the closest point.
	A Q

	// IndexA is the index of WA.
	IndexA int

	// IndexB is the index of WB.
	IndexB int
}

SimplexVertex is a vertex of the GJK simplex, kept for debugging. It corresponds to b2SimplexVertex in include/box2d/collision.h.

type SurfaceMaterial

type SurfaceMaterial struct {
	// The Coulomb friction coefficient, usually in the range [0, 1].
	Friction Q

	// The coefficient of restitution, usually in the range [0, 1].
	Restitution Q

	// The rolling resistance, usually in the range [0, 1].
	RollingResistance Q

	// The tangent speed, for conveyor belts.
	TangentSpeed Q

	// Application material identifier, returned with query results. The
	// world does not use it.
	UserMaterialId int

	// Custom debug draw color.
	CustomColor uint32
}

SurfaceMaterial holds the surface properties of a shape.

func DefaultSurfaceMaterial

func DefaultSurfaceMaterial() SurfaceMaterial

DefaultSurfaceMaterial returns the default material: friction 0.6.

type Sweep added in v0.3.0

type Sweep struct {
	// LocalCenter is the local center of mass.
	LocalCenter Vec2

	// C1 is the starting world center of mass.
	C1 Vec2

	// C2 is the ending world center of mass.
	C2 Vec2

	// Q1 is the starting world rotation.
	Q1 Rot

	// Q2 is the ending world rotation.
	Q2 Rot
}

Sweep describes the motion of a body for the time of impact. Shapes are defined about the body origin, which may differ from the center of mass, so the sweep interpolates the center of mass. It corresponds to b2Sweep in include/box2d/collision.h.

type TOIInput added in v0.3.0

type TOIInput struct {
	// ProxyA is the proxy for shape A.
	ProxyA ShapeProxy

	// ProxyB is the proxy for shape B.
	ProxyB ShapeProxy

	// SweepA is the movement of shape A.
	SweepA Sweep

	// SweepB is the movement of shape B.
	SweepB Sweep

	// MaxFraction defines the sweep interval [0, MaxFraction].
	MaxFraction Q
}

TOIInput is the input of TimeOfImpact. It corresponds to b2TOIInput in include/box2d/collision.h.

type TOIOutput added in v0.3.0

type TOIOutput struct {
	// State is the type of result.
	State TOIState

	// Fraction is the sweep time of the collision.
	Fraction Q
}

TOIOutput is the output of TimeOfImpact. It corresponds to b2TOIOutput in include/box2d/collision.h.

func TimeOfImpact added in v0.3.0

func TimeOfImpact(input *TOIInput) TOIOutput

TimeOfImpact computes the largest fraction of the sweeps at which the two proxies stay separated by the target. It uses the local separating axis method, so it may miss some intermediate, non-tunneling collisions. The reference counters under B2_SNOOP_TOI_COUNTERS are not ported. It corresponds to b2TimeOfImpact in src/distance.c.

type TOIState added in v0.3.0

type TOIState int

TOIState describes the result of TimeOfImpact. It corresponds to b2TOIState in include/box2d/collision.h.

const (
	// TOIStateUnknown means the solver did not reach a conclusion.
	TOIStateUnknown TOIState = iota

	// TOIStateFailed means the root finder ran out of iterations.
	TOIStateFailed

	// TOIStateOverlapped means the shapes overlap at the start.
	TOIStateOverlapped

	// TOIStateHit means the shapes touch at the fraction.
	TOIStateHit

	// TOIStateSeparated means the shapes stay apart over the whole interval.
	TOIStateSeparated
)

type Transform

type Transform struct {
	P Vec2
	Q Rot
}

Transform is a 2D rigid transform.

func GetSweepTransform added in v0.3.0

func GetSweepTransform(sweep *Sweep, time Q) Transform

GetSweepTransform evaluates the sweep at a time in [0, 1]. It corresponds to b2GetSweepTransform in src/distance.c.

func InvMulTransforms

func InvMulTransforms(a, b Transform) Transform

InvMulTransforms returns the transform that converts a point local to frame b into a point local to frame a.

v2 = inv(a.q) * (b.q * v1 + b.p - a.p)
   = inv(a.q) * b.q * v1 + inv(a.q) * (b.p - a.p)

func MulTransforms

func MulTransforms(a, b Transform) Transform

MulTransforms composes two transforms. Applied to a point local to frame b, the result converts it to a point local to frame a, then to a point in the world frame.

v2 = a.q.Rot(b.q.Rot(v1) + b.p) + a.p
   = (a.q * b.q).Rot(v1) + a.q.Rot(b.p) + a.p

func TransformIdentity

func TransformIdentity() Transform

TransformIdentity returns the transform that moves and rotates nothing.

type TreeStats added in v0.3.0

type TreeStats struct {
	// NodeVisits counts every node the walk touched.
	NodeVisits int

	// LeafVisits counts the leaves the walk tested.
	LeafVisits int
}

TreeStats counts the nodes a world query visited. It corresponds to b2TreeStats in include/box2d/collision.h.

func CastRay added in v0.3.0

func CastRay(worldId WorldId, origin, translation Vec2, filter QueryFilter, fcn CastResultFcn) TreeStats

CastRay reports the shapes a ray hits, tree by tree. The callback clips the ray for the next tree; a zero return stops the cast. A locked world panics. It corresponds to b2World_CastRay in src/world.c.

func CastShape added in v0.3.0

func CastShape(worldId WorldId, proxy *ShapeProxy, translation Vec2, filter QueryFilter, fcn CastResultFcn) TreeStats

CastShape sweeps a proxy through the world and reports each hit, tree by tree. The callback returns as for CastRay. A locked world panics. It corresponds to b2World_CastShape in src/world.c.

func OverlapAABB added in v0.3.0

func OverlapAABB(worldId WorldId, aabb AABB, filter QueryFilter, fcn OverlapResultFcn) TreeStats

OverlapAABB reports every shape whose fat bounds overlap the box and whose filter accepts the query. It walks the static, the kinematic and the dynamic tree in that order; a false result ends only the current tree, as in the reference. A locked world panics. It corresponds to b2World_OverlapAABB in src/world.c.

func OverlapShape added in v0.3.0

func OverlapShape(worldId WorldId, proxy *ShapeProxy, filter QueryFilter, fcn OverlapResultFcn) TreeStats

OverlapShape reports every shape that overlaps the proxy and whose filter accepts the query, tree by tree; a false result ends only the current tree. The distance solver decides the overlap, so the report is exact, not a bounds test. A locked world panics. It corresponds to b2World_OverlapShape in src/world.c.

type Vec2

type Vec2 = fixed.Vec2

Vec2 is a 2D vector. It represents a point or a free vector.

func AABBCenter

func AABBCenter(a AABB) Vec2

AABBCenter returns the center of a.

func AABBExtents

func AABBExtents(a AABB) Vec2

AABBExtents returns the half-widths of a.

func Abs

func Abs(a Vec2) Vec2

Abs returns the component-wise absolute value of a.

func Clamp

func Clamp(v, a, b Vec2) Vec2

Clamp returns v limited component-wise to the box [a, b].

func CrossSV

func CrossSV(s Q, v Vec2) Vec2

CrossSV returns the cross product of a scalar and a vector.

func CrossVS

func CrossVS(v Vec2, s Q) Vec2

CrossVS returns the cross product of a vector and a scalar.

func InvRotateVector

func InvRotateVector(q Rot, v Vec2) Vec2

InvRotateVector rotates v by the inverse of q.

func InvTransformPoint

func InvTransformPoint(t Transform, p Vec2) Vec2

InvTransformPoint carries the point p from the parent frame into the frame of t, for example from world space into local space.

func LeftPerp

func LeftPerp(v Vec2) Vec2

LeftPerp returns the left-pointing perpendicular of v. It equals CrossSV(one, v).

func Lerp

func Lerp(a, b Vec2, t Q) Vec2

Lerp interpolates between a and b by t.

It weighs both ends, unlike the Lerp method of the fixed-point module, which adds a scaled difference. The two round differently.

func Max

func Max(a, b Vec2) Vec2

Max returns the component-wise maximum of a and b.

func Min

func Min(a, b Vec2) Vec2

Min returns the component-wise minimum of a and b.

func Mul

func Mul(a, b Vec2) Vec2

Mul returns the component-wise product of a and b.

func MulAdd

func MulAdd(a Vec2, s Q, b Vec2) Vec2

MulAdd returns a + s * b.

func MulMV

func MulMV(m Mat22, v Vec2) Vec2

MulMV returns the product of the matrix m and the vector v.

func MulSub

func MulSub(a Vec2, s Q, b Vec2) Vec2

MulSub returns a - s * b.

func Neg

func Neg(a Vec2) Vec2

Neg returns the negation of a.

func RightPerp

func RightPerp(v Vec2) Vec2

RightPerp returns the right-pointing perpendicular of v. It equals CrossVS(v, one).

func RotGetXAxis

func RotGetXAxis(q Rot) Vec2

RotGetXAxis returns the x axis of q.

func RotGetYAxis

func RotGetYAxis(q Rot) Vec2

RotGetYAxis returns the y axis of q.

func RotateVector

func RotateVector(q Rot, v Vec2) Vec2

RotateVector rotates v by q.

func Solve22

func Solve22(m Mat22, b Vec2) Vec2

Solve22 solves m * x = b for the column vector b. It is cheaper than the inverse for a one-shot case. A singular matrix returns the zero vector.

func TransformPoint

func TransformPoint(t Transform, p Vec2) Vec2

TransformPoint carries the point p from the frame of t into the parent frame, for example from local space into world space.

func Vec2Zero

func Vec2Zero() Vec2

Vec2Zero returns the zero vector.

type Version

type Version struct {
	// Major counts significant changes.
	Major int

	// Minor counts incremental changes.
	Minor int

	// Revision counts bug fixes.
	Revision int
}

Version reports a three-part release number.

func ReferenceVersion

func ReferenceVersion() Version

ReferenceVersion returns the Box2D release that this package ports. The module has its own version; this one identifies the reference source.

type WeldJointDef added in v0.3.0

type WeldJointDef struct {
	// The first attached body.
	BodyIdA BodyId

	// The second attached body.
	BodyIdB BodyId

	// The local anchor point relative to the origin of body A.
	LocalAnchorA Vec2

	// The local anchor point relative to the origin of body B.
	LocalAnchorB Vec2

	// The angle of body B minus the angle of body A in the reference
	// state, in turns.
	ReferenceAngle Q

	// Linear stiffness in cycles per second. Zero means rigid.
	LinearHertz Q

	// Angular stiffness in cycles per second. Zero means rigid.
	AngularHertz Q

	// Linear damping ratio, non-dimensional.
	LinearDampingRatio Q

	// Angular damping ratio, non-dimensional.
	AngularDampingRatio Q

	// Set this flag to true if the attached bodies should collide.
	CollideConnected bool

	// Application data attached to the joint.
	UserData any
	// contains filtered or unexported fields
}

WeldJointDef configures a weld joint: it holds the relative transform of two bodies, rigidly or with a spring. Initialize it with DefaultWeldJointDef.

func DefaultWeldJointDef added in v0.3.0

func DefaultWeldJointDef() WeldJointDef

DefaultWeldJointDef returns the default weld joint definition.

type WheelJointDef added in v0.3.0

type WheelJointDef struct {
	// The first attached body.
	BodyIdA BodyId

	// The second attached body.
	BodyIdB BodyId

	// The local anchor point relative to the origin of body A.
	LocalAnchorA Vec2

	// The local anchor point relative to the origin of body B.
	LocalAnchorB Vec2

	// The local translation unit axis in body A.
	LocalAxisA Vec2

	// Enable a linear spring along the local axis.
	EnableSpring bool

	// The spring stiffness in cycles per second.
	Hertz Q

	// The spring damping ratio, non-dimensional.
	DampingRatio Q

	// Enable and disable the joint limit.
	EnableLimit bool

	// The lower translation limit.
	LowerTranslation Q

	// The upper translation limit.
	UpperTranslation Q

	// Enable and disable the joint rotational motor.
	EnableMotor bool

	// The maximum motor torque, usually in newton-meters.
	MaxMotorTorque Q

	// The desired motor speed in turns per second.
	MotorSpeed Q

	// Set this flag to true if the attached bodies should collide.
	CollideConnected bool

	// Application data attached to the joint.
	UserData any
	// contains filtered or unexported fields
}

WheelJointDef configures a wheel joint: body B rotates freely about a point on an axis fixed in body A, with a suspension spring along the axis. Initialize it with DefaultWheelJointDef.

func DefaultWheelJointDef added in v0.3.0

func DefaultWheelJointDef() WheelJointDef

DefaultWheelJointDef returns the default wheel joint definition.

type WorldDef

type WorldDef struct {
	// Gravity vector. The world has no up vector.
	Gravity Vec2

	// Restitution speed threshold, usually in meters per second. Collisions
	// above this speed have restitution applied, so they bounce.
	RestitutionThreshold Q

	// Threshold speed for hit events, usually in meters per second.
	HitEventThreshold Q

	// Contact stiffness in cycles per second. Increasing this increases the
	// speed of overlap recovery, but can introduce jitter.
	ContactHertz Q

	// Contact bounciness, non-dimensional. Decreasing this speeds up overlap
	// recovery, with a more energetic resolution as the trade-off.
	ContactDampingRatio Q

	// A cap on the overlap resolution speed, usually in meters per second.
	// The hertz and the damping ratio set the speed itself.
	MaxContactPushSpeed Q

	// Maximum linear speed, usually in meters per second.
	MaximumLinearSpeed Q

	// Enable sleeping to improve performance.
	EnableSleep bool

	// Enable continuous collision.
	EnableContinuous bool

	// Application data attached to the world.
	UserData any
	// contains filtered or unexported fields
}

WorldDef configures the creation of a world. Initialize it with DefaultWorldDef.

func DefaultWorldDef

func DefaultWorldDef() WorldDef

DefaultWorldDef returns the default world definition.

type WorldId

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

WorldId identifies a world. Its zero value is null.

func CreateWorld

func CreateWorld(def *WorldDef) WorldId

CreateWorld creates a world from a definition. The definition must come from DefaultWorldDef and is not retained. It returns the null id when every slot of the registry is in use.

func LoadWorldId

func LoadWorldId(x uint32) WorldId

LoadWorldId unpacks a world id from a uint32.

func (WorldId) Gravity

func (id WorldId) Gravity() Vec2

Gravity returns the gravity vector of the world.

func (WorldId) IsNull

func (id WorldId) IsNull() bool

IsNull reports whether the id references nothing.

func (WorldId) IsValid

func (id WorldId) IsValid() bool

IsValid reports whether the id references a live world. It lets an application hold ids safely across destruction.

Jump to

Keyboard shortcuts

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