mirror of
https://github.com/odin-lang/Odin.git
synced 2026-05-28 14:45:09 +00:00
494 lines
15 KiB
Odin
494 lines
15 KiB
Odin
package vendor_box2d
|
|
|
|
import "core:c"
|
|
|
|
|
|
// The maximum number of vertices on a convex polygon. Changing this affects performance even if you
|
|
// don't use more vertices.
|
|
MAX_POLYGON_VERTICES :: 8
|
|
|
|
// Low level ray cast input data
|
|
RayCastInput :: struct {
|
|
// Start point of the ray cast
|
|
origin: Vec2,
|
|
|
|
// Translation of the ray cast
|
|
translation: Vec2,
|
|
|
|
// The maximum fraction of the translation to consider, typically 1
|
|
maxFraction: f32,
|
|
}
|
|
|
|
// A distance proxy is used by the GJK algorithm. It encapsulates any shape.
|
|
// You can provide between 1 and MAX_POLYGON_VERTICES and a radius.
|
|
ShapeProxy :: struct {
|
|
// The point cloud
|
|
points: [MAX_POLYGON_VERTICES]Vec2 `fmt:"v,count"`,
|
|
|
|
// The number of points. Must be greater than 0.
|
|
count: c.int,
|
|
|
|
// The external radius of the point cloud. May be zero.
|
|
radius: f32,
|
|
}
|
|
|
|
// Low level shape cast input in generic form. This allows casting an arbitrary point
|
|
// cloud wrap with a radius. For example, a circle is a single point with a non-zero radius.
|
|
// A capsule is two points with a non-zero radius. A box is four points with a zero radius.
|
|
ShapeCastInput :: struct {
|
|
// A generic shape
|
|
proxy: ShapeProxy,
|
|
|
|
// The translation of the shape cast
|
|
translation: Vec2,
|
|
|
|
// The maximum fraction of the translation to consider, typically 1
|
|
maxFraction: f32,
|
|
|
|
// Allow shape cast to encroach when initially touching. This only works if the radius is greater than zero.
|
|
canEncroach: bool,
|
|
}
|
|
|
|
// Low level ray cast or shape-cast output data. Returns a zero fraction and normal in the case of initial overlap.
|
|
CastOutput :: struct {
|
|
// The surface normal at the hit point
|
|
normal: Vec2,
|
|
|
|
// The surface hit point
|
|
point: Vec2,
|
|
|
|
// The fraction of the input translation at collision
|
|
fraction: f32,
|
|
|
|
// The number of iterations used
|
|
iterations: c.int,
|
|
|
|
// Did the cast hit?
|
|
hit: bool,
|
|
}
|
|
|
|
// This holds the mass data computed for a shape.
|
|
MassData :: struct {
|
|
// The mass of the shape, usually in kilograms.
|
|
mass: f32,
|
|
|
|
// The position of the shape's centroid relative to the shape's origin.
|
|
center: Vec2,
|
|
|
|
// The rotational inertia of the shape about the local origin.
|
|
rotationalInertia: f32,
|
|
}
|
|
|
|
// A solid circle
|
|
Circle :: struct {
|
|
// The local center
|
|
center: Vec2,
|
|
|
|
// The radius
|
|
radius: f32,
|
|
}
|
|
|
|
// A solid capsule can be viewed as two semicircles connected
|
|
// by a rectangle.
|
|
Capsule :: struct {
|
|
// Local center of the first semicircle
|
|
center1: Vec2,
|
|
|
|
// Local center of the second semicircle
|
|
center2: Vec2,
|
|
|
|
// The radius of the semicircles
|
|
radius: f32,
|
|
}
|
|
|
|
// A solid convex polygon. It is assumed that the interior of the polygon is to
|
|
// the left of each edge.
|
|
// Polygons have a maximum number of vertices equal to MAX_POLYGON_VERTICES.
|
|
// In most cases you should not need many vertices for a convex polygon.
|
|
// @warning DO NOT fill this out manually, instead use a helper function like
|
|
// b2MakePolygon or b2MakeBox.
|
|
Polygon :: struct {
|
|
// The polygon vertices
|
|
vertices: [MAX_POLYGON_VERTICES]Vec2 `fmt:"v,count"`,
|
|
|
|
// The outward normal vectors of the polygon sides
|
|
normals: [MAX_POLYGON_VERTICES]Vec2 `fmt:"v,count"`,
|
|
|
|
// The centroid of the polygon
|
|
centroid: Vec2,
|
|
|
|
// The external radius for rounded polygons
|
|
radius: f32,
|
|
|
|
// The number of polygon vertices
|
|
count: c.int,
|
|
}
|
|
|
|
// A line segment with two-sided collision.
|
|
Segment :: struct {
|
|
// The first point
|
|
point1: Vec2,
|
|
|
|
// The second point
|
|
point2: Vec2,
|
|
}
|
|
|
|
// A line segment with one-sided collision. Only collides on the right side.
|
|
// Several of these are generated for a chain shape.
|
|
// ghost1 -> point1 -> point2 -> ghost2
|
|
ChainSegment :: struct {
|
|
// The tail ghost vertex
|
|
ghost1: Vec2,
|
|
|
|
// The line segment
|
|
segment: Segment,
|
|
|
|
// The head ghost vertex
|
|
ghost2: Vec2,
|
|
|
|
// The owning chain shape index (internal usage only)
|
|
chainId: c.int,
|
|
}
|
|
|
|
|
|
// A convex hull. Used to create convex polygons.
|
|
// @warning Do not modify these values directly, instead use b2ComputeHull()
|
|
Hull :: struct {
|
|
// The final points of the hull
|
|
points: [MAX_POLYGON_VERTICES]Vec2 `fmt:"v,count"`,
|
|
|
|
// The number of points
|
|
count: c.int,
|
|
}
|
|
|
|
/**
|
|
* @defgroup distance Distance
|
|
* Functions for computing the distance between shapes.
|
|
*
|
|
* These are advanced functions you can use to perform distance calculations. There
|
|
* are functions for computing the closest points between shapes, doing linear shape casts,
|
|
* and doing rotational shape casts. The latter is called time of impact (TOI).
|
|
*/
|
|
|
|
// Result of computing the distance between two line segments
|
|
SegmentDistanceResult :: struct {
|
|
// The closest point on the first segment
|
|
closest1: Vec2,
|
|
|
|
// The closest point on the second segment
|
|
closest2: Vec2,
|
|
|
|
// The barycentric coordinate on the first segment
|
|
fraction1: f32,
|
|
|
|
// The barycentric coordinate on the second segment
|
|
fraction2: f32,
|
|
|
|
// The squared distance between the closest points
|
|
distanceSquared: f32,
|
|
}
|
|
|
|
// Used to warm start the GJK simplex. If you call this function multiple times with nearby
|
|
// transforms this might improve performance. Otherwise you can zero initialize this.
|
|
// The distance cache must be initialized to zero on the first call.
|
|
// Users should generally just zero initialize this structure for each call.
|
|
SimplexCache :: struct {
|
|
// The number of stored simplex points
|
|
count: u16,
|
|
|
|
// The cached simplex indices on shape A
|
|
indexA: [3]u8 `fmt:"v,count"`,
|
|
|
|
// The cached simplex indices on shape B
|
|
indexB: [3]u8 `fmt:"v,count"`,
|
|
}
|
|
|
|
emptySimplexCache :: SimplexCache{}
|
|
|
|
// Input for b2ShapeDistance
|
|
DistanceInput :: struct {
|
|
// The proxy for shape A
|
|
proxyA: ShapeProxy,
|
|
|
|
// The proxy for shape B
|
|
proxyB: ShapeProxy,
|
|
|
|
// The world transform for shape A
|
|
transformA: Transform,
|
|
|
|
// The world transform for shape B
|
|
transformB: Transform,
|
|
|
|
// Should the proxy radius be considered?
|
|
useRadii: bool,
|
|
}
|
|
|
|
// Output for b2ShapeDistance
|
|
DistanceOutput :: struct {
|
|
pointA: Vec2, // Closest point on shapeA
|
|
pointB: Vec2, // Closest point on shapeB
|
|
normal: Vec2, // Normal vector that points from A to B. Invalid if distance is zero.
|
|
distance: f32, // The final distance, zero if overlapped
|
|
iterations: i32, // Number of GJK iterations used
|
|
simplexCount: i32, // The number of simplexes stored in the simplex array
|
|
}
|
|
|
|
// Simplex vertex for debugging the GJK algorithm
|
|
SimplexVertex :: struct {
|
|
wA: Vec2, // support point in proxyA
|
|
wB: Vec2, // support point in proxyB
|
|
w: Vec2, // wB - wA
|
|
a: f32, // barycentric coordinate for closest point
|
|
indexA: c.int, // wA index
|
|
indexB: c.int, // wB index
|
|
}
|
|
|
|
// Simplex from the GJK algorithm
|
|
Simplex :: struct {
|
|
v1, v2, v3: SimplexVertex `fmt:"v,count"`, // vertices
|
|
count: c.int, // number of valid vertices
|
|
}
|
|
|
|
// Input parameters for b2ShapeCast
|
|
ShapeCastPairInput :: struct {
|
|
proxyA: ShapeProxy, // The proxy for shape A
|
|
proxyB: ShapeProxy, // The proxy for shape B
|
|
transformA: Transform, // The world transform for shape A
|
|
transformB: Transform, // The world transform for shape B
|
|
translationB: Vec2, // The translation of shape B
|
|
maxFraction: f32, // The fraction of the translation to consider, typically 1
|
|
canEncroach: bool, // Allows shapes with a radius to move slightly closer if already touching
|
|
}
|
|
|
|
|
|
// This describes the motion of a body/shape for TOI computation. Shapes are defined with respect to the body origin,
|
|
// which may not coincide with the center of mass. However, to support dynamics we must interpolate the center of mass
|
|
// position.
|
|
Sweep :: struct {
|
|
localCenter: Vec2, // Local center of mass position
|
|
c1: Vec2, // Starting center of mass world position
|
|
c2: Vec2, // Ending center of mass world position
|
|
q1: Rot, // Starting world rotation
|
|
q2: Rot, // Ending world rotation
|
|
}
|
|
|
|
// Input parameters for b2TimeOfImpact
|
|
TOIInput :: struct {
|
|
proxyA: ShapeProxy, // The proxy for shape A
|
|
proxyB: ShapeProxy, // The proxy for shape B
|
|
sweepA: Sweep, // The movement of shape A
|
|
sweepB: Sweep, // The movement of shape B
|
|
maxFraction: f32, // Defines the sweep interval [0, maxFraction]
|
|
}
|
|
|
|
// Describes the TOI output
|
|
TOIState :: enum c.int {
|
|
Unknown,
|
|
Failed,
|
|
Overlapped,
|
|
Hit,
|
|
Separated,
|
|
}
|
|
|
|
// Output parameters for b2TimeOfImpact.
|
|
TOIOutput :: struct {
|
|
state: TOIState, // The type of result
|
|
fraction: f32, // The sweep time of the collision
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @defgroup collision Collision
|
|
* @brief Functions for colliding pairs of shapes
|
|
*/
|
|
|
|
// A manifold point is a contact point belonging to a contact manifold.
|
|
// It holds details related to the geometry and dynamics of the contact points.
|
|
// Box2D uses speculative collision so some contact points may be separated.
|
|
// You may use the totalNormalImpulse to determine if there was an interaction during
|
|
// the time step.
|
|
ManifoldPoint :: struct {
|
|
// Location of the contact point in world space. Subject to precision loss at large coordinates.
|
|
// @note Should only be used for debugging.
|
|
point: Vec2,
|
|
|
|
// Location of the contact point relative to shapeA's origin in world space
|
|
// @note When used internally to the Box2D solver, this is relative to the body center of mass.
|
|
anchorA: Vec2,
|
|
|
|
// Location of the contact point relative to shapeB's origin in world space
|
|
// @note When used internally to the Box2D solver, this is relative to the body center of mass.
|
|
anchorB: Vec2,
|
|
|
|
// The separation of the contact point, negative if penetrating
|
|
separation: f32,
|
|
|
|
// The total normal impulse applied across sub-stepping and restitution. This is important
|
|
// to identify speculative contact points that had an interaction in the time step.
|
|
totalNormalImpulse: f32,
|
|
|
|
// The friction impulse
|
|
tangentImpulse: f32,
|
|
|
|
// The maximum normal impulse applied during sub-stepping
|
|
// todo not sure this is needed
|
|
maxNormalImpulse: f32,
|
|
|
|
// Relative normal velocity pre-solve. Used for hit events. If the normal impulse is
|
|
// zero then there was no hit. Negative means shapes are approaching.
|
|
normalVelocity: f32,
|
|
|
|
// Uniquely identifies a contact point between two shapes
|
|
id: u16,
|
|
|
|
// Did this contact point exist the previous step?
|
|
persisted: bool,
|
|
}
|
|
|
|
// A contact manifold describes the contact points between colliding shapes.
|
|
// @note Box2D uses speculative collision so some contact points may be separated.
|
|
Manifold :: struct {
|
|
// The unit normal vector in world space, points from shape A to bodyB
|
|
normal: Vec2,
|
|
|
|
// Angular impulse applied for rolling resistance. N * m * s = kg * m^2 / s
|
|
rollingImpulse: f32,
|
|
|
|
// The manifold points, up to two are possible in 2D
|
|
points: [2]ManifoldPoint,
|
|
|
|
|
|
// The number of contacts points, will be 0, 1, or 2
|
|
pointCount: c.int,
|
|
}
|
|
|
|
|
|
/**
|
|
* @defgroup tree Dynamic Tree
|
|
* The dynamic tree is a binary AABB tree to organize and query large numbers of geometric objects
|
|
*
|
|
* Box2D uses the dynamic tree internally to sort collision shapes into a binary bounding volume hierarchy.
|
|
* This data structure may have uses in games for organizing other geometry data and may be used independently
|
|
* of Box2D rigid body simulation.
|
|
*
|
|
* A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
|
|
* A dynamic tree arranges data in a binary tree to accelerate
|
|
* queries such as AABB queries and ray casts. Leaf nodes are proxies
|
|
* with an AABB. These are used to hold a user collision object.
|
|
* Nodes are pooled and relocatable, so I use node indices rather than pointers.
|
|
* The dynamic tree is made available for advanced users that would like to use it to organize
|
|
* spatial game data besides rigid bodies.
|
|
*/
|
|
|
|
// The dynamic tree structure. This should be considered private data.
|
|
// It is placed here for performance reasons.
|
|
DynamicTree :: struct {
|
|
// The tree nodes
|
|
nodes: rawptr,
|
|
|
|
// The root index
|
|
root: i32,
|
|
|
|
// The number of nodes
|
|
nodeCount: i32,
|
|
|
|
// The allocated node space
|
|
nodeCapacity: i32,
|
|
|
|
// Node free list
|
|
freeList: i32,
|
|
|
|
// Number of proxies created
|
|
proxyCount: i32,
|
|
|
|
// Leaf indices for rebuild
|
|
leafIndices: [^]i32,
|
|
|
|
// Leaf bounding boxes for rebuild
|
|
leafBoxes: [^]AABB,
|
|
|
|
// Leaf bounding box centers for rebuild
|
|
leafCenters: [^]Vec2,
|
|
|
|
// Bins for sorting during rebuild
|
|
binIndices: [^]i32,
|
|
|
|
// Allocated space for rebuilding
|
|
rebuildCapacity: i32,
|
|
}
|
|
|
|
// These are performance results returned by dynamic tree queries.
|
|
TreeStats :: struct {
|
|
// Number of internal nodes visited during the query
|
|
nodeVisits: c.int,
|
|
|
|
// Number of leaf nodes visited during the query
|
|
leafVisits: c.int,
|
|
}
|
|
|
|
// This function receives proxies found in the AABB query.
|
|
// @return true if the query should continue
|
|
TreeQueryCallbackFcn :: #type proc "c" (proxyId: i32, userData: u64, ctx: rawptr) -> bool
|
|
|
|
// This function receives clipped ray cast input for a proxy. The function
|
|
// returns the new ray fraction.
|
|
// - return a value of 0 to terminate the ray cast
|
|
// - return a value less than input->maxFraction to clip the ray
|
|
// - return a value of input->maxFraction to continue the ray cast without clipping
|
|
TreeShapeCastCallbackFcn :: #type proc "c" (#by_ptr input: ShapeCastInput, proxyId: i32, userData: u64, ctx: rawptr) -> f32
|
|
|
|
|
|
// This function receives clipped raycast input for a proxy. The function
|
|
// returns the new ray fraction.
|
|
// - return a value of 0 to terminate the ray cast
|
|
// - return a value less than input->maxFraction to clip the ray
|
|
// - return a value of input->maxFraction to continue the ray cast without clipping
|
|
TreeRayCastCallbackFcn :: #type proc "c" (#by_ptr input: RayCastInput, proxyId: i32, userData: u64, ctx: rawptr) -> f32
|
|
|
|
/**@}*/
|
|
|
|
/**
|
|
* @defgroup character Character mover
|
|
* Character movement solver
|
|
* @{
|
|
*/
|
|
|
|
/// These are the collision planes returned from b2World_CollideMover
|
|
PlaneResult :: struct {
|
|
// The collision plane between the mover and convex shape
|
|
plane: Plane,
|
|
|
|
// The collision point on the shape.
|
|
point: Vec2,
|
|
|
|
// Did the collision register a hit? If not this plane should be ignored.
|
|
hit: bool,
|
|
}
|
|
|
|
// These are collision planes that can be fed to b2SolvePlanes. Normally
|
|
// this is assembled by the user from plane results in b2PlaneResult
|
|
CollisionPlane :: struct {
|
|
// The collision plane between the mover and some shape
|
|
plane: Plane,
|
|
|
|
// Setting this to FLT_MAX makes the plane as rigid as possible. Lower values can
|
|
// make the plane collision soft. Usually in meters.
|
|
pushLimit: f32,
|
|
|
|
// The push on the mover determined by b2SolvePlanes. Usually in meters.
|
|
push: f32,
|
|
|
|
// Indicates if b2ClipVector should clip against this plane. Should be false for soft collision.
|
|
clipVelocity: bool,
|
|
}
|
|
|
|
// Result returned by b2SolvePlanes
|
|
PlaneSolverResult :: struct {
|
|
// The translation of the mover
|
|
translation: Vec2,
|
|
|
|
// The number of iterations used by the plane solver. For diagnostics.
|
|
iterationCount: i32,
|
|
}
|