mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-13 23:03:16 +00:00
Merge pull request #5069 from laytan/box2d-3.1.0
box2d: update to 3.1.0
This commit is contained in:
627
vendor/box2d/box2d.odin
vendored
627
vendor/box2d/box2d.odin
vendored
File diff suppressed because it is too large
Load Diff
6
vendor/box2d/build_box2d.sh
vendored
6
vendor/box2d/build_box2d.sh
vendored
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
|
||||
VERSION="3.0.0"
|
||||
VERSION="3.1.0"
|
||||
RELEASE="https://github.com/erincatto/box2d/archive/refs/tags/v$VERSION.tar.gz"
|
||||
|
||||
cd "$(odin root)"/vendor/box2d
|
||||
@@ -75,5 +75,5 @@ if [[ $? -ne 0 ]]; then
|
||||
fi
|
||||
set -e
|
||||
|
||||
rm -rf v3.0.0.tar.gz
|
||||
rm -rf box2d-3.0.0
|
||||
rm -rf "v$VERSION.tar.gz"
|
||||
rm -rf box2d-"$VERSION"
|
||||
|
||||
269
vendor/box2d/collision.odin
vendored
269
vendor/box2d/collision.odin
vendored
@@ -5,9 +5,9 @@ import "core:c"
|
||||
|
||||
// The maximum number of vertices on a convex polygon. Changing this affects performance even if you
|
||||
// don't use more vertices.
|
||||
maxPolygonVertices :: 8
|
||||
MAX_POLYGON_VERTICES :: 8
|
||||
|
||||
// Low level ray-cast input data
|
||||
// Low level ray cast input data
|
||||
RayCastInput :: struct {
|
||||
// Start point of the ray cast
|
||||
origin: Vec2,
|
||||
@@ -19,27 +19,37 @@ RayCastInput :: struct {
|
||||
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.
|
||||
// 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 point cloud to cast
|
||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The number of points
|
||||
count: i32,
|
||||
|
||||
// The radius around the point cloud
|
||||
radius: f32,
|
||||
// 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
|
||||
// Low level ray cast or shape-cast output data
|
||||
CastOutput :: struct {
|
||||
// The surface normal at the hit point
|
||||
normal: Vec2,
|
||||
@@ -51,7 +61,7 @@ CastOutput :: struct {
|
||||
fraction: f32,
|
||||
|
||||
// The number of iterations used
|
||||
iterations: i32,
|
||||
iterations: c.int,
|
||||
|
||||
// Did the cast hit?
|
||||
hit: bool,
|
||||
@@ -93,16 +103,16 @@ Capsule :: struct {
|
||||
|
||||
// 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 maxPolygonVertices.
|
||||
// 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.
|
||||
// @warning DO NOT fill this out manually, instead use a helper function like
|
||||
// b2MakePolygon or b2MakeBox.
|
||||
Polygon :: struct {
|
||||
// The polygon vertices
|
||||
vertices: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
vertices: [MAX_POLYGON_VERTICES]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The outward normal vectors of the polygon sides
|
||||
normals: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
normals: [MAX_POLYGON_VERTICES]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The centroid of the polygon
|
||||
centroid: Vec2,
|
||||
@@ -111,7 +121,7 @@ Polygon :: struct {
|
||||
radius: f32,
|
||||
|
||||
// The number of polygon vertices
|
||||
count: i32,
|
||||
count: c.int,
|
||||
}
|
||||
|
||||
// A line segment with two-sided collision.
|
||||
@@ -123,10 +133,10 @@ Segment :: struct {
|
||||
point2: Vec2,
|
||||
}
|
||||
|
||||
// A smooth line segment with one-sided collision. Only collides on the right side.
|
||||
// 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
|
||||
SmoothSegment :: struct {
|
||||
ChainSegment :: struct {
|
||||
// The tail ghost vertex
|
||||
ghost1: Vec2,
|
||||
|
||||
@@ -137,7 +147,7 @@ SmoothSegment :: struct {
|
||||
ghost2: Vec2,
|
||||
|
||||
// The owning chain shape index (internal usage only)
|
||||
chainId: i32,
|
||||
chainId: c.int,
|
||||
}
|
||||
|
||||
|
||||
@@ -145,10 +155,10 @@ SmoothSegment :: struct {
|
||||
// @warning Do not modify these values directly, instead use b2ComputeHull()
|
||||
Hull :: struct {
|
||||
// The final points of the hull
|
||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
points: [MAX_POLYGON_VERTICES]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The number of points
|
||||
count: i32,
|
||||
count: c.int,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,21 +188,11 @@ SegmentDistanceResult :: struct {
|
||||
distanceSquared: f32,
|
||||
}
|
||||
|
||||
// A distance proxy is used by the GJK algorithm. It encapsulates any shape.
|
||||
DistanceProxy :: struct {
|
||||
// The point cloud
|
||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
||||
|
||||
// The number of points
|
||||
count: i32,
|
||||
|
||||
// The external radius of the point cloud
|
||||
radius: f32,
|
||||
}
|
||||
|
||||
// Used to warm start b2Distance. Set count to zero on first call or
|
||||
// use zero initialization.
|
||||
DistanceCache :: struct {
|
||||
// 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,
|
||||
|
||||
@@ -203,15 +203,15 @@ DistanceCache :: struct {
|
||||
indexB: [3]u8 `fmt:"v,count"`,
|
||||
}
|
||||
|
||||
emptyDistanceCache :: DistanceCache{}
|
||||
emptySimplexCache :: SimplexCache{}
|
||||
|
||||
// Input for b2ShapeDistance
|
||||
DistanceInput :: struct {
|
||||
// The proxy for shape A
|
||||
proxyA: DistanceProxy,
|
||||
proxyA: ShapeProxy,
|
||||
|
||||
// The proxy for shape B
|
||||
proxyB: DistanceProxy,
|
||||
proxyB: ShapeProxy,
|
||||
|
||||
// The world transform for shape A
|
||||
transformA: Transform,
|
||||
@@ -227,6 +227,7 @@ DistanceInput :: struct {
|
||||
DistanceOutput :: struct {
|
||||
pointA: Vec2, // Closest point on shapeA
|
||||
pointB: Vec2, // Closest point on shapeB
|
||||
normal: Vec2, // Normal vector that points from A to B
|
||||
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
|
||||
@@ -234,28 +235,29 @@ DistanceOutput :: struct {
|
||||
|
||||
// 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: i32, // wA index
|
||||
indexB: i32, // wB index
|
||||
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: i32, // number of valid vertices
|
||||
count: c.int, // number of valid vertices
|
||||
}
|
||||
|
||||
// Input parameters for b2ShapeCast
|
||||
ShapeCastPairInput :: struct {
|
||||
proxyA: DistanceProxy, // The proxy for shape A
|
||||
proxyB: DistanceProxy, // The proxy for shape B
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -272,11 +274,11 @@ Sweep :: struct {
|
||||
|
||||
// Input parameters for b2TimeOfImpact
|
||||
TOIInput :: struct {
|
||||
proxyA: DistanceProxy, // The proxy for shape A
|
||||
proxyB: DistanceProxy, // The proxy for shape B
|
||||
sweepA: Sweep, // The movement of shape A
|
||||
sweepB: Sweep, // The movement of shape B
|
||||
tMax: f32, // Defines the sweep interval [0, tMax]
|
||||
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
|
||||
@@ -290,8 +292,8 @@ TOIState :: enum c.int {
|
||||
|
||||
// Output parameters for b2TimeOfImpact.
|
||||
TOIOutput :: struct {
|
||||
state: TOIState, // The type of result
|
||||
t: f32, // The time of the collision
|
||||
state: TOIState, // The type of result
|
||||
fraction: f32, // The sweep time of the collision
|
||||
}
|
||||
|
||||
|
||||
@@ -301,26 +303,30 @@ TOIOutput :: struct {
|
||||
* @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.
|
||||
// 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 bodyA's origin in world space
|
||||
// @note When used internally to the Box2D solver, these are relative to the center of mass.
|
||||
// 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 bodyB's origin in world space
|
||||
// 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 impulse along the manifold normal vector.
|
||||
normalImpulse: 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,
|
||||
@@ -340,16 +346,21 @@ ManifoldPoint :: struct {
|
||||
persisted: bool,
|
||||
}
|
||||
|
||||
// A contact manifold describes the contact points between colliding shapes
|
||||
// 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 manifold points, up to two are possible in 2D
|
||||
points: [2]ManifoldPoint,
|
||||
|
||||
// The unit normal vector in world space, points from shape A to bodyB
|
||||
normal: Vec2,
|
||||
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: i32,
|
||||
pointCount: c.int,
|
||||
}
|
||||
|
||||
|
||||
@@ -364,63 +375,17 @@ Manifold :: struct {
|
||||
* 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, such as a reference to a b2Shape.
|
||||
* 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.
|
||||
*
|
||||
* @note This is an advanced feature and normally not used by applications directly.
|
||||
*/
|
||||
|
||||
// The default category bit for a tree proxy. Used for collision filtering.
|
||||
defaultCategoryBits :: 0x00000001
|
||||
|
||||
// Convenience mask bits to use when you don't need collision filtering and just want
|
||||
// all results.
|
||||
defaultMaskBits :: 0xFFFFFFFF
|
||||
|
||||
// A node in the dynamic tree. This is private data placed here for performance reasons.
|
||||
// 16 + 16 + 8 + pad(8)
|
||||
TreeNode :: struct {
|
||||
// The node bounding box
|
||||
aabb: AABB, // 16
|
||||
|
||||
// Category bits for collision filtering
|
||||
categoryBits: u32, // 4
|
||||
|
||||
using _: struct #raw_union {
|
||||
// The node parent index
|
||||
parent: i32,
|
||||
|
||||
// The node freelist next index
|
||||
next: i32,
|
||||
}, // 4
|
||||
|
||||
// Child 1 index
|
||||
child1: i32, // 4
|
||||
|
||||
// Child 2 index
|
||||
child2: i32, // 4
|
||||
|
||||
// User data
|
||||
// todo could be union with child index
|
||||
userData: i32, // 4
|
||||
|
||||
// Leaf = 0, free node = -1
|
||||
height: i16, // 2
|
||||
|
||||
// Has the AABB been enlarged?
|
||||
enlarged: bool, // 1
|
||||
|
||||
// Padding for clarity
|
||||
_: [9]byte,
|
||||
}
|
||||
|
||||
// The dynamic tree structure. This should be considered private data.
|
||||
// It is placed here for performance reasons.
|
||||
DynamicTree :: struct {
|
||||
// The tree nodes
|
||||
nodes: [^]TreeNode `fmt"v,nodeCount"`,
|
||||
nodes: rawptr,
|
||||
|
||||
// The root index
|
||||
root: i32,
|
||||
@@ -453,16 +418,25 @@ DynamicTree :: struct {
|
||||
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: i32, ctx: rawptr) -> bool
|
||||
TreeQueryCallbackFcn :: #type proc "c" (proxyId: i32, userData: u64, ctx: rawptr) -> bool
|
||||
|
||||
// This function receives clipped ray-cast input for a proxy. The function
|
||||
// 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 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: i32, ctx: rawptr) -> f32
|
||||
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
|
||||
@@ -470,4 +444,47 @@ TreeShapeCastCallbackFcn :: #type proc "c" (#by_ptr input: ShapeCastInput, proxy
|
||||
// - 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: i32, ctx: rawptr) -> f32
|
||||
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,
|
||||
|
||||
// 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 final position of the mover
|
||||
position: Vec2,
|
||||
|
||||
// The number of iterations used by the plane solver. For diagnostics.
|
||||
iterationCount: i32,
|
||||
}
|
||||
|
||||
43
vendor/box2d/id.odin
vendored
43
vendor/box2d/id.odin
vendored
@@ -23,45 +23,46 @@ import "base:intrinsics"
|
||||
|
||||
/// World id references a world instance. This should be treated as an opaque handle.
|
||||
WorldId :: struct {
|
||||
index1: u16,
|
||||
revision: u16,
|
||||
index1: u16,
|
||||
generation: u16,
|
||||
}
|
||||
|
||||
/// Body id references a body instance. This should be treated as an opaque handle.
|
||||
BodyId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
revision: u16,
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
generation: u16,
|
||||
}
|
||||
|
||||
/// Shape id references a shape instance. This should be treated as an opaque handle.
|
||||
ShapeId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
revision: u16,
|
||||
}
|
||||
|
||||
/// Joint id references a joint instance. This should be treated as an opaque handle.
|
||||
JointId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
revision: u16,
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
generation: u16,
|
||||
}
|
||||
|
||||
/// Chain id references a chain instances. This should be treated as an opaque handle.
|
||||
ChainId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
revision: u16,
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
generation: u16,
|
||||
}
|
||||
|
||||
/// Joint id references a joint instance. This should be treated as an opaque handle.
|
||||
JointId :: struct {
|
||||
index1: i32,
|
||||
world0: u16,
|
||||
generation: u16,
|
||||
}
|
||||
|
||||
|
||||
/// Use these to make your identifiers null.
|
||||
/// You may also use zero initialization to get null.
|
||||
nullWorldId :: WorldId{}
|
||||
nullBodyId :: BodyId{}
|
||||
nullShapeId :: ShapeId{}
|
||||
nullJointId :: JointId{}
|
||||
nullChainId :: ChainId{}
|
||||
nullJointId :: JointId{}
|
||||
|
||||
/// Macro to determine if any id is null.
|
||||
IS_NULL :: #force_inline proc "c" (id: $T) -> bool
|
||||
@@ -82,6 +83,6 @@ ID_EQUALS :: #force_inline proc "c" (id1, id2: $T) -> bool
|
||||
where intrinsics.type_is_struct(T),
|
||||
intrinsics.type_has_field(T, "index1"),
|
||||
intrinsics.type_has_field(T, "world0"),
|
||||
intrinsics.type_has_field(T, "revision") {
|
||||
return id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.revision == id2.revision
|
||||
intrinsics.type_has_field(T, "generation") {
|
||||
return id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.generation == id2.generation
|
||||
}
|
||||
|
||||
BIN
vendor/box2d/lib/box2d_darwin_amd64_avx2.a
vendored
BIN
vendor/box2d/lib/box2d_darwin_amd64_avx2.a
vendored
Binary file not shown.
BIN
vendor/box2d/lib/box2d_darwin_amd64_sse2.a
vendored
BIN
vendor/box2d/lib/box2d_darwin_amd64_sse2.a
vendored
Binary file not shown.
BIN
vendor/box2d/lib/box2d_darwin_arm64.a
vendored
BIN
vendor/box2d/lib/box2d_darwin_arm64.a
vendored
Binary file not shown.
BIN
vendor/box2d/lib/box2d_wasm.o
vendored
BIN
vendor/box2d/lib/box2d_wasm.o
vendored
Binary file not shown.
BIN
vendor/box2d/lib/box2d_wasm_simd.o
vendored
BIN
vendor/box2d/lib/box2d_wasm_simd.o
vendored
Binary file not shown.
BIN
vendor/box2d/lib/box2d_windows_amd64_avx2.lib
vendored
BIN
vendor/box2d/lib/box2d_windows_amd64_avx2.lib
vendored
Binary file not shown.
BIN
vendor/box2d/lib/box2d_windows_amd64_sse2.lib
vendored
BIN
vendor/box2d/lib/box2d_windows_amd64_sse2.lib
vendored
Binary file not shown.
317
vendor/box2d/math_functions.odin
vendored
317
vendor/box2d/math_functions.odin
vendored
@@ -3,9 +3,18 @@ package vendor_box2d
|
||||
import "core:c"
|
||||
import "core:math"
|
||||
|
||||
pi :: 3.14159265359
|
||||
EPSILON :: 1e-23
|
||||
|
||||
Vec2 :: [2]f32
|
||||
|
||||
// Cosine and sine pair
|
||||
// This uses a custom implementation designed for cross-platform determinism
|
||||
CosSin :: struct {
|
||||
// cosine and sine
|
||||
cosine: f32,
|
||||
sine: f32,
|
||||
}
|
||||
|
||||
Rot :: struct {
|
||||
c, s: f32, // cosine and sine
|
||||
}
|
||||
@@ -21,11 +30,43 @@ AABB :: struct {
|
||||
upperBound: Vec2,
|
||||
}
|
||||
|
||||
// separation = dot(normal, point) - offset
|
||||
Plane :: struct {
|
||||
normal: Vec2,
|
||||
offset: f32,
|
||||
}
|
||||
|
||||
PI :: math.PI
|
||||
|
||||
Vec2_zero :: Vec2{0, 0}
|
||||
Rot_identity :: Rot{1, 0}
|
||||
Transform_identity :: Transform{{0, 0}, {1, 0}}
|
||||
Mat22_zero :: Mat22{0, 0, 0, 0}
|
||||
|
||||
// @return the minimum of two integers
|
||||
@(deprecated="Prefer the built-in 'min(a, b)'", require_results)
|
||||
MinInt :: proc "c" (a, b: c.int) -> c.int {
|
||||
return min(a, b)
|
||||
}
|
||||
|
||||
// @return the maximum of two integers
|
||||
@(deprecated="Prefer the built-in 'max(a, b)'", require_results)
|
||||
MaxInt :: proc "c" (a, b: c.int) -> c.int {
|
||||
return max(a, b)
|
||||
}
|
||||
|
||||
// @return the absolute value of an integer
|
||||
@(deprecated="Prefer the built-in 'abs(a)'", require_results)
|
||||
AbsInt :: proc "c" (a: c.int) -> c.int {
|
||||
return abs(a)
|
||||
}
|
||||
|
||||
// @return an integer clamped between a lower and upper bound
|
||||
@(deprecated="Prefer the built-in 'clamp(a, lower, upper)'", require_results)
|
||||
ClampInt :: proc "c" (a, lower, upper: c.int) -> c.int {
|
||||
return clamp(a, lower, upper)
|
||||
}
|
||||
|
||||
|
||||
// @return the minimum of two floats
|
||||
@(deprecated="Prefer the built-in 'min(a, b)'", require_results)
|
||||
@@ -51,28 +92,15 @@ ClampFloat :: proc "c" (a, lower, upper: f32) -> f32 {
|
||||
return clamp(a, lower, upper)
|
||||
}
|
||||
|
||||
// @return the minimum of two integers
|
||||
@(deprecated="Prefer the built-in 'min(a, b)'", require_results)
|
||||
MinInt :: proc "c" (a, b: c.int) -> c.int {
|
||||
return min(a, b)
|
||||
@(require_results)
|
||||
Atan2 :: proc "c" (y, x: f32) -> f32 {
|
||||
return math.atan2(y, x)
|
||||
}
|
||||
|
||||
// @return the maximum of two integers
|
||||
@(deprecated="Prefer the built-in 'max(a, b)'", require_results)
|
||||
MaxInt :: proc "c" (a, b: c.int) -> c.int {
|
||||
return max(a, b)
|
||||
}
|
||||
|
||||
// @return the absolute value of an integer
|
||||
@(deprecated="Prefer the built-in 'abs(a)'", require_results)
|
||||
AbsInt :: proc "c" (a: c.int) -> c.int {
|
||||
return abs(a)
|
||||
}
|
||||
|
||||
// @return an integer clamped between a lower and upper bound
|
||||
@(deprecated="Prefer the built-in 'clamp(a, lower, upper)'", require_results)
|
||||
ClampInt :: proc "c" (a, lower, upper: c.int) -> c.int {
|
||||
return clamp(a, lower, upper)
|
||||
@(require_results)
|
||||
ComputeCosSin :: proc "c" (radians: f32) -> (res: CosSin) {
|
||||
res.sine, res.cosine = math.sincos(radians)
|
||||
return
|
||||
}
|
||||
|
||||
// Vector dot product
|
||||
@@ -198,12 +226,6 @@ Length :: proc "c" (v: Vec2) -> f32 {
|
||||
return math.sqrt(v.x * v.x + v.y * v.y)
|
||||
}
|
||||
|
||||
// Get the length squared of this vector
|
||||
@(require_results)
|
||||
LengthSquared :: proc "c" (v: Vec2) -> f32 {
|
||||
return v.x * v.x + v.y * v.y
|
||||
}
|
||||
|
||||
// Get the distance between two points
|
||||
@(require_results)
|
||||
Distance :: proc "c" (a, b: Vec2) -> f32 {
|
||||
@@ -212,45 +234,41 @@ Distance :: proc "c" (a, b: Vec2) -> f32 {
|
||||
return math.sqrt(dx * dx + dy * dy)
|
||||
}
|
||||
|
||||
// Get the distance squared between points
|
||||
@(require_results)
|
||||
DistanceSquared :: proc "c" (a, b: Vec2) -> f32 {
|
||||
c := Vec2{b.x - a.x, b.y - a.y}
|
||||
return c.x * c.x + c.y * c.y
|
||||
Normalize :: proc "c" (v: Vec2) -> Vec2 {
|
||||
length := Length(v)
|
||||
if length < EPSILON {
|
||||
return Vec2_zero
|
||||
}
|
||||
invLength := 1 / length
|
||||
return invLength * v
|
||||
}
|
||||
|
||||
// Make a rotation using an angle in radians
|
||||
@(require_results)
|
||||
MakeRot :: proc "c" (angle: f32) -> Rot {
|
||||
// todo determinism
|
||||
return {math.cos(angle), math.sin(angle)}
|
||||
IsNormalized :: proc "c" (v: Vec2) -> bool {
|
||||
aa := Dot(v, v)
|
||||
return abs(1. - aa) < 10. * EPSILON
|
||||
}
|
||||
|
||||
// Normalize rotation
|
||||
@(require_results)
|
||||
NormalizeRot :: proc "c" (q: Rot) -> Rot {
|
||||
mag := math.sqrt(q.s * q.s + q.c * q.c)
|
||||
invMag := f32(mag > 0.0 ? 1.0 / mag : 0.0)
|
||||
return {q.c * invMag, q.s * invMag}
|
||||
NormalizeChecked :: proc "odin" (v: Vec2) -> Vec2 {
|
||||
length := Length(v)
|
||||
if length < 1e-23 {
|
||||
panic("zero-length Vec2")
|
||||
}
|
||||
invLength := 1 / length
|
||||
return invLength * v
|
||||
}
|
||||
|
||||
// Is this rotation normalized?
|
||||
@(require_results)
|
||||
IsNormalized :: proc "c" (q: Rot) -> bool {
|
||||
// larger tolerance due to failure on mingw 32-bit
|
||||
qq := q.s * q.s + q.c * q.c
|
||||
return 1.0 - 0.0006 < qq && qq < 1 + 0.0006
|
||||
}
|
||||
|
||||
// Normalized linear interpolation
|
||||
// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
|
||||
@(require_results)
|
||||
NLerp :: proc "c" (q1: Rot, q2: Rot, t: f32) -> Rot {
|
||||
omt := 1 - t
|
||||
return NormalizeRot({
|
||||
omt * q1.c + t * q2.c,
|
||||
omt * q1.s + t * q2.s,
|
||||
})
|
||||
GetLengthAndNormalize :: proc "c" (v: Vec2) -> (length: f32, vn: Vec2) {
|
||||
length = Length(v)
|
||||
if length < 1e-23 {
|
||||
return
|
||||
}
|
||||
invLength := 1 / length
|
||||
vn = invLength * v
|
||||
return
|
||||
}
|
||||
|
||||
// Integration rotation from angular velocity
|
||||
@@ -268,6 +286,63 @@ IntegrateRotation :: proc "c" (q1: Rot, deltaAngle: f32) -> Rot {
|
||||
return {q2.c * invMag, q2.s * invMag}
|
||||
}
|
||||
|
||||
// Get the length squared of this vector
|
||||
@(require_results)
|
||||
LengthSquared :: proc "c" (v: Vec2) -> f32 {
|
||||
return v.x * v.x + v.y * v.y
|
||||
}
|
||||
|
||||
// Get the distance squared between points
|
||||
@(require_results)
|
||||
DistanceSquared :: proc "c" (a, b: Vec2) -> f32 {
|
||||
c := Vec2{b.x - a.x, b.y - a.y}
|
||||
return c.x * c.x + c.y * c.y
|
||||
}
|
||||
|
||||
// Make a rotation using an angle in radians
|
||||
@(require_results)
|
||||
MakeRot :: proc "c" (angle: f32) -> Rot {
|
||||
cs := ComputeCosSin(angle)
|
||||
return Rot{c=cs.cosine, s=cs.sine}
|
||||
}
|
||||
|
||||
// Compute the rotation between two unit vectors
|
||||
@(require_results)
|
||||
ComputeRotationBetweenUnitVectors :: proc(v1, v2: Vec2) -> Rot {
|
||||
return NormalizeRot({
|
||||
c = Dot(v1, v2),
|
||||
s = Cross(v1, v2),
|
||||
})
|
||||
}
|
||||
|
||||
// Is this rotation normalized?
|
||||
@(require_results)
|
||||
IsNormalizedRot :: proc "c" (q: Rot) -> bool {
|
||||
// larger tolerance due to failure on mingw 32-bit
|
||||
qq := q.s * q.s + q.c * q.c
|
||||
return 1.0 - 0.0006 < qq && qq < 1 + 0.0006
|
||||
}
|
||||
|
||||
// Normalize rotation
|
||||
@(require_results)
|
||||
NormalizeRot :: proc "c" (q: Rot) -> Rot {
|
||||
mag := math.sqrt(q.s * q.s + q.c * q.c)
|
||||
invMag := f32(mag > 0.0 ? 1.0 / mag : 0.0)
|
||||
return {q.c * invMag, q.s * invMag}
|
||||
}
|
||||
|
||||
// Normalized linear interpolation
|
||||
// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
|
||||
// https://web.archive.org/web/20170825184056/http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
|
||||
@(require_results)
|
||||
NLerp :: proc "c" (q1: Rot, q2: Rot, t: f32) -> Rot {
|
||||
omt := 1 - t
|
||||
return NormalizeRot({
|
||||
omt * q1.c + t * q2.c,
|
||||
omt * q1.s + t * q2.s,
|
||||
})
|
||||
}
|
||||
|
||||
// Compute the angular velocity necessary to rotate between two rotations over a give time
|
||||
// @param q1 initial rotation
|
||||
// @param q2 final rotation
|
||||
@@ -291,8 +366,7 @@ ComputeAngularVelocity :: proc "c" (q1: Rot, q2: Rot, inv_h: f32) -> f32 {
|
||||
// Get the angle in radians in the range [-pi, pi]
|
||||
@(require_results)
|
||||
Rot_GetAngle :: proc "c" (q: Rot) -> f32 {
|
||||
// todo determinism
|
||||
return math.atan2(q.s, q.c)
|
||||
return Atan2(q.s, q.c)
|
||||
}
|
||||
|
||||
// Get the x-axis
|
||||
@@ -338,18 +412,34 @@ RelativeAngle :: proc "c" (b, a: Rot) -> f32 {
|
||||
// cos(b - a) = bc * ac + bs * as
|
||||
s := b.s * a.c - b.c * a.s
|
||||
c := b.c * a.c + b.s * a.s
|
||||
return math.atan2(s, c)
|
||||
return Atan2(s, c)
|
||||
}
|
||||
|
||||
// Convert an angle in the range [-2*pi, 2*pi] into the range [-pi, pi]
|
||||
@(require_results)
|
||||
UnwindAngle :: proc "c" (angle: f32) -> f32 {
|
||||
if angle < -pi {
|
||||
return angle + 2.0 * pi
|
||||
} else if angle > pi {
|
||||
return angle - 2.0 * pi
|
||||
UnwindAngle :: proc "c" (radians: f32) -> f32 {
|
||||
if radians < -PI {
|
||||
return radians + 2.0 * PI
|
||||
} else if radians > PI {
|
||||
return radians - 2.0 * PI
|
||||
}
|
||||
return angle
|
||||
return radians
|
||||
}
|
||||
|
||||
// Convert any into the range [-pi, pi] (slow)
|
||||
@(require_results)
|
||||
UnwindLargeAngle :: proc "c" (radians: f32) -> f32 {
|
||||
radians := radians
|
||||
|
||||
for radians > PI {
|
||||
radians -= 2. * PI
|
||||
}
|
||||
|
||||
for radians < -PI {
|
||||
radians += 2. * PI
|
||||
}
|
||||
|
||||
return radians
|
||||
}
|
||||
|
||||
// Rotate a vector
|
||||
@@ -380,6 +470,9 @@ InvTransformPoint :: proc "c" (t: Transform, p: Vec2) -> Vec2 {
|
||||
return {t.q.c * vx + t.q.s * vy, -t.q.s * vx + t.q.c * vy}
|
||||
}
|
||||
|
||||
// Multiply two transforms. If the result is applied to a point p local to frame B,
|
||||
// the transform would first convert p to a point local to frame A, then into 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
|
||||
@(require_results)
|
||||
@@ -389,6 +482,7 @@ MulTransforms :: proc "c" (A, B: Transform) -> (C: Transform) {
|
||||
return
|
||||
}
|
||||
|
||||
// Creates a transform that converts a local point in frame B to a local point in frame A.
|
||||
// v2 = A.q' * (B.q * v1 + B.p - A.p)
|
||||
// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
|
||||
@(require_results)
|
||||
@@ -469,54 +563,65 @@ AABB_Union :: proc "c" (a, b: AABB) -> (c: AABB) {
|
||||
return
|
||||
}
|
||||
|
||||
// Compute the bounding box of an array of circles
|
||||
@(require_results)
|
||||
Float_IsValid :: proc "c" (a: f32) -> bool {
|
||||
math.is_nan(a) or_return
|
||||
math.is_inf(a) or_return
|
||||
MakeAABB :: proc "c" (points: []Vec2, radius: f32) -> AABB {
|
||||
a := AABB{points[0], points[0]}
|
||||
for point in points {
|
||||
a.lowerBound = Min(a.lowerBound, point)
|
||||
a.upperBound = Max(a.upperBound, point)
|
||||
}
|
||||
|
||||
r := Vec2{radius, radius}
|
||||
a.lowerBound = a.lowerBound - r
|
||||
a.upperBound = a.upperBound + r
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// Signed separation of a point from a plane
|
||||
@(require_results)
|
||||
PlaneSeparation :: proc "c" (plane: Plane, point: Vec2) -> f32 {
|
||||
return Dot(plane.normal, point) - plane.offset
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
IsValidFloat :: proc "c" (a: f32) -> bool {
|
||||
#partial switch math.classify(a) {
|
||||
case .NaN, .Inf, .Neg_Inf: return false
|
||||
case: return true
|
||||
}
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
IsValidVec2 :: proc "c" (v: Vec2) -> bool {
|
||||
IsValidFloat(v.x) or_return
|
||||
IsValidFloat(v.y) or_return
|
||||
return true
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
Vec2_IsValid :: proc "c" (v: Vec2) -> bool {
|
||||
(math.is_nan(v.x) || math.is_nan(v.y)) or_return
|
||||
(math.is_inf(v.x) || math.is_inf(v.y)) or_return
|
||||
IsValidRotation :: proc "c" (q: Rot) -> bool {
|
||||
IsValidFloat(q.s) or_return
|
||||
IsValidFloat(q.c) or_return
|
||||
return IsNormalizedRot(q)
|
||||
}
|
||||
|
||||
// Is this a valid bounding box? Not Nan or infinity. Upper bound greater than or equal to lower bound.
|
||||
@(require_results)
|
||||
IsValidAABB :: proc "c" (aabb: AABB) -> bool {
|
||||
IsValidVec2(aabb.lowerBound) or_return
|
||||
IsValidVec2(aabb.upperBound) or_return
|
||||
(aabb.upperBound.x >= aabb.lowerBound.x) or_return
|
||||
(aabb.upperBound.y >= aabb.lowerBound.y) or_return
|
||||
return true
|
||||
}
|
||||
|
||||
// Is this a valid plane? Normal is a unit vector. Not Nan or infinity.
|
||||
@(require_results)
|
||||
Rot_IsValid :: proc "c" (q: Rot) -> bool {
|
||||
(math.is_nan(q.s) || math.is_nan(q.c)) or_return
|
||||
(math.is_inf(q.s) || math.is_inf(q.c)) or_return
|
||||
return IsNormalized(q)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
Normalize :: proc "c" (v: Vec2) -> Vec2 {
|
||||
length := Length(v)
|
||||
if length < 1e-23 {
|
||||
return Vec2_zero
|
||||
}
|
||||
invLength := 1 / length
|
||||
return invLength * v
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
NormalizeChecked :: proc "odin" (v: Vec2) -> Vec2 {
|
||||
length := Length(v)
|
||||
if length < 1e-23 {
|
||||
panic("zero-length Vec2")
|
||||
}
|
||||
invLength := 1 / length
|
||||
return invLength * v
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
GetLengthAndNormalize :: proc "c" (v: Vec2) -> (length: f32, vn: Vec2) {
|
||||
length = Length(v)
|
||||
if length < 1e-23 {
|
||||
return
|
||||
}
|
||||
invLength := 1 / length
|
||||
vn = invLength * v
|
||||
return
|
||||
IsValidPlane :: proc "c" (plane: Plane) -> bool {
|
||||
IsValidFloat(plane.offset) or_return
|
||||
IsValidVec2(plane.normal) or_return
|
||||
IsNormalized(plane.normal) or_return
|
||||
return true
|
||||
}
|
||||
|
||||
581
vendor/box2d/types.odin
vendored
581
vendor/box2d/types.odin
vendored
@@ -37,14 +37,28 @@ EnqueueTaskCallback :: #type proc "c" (task: TaskCallback, itemCount: i32, minRa
|
||||
// @ingroup world
|
||||
FinishTaskCallback :: #type proc "c" (userTask: rawptr, userContext: rawptr)
|
||||
|
||||
// Optional friction mixing callback. This intentionally provides no context objects because this is called
|
||||
// from a worker thread.
|
||||
// @warning This function should not attempt to modify Box2D state or user application state.
|
||||
// @ingroup world
|
||||
FrictionCallback :: #type proc "c" (frictionA: f32, userMaterialIdA: i32, frictionB: f32, userMaterialIdB: i32)
|
||||
|
||||
// Optional restitution mixing callback. This intentionally provides no context objects because this is called
|
||||
// from a worker thread.
|
||||
// @warning This function should not attempt to modify Box2D state or user application state.
|
||||
// @ingroup world
|
||||
RestitutionCallback :: #type proc "c" (restitutionA: f32, userMaterialIdA: i32, restitutuionB: f32, userMaterialIdB: i32)
|
||||
|
||||
// Result from b2World_RayCastClosest
|
||||
// @ingroup world
|
||||
RayResult :: struct {
|
||||
shapeId: ShapeId,
|
||||
point: Vec2,
|
||||
normal: Vec2,
|
||||
fraction: f32,
|
||||
hit: bool,
|
||||
shapeId: ShapeId,
|
||||
point: Vec2,
|
||||
normal: Vec2,
|
||||
fraction: f32,
|
||||
nodeVisits: i32,
|
||||
leafVisits: i32,
|
||||
hit: bool,
|
||||
}
|
||||
|
||||
// World definition used to create a simulation world.
|
||||
@@ -54,37 +68,53 @@ WorldDef :: struct {
|
||||
// Gravity vector. Box2D has no up-vector defined.
|
||||
gravity: Vec2,
|
||||
|
||||
// Restitution velocity threshold, usually in m/s. Collisions above this
|
||||
// Restitution speed threshold, usually in m/s. Collisions above this
|
||||
// speed have restitution applied (will bounce).
|
||||
restitutionThreshold: f32,
|
||||
|
||||
// This parameter controls how fast overlap is resolved and has units of meters per second
|
||||
contactPushoutVelocity: f32,
|
||||
|
||||
// Threshold velocity for hit events. Usually meters per second.
|
||||
// Threshold speed for hit events. Usually meters per second.
|
||||
hitEventThreshold: f32,
|
||||
|
||||
// Contact stiffness. Cycles per second.
|
||||
// Contact stiffness. Cycles per second. Increasing this increases the speed of overlap recovery, but can introduce jitter.
|
||||
contactHertz: f32,
|
||||
|
||||
// Contact bounciness. Non-dimensional.
|
||||
// Contact bounciness. Non-dimensional. You can speed up overlap recovery by decreasing this with
|
||||
// the trade-off that overlap resolution becomes more energetic.
|
||||
contactDampingRatio: f32,
|
||||
|
||||
// This parameter controls how fast overlap is resolved and usually has units of meters per second. This only
|
||||
// puts a cap on the resolution speed. The resolution speed is increased by increasing the hertz and/or
|
||||
// decreasing the damping ratio.
|
||||
maxContactPushSpeed: f32,
|
||||
|
||||
// Joint stiffness. Cycles per second.
|
||||
jointHertz: f32,
|
||||
|
||||
// Joint bounciness. Non-dimensional.
|
||||
jointDampingRatio: f32,
|
||||
|
||||
// Maximum linear speed. Usually meters per second.
|
||||
maximumLinearSpeed: f32,
|
||||
|
||||
// Optional mixing callback for friction. The default uses sqrt(frictionA * frictionB).
|
||||
frictionCallback: FrictionCallback,
|
||||
|
||||
// Optional mixing callback for restitution. The default uses max(restitutionA, restitutionB).
|
||||
restitutionCallback: RestitutionCallback,
|
||||
|
||||
// Can bodies go to sleep to improve performance
|
||||
enableSleep: bool,
|
||||
|
||||
// Enable continuous collision
|
||||
enableContinous: bool,
|
||||
enableContinuous: bool,
|
||||
|
||||
// Number of workers to use with the provided task system. Box2D performs best when using only
|
||||
// performance cores and accessing a single L2 cache. Efficiency cores and hyper-threading provide
|
||||
// little benefit and may even harm performance.
|
||||
// performance cores and accessing a single L2 cache. Efficiency cores and hyper-threading provide
|
||||
// little benefit and may even harm performance.
|
||||
// @note Box2D does not create threads. This is the number of threads your applications has created
|
||||
// that you are allocating to b2World_Step.
|
||||
// @warning Do not modify the default value unless you are also providing a task system and providing
|
||||
// task callbacks (enqueueTask and finishTask).
|
||||
workerCount: i32,
|
||||
|
||||
// Function to spawn tasks
|
||||
@@ -96,6 +126,9 @@ WorldDef :: struct {
|
||||
// User context that is provided to enqueueTask and finishTask
|
||||
userTaskContext: rawptr,
|
||||
|
||||
// User data
|
||||
userData: rawptr,
|
||||
|
||||
// Used internally to detect a valid definition. DO NOT SET.
|
||||
internalValue: i32,
|
||||
}
|
||||
@@ -138,20 +171,20 @@ BodyDef :: struct {
|
||||
// The initial world rotation of the body. Use b2MakeRot() if you have an angle.
|
||||
rotation: Rot,
|
||||
|
||||
// The initial linear velocity of the body's origin. Typically in meters per second.
|
||||
// The initial linear velocity of the body's origin. Usually in meters per second.
|
||||
linearVelocity: Vec2,
|
||||
|
||||
// The initial angular velocity of the body. Radians per second.
|
||||
angularVelocity: f32,
|
||||
|
||||
// Linear damping is use to reduce the linear velocity. The damping parameter
|
||||
// Linear damping is used to reduce the linear velocity. The damping parameter
|
||||
// can be larger than 1 but the damping effect becomes sensitive to the
|
||||
// time step when the damping parameter is large.
|
||||
// Generally linear damping is undesirable because it makes objects move slowly
|
||||
// as if they are f32ing.
|
||||
linearDamping: f32,
|
||||
|
||||
// Angular damping is use to reduce the angular velocity. The damping parameter
|
||||
// Angular damping is used to reduce the angular velocity. The damping parameter
|
||||
// can be larger than 1.0f but the damping effect becomes sensitive to the
|
||||
// time step when the damping parameter is large.
|
||||
// Angular damping can be use slow down rotating bodies.
|
||||
@@ -160,9 +193,12 @@ BodyDef :: struct {
|
||||
// Scale the gravity applied to this body. Non-dimensional.
|
||||
gravityScale: f32,
|
||||
|
||||
// Sleep velocity threshold, default is 0.05 meter per second
|
||||
// Sleep speed threshold, default is 0.05 meters per second
|
||||
sleepThreshold: f32,
|
||||
|
||||
// Optional body name for debugging. Up to 32 characters (excluding null termination)
|
||||
name: cstring,
|
||||
|
||||
// Use this to store application specific body data.
|
||||
userData: rawptr,
|
||||
|
||||
@@ -184,10 +220,6 @@ BodyDef :: struct {
|
||||
// Used to disable a body. A disabled body does not move or collide.
|
||||
isEnabled: bool,
|
||||
|
||||
// Automatically compute mass and related properties on this body from shapes.
|
||||
// Triggers whenever a shape is add/removed/changed. Default is true.
|
||||
automaticMass: bool,
|
||||
|
||||
// This allows this body to bypass rotational speed limits. Should only be used
|
||||
// for circular objects, like wheels.
|
||||
allowFastRotation: bool,
|
||||
@@ -204,7 +236,7 @@ Filter :: struct {
|
||||
// The collision category bits. Normally you would just set one bit. The category bits should
|
||||
// represent your application object types. For example:
|
||||
// @code{.odin}
|
||||
// My_Categories :: enum u32 {
|
||||
// My_Categories :: enum u64 {
|
||||
// Static = 0x00000001,
|
||||
// Dynamic = 0x00000002,
|
||||
// Debris = 0x00000004,
|
||||
@@ -213,16 +245,16 @@ Filter :: struct {
|
||||
// };
|
||||
// @endcode
|
||||
// Or use a bit_set.
|
||||
categoryBits: u32,
|
||||
categoryBits: u64,
|
||||
|
||||
// The collision mask bits. This states the categories that this
|
||||
// shape would accept for collision.
|
||||
// For example, you may want your player to only collide with static objects
|
||||
// and other players.
|
||||
// @code{.odin}
|
||||
// maskBits = u32(My_Categories.Static | My_Categories.Player);
|
||||
// maskBits = u64(My_Categories.Static | My_Categories.Player);
|
||||
// @endcode
|
||||
maskBits: u32,
|
||||
maskBits: u64,
|
||||
|
||||
// Collision groups allow a certain group of objects to never collide (negative)
|
||||
// or always collide (positive). A group index of zero has no effect. Non-zero group filtering
|
||||
@@ -240,11 +272,11 @@ Filter :: struct {
|
||||
// @ingroup shape
|
||||
QueryFilter :: struct {
|
||||
// The collision category bits of this query. Normally you would just set one bit.
|
||||
categoryBits: u32,
|
||||
categoryBits: u64,
|
||||
|
||||
// The collision mask bits. This states the shape categories that this
|
||||
// query would accept for collision.
|
||||
maskBits: u32,
|
||||
maskBits: u64,
|
||||
}
|
||||
|
||||
|
||||
@@ -263,13 +295,37 @@ ShapeType :: enum c.int {
|
||||
// A convex polygon
|
||||
polygonShape,
|
||||
|
||||
// A smooth segment owned by a chain shape
|
||||
smoothSegmentShape,
|
||||
// A line segment owned by a chain shape
|
||||
chainSegmentShape,
|
||||
}
|
||||
|
||||
// The number of shape types
|
||||
shapeTypeCount :: len(ShapeType)
|
||||
|
||||
// Surface materials allow chain shapes to have per segment surface properties.
|
||||
// @ingroup shape
|
||||
SurfaceMaterial :: struct {
|
||||
// The Coulomb (dry) friction coefficient, usually in the range [0,1].
|
||||
friction: f32,
|
||||
|
||||
// The coefficient of restitution (bounce) usually in the range [0,1].
|
||||
// https://en.wikipedia.org/wiki/Coefficient_of_restitution
|
||||
restitution: f32,
|
||||
|
||||
// The rolling resistance usually in the range [0,1].
|
||||
rollingResistance: f32,
|
||||
|
||||
// The tangent speed for conveyor belts
|
||||
tangentSpeed: f32,
|
||||
|
||||
// User material identifier. This is passed with query results and to friction and restitution
|
||||
// combining functions. It is not used internally.
|
||||
userMaterialId: i32,
|
||||
|
||||
// Custom debug draw color.
|
||||
customColor: u32,
|
||||
}
|
||||
|
||||
// Used to create a shape.
|
||||
// This is a temporary object used to bundle shape creation parameters. You may use
|
||||
// the same shape definition to create multiple shapes.
|
||||
@@ -279,58 +335,61 @@ ShapeDef :: struct {
|
||||
// Use this to store application specific shape data.
|
||||
userData: rawptr,
|
||||
|
||||
// The Coulomb (dry) friction coefficient, usually in the range [0,1].
|
||||
friction: f32,
|
||||
|
||||
// The restitution (bounce) usually in the range [0,1].
|
||||
restitution: f32,
|
||||
// The surface material for this shape.
|
||||
material: SurfaceMaterial,
|
||||
|
||||
// The density, usually in kg/m^2.
|
||||
// This is not part of the surface material because this is for the interior, which may have
|
||||
// other considerations, such as being hollow. For example a wood barrel may be hollow or full of water.
|
||||
density: f32,
|
||||
|
||||
// Collision filtering data.
|
||||
filter: Filter,
|
||||
|
||||
// Custom debug draw color.
|
||||
customColor: u32,
|
||||
|
||||
// A sensor shape generates overlap events but never generates a collision response.
|
||||
// Sensors do not have continuous collision. Instead, use a ray or shape cast for those scenarios.
|
||||
// Sensors still contribute to the body mass if they have non-zero density.
|
||||
// @note Sensor events are disabled by default.
|
||||
// @see enableSensorEvents
|
||||
isSensor: bool,
|
||||
|
||||
// Enable sensor events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors.
|
||||
// Enable sensor events for this shape. This applies to sensors and non-sensors. False by default, even for sensors.
|
||||
enableSensorEvents: bool,
|
||||
|
||||
// Enable contact events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors.
|
||||
// Enable contact events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. False by default.
|
||||
enableContactEvents: bool,
|
||||
|
||||
// Enable hit events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors.
|
||||
// Enable hit events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. False by default.
|
||||
enableHitEvents: bool,
|
||||
|
||||
// Enable pre-solve contact events for this shape. Only applies to dynamic bodies. These are expensive
|
||||
// and must be carefully handled due to threading. Ignored for sensors.
|
||||
enablePreSolveEvents: bool,
|
||||
|
||||
// Normally shapes on static bodies don't invoke contact creation when they are added to the world. This overrides
|
||||
// that behavior and causes contact creation. This significantly slows down static body creation which can be important
|
||||
// when there are many static shapes.
|
||||
forceContactCreation: bool,
|
||||
// When shapes are created they will scan the environment for collision the next time step. This can significantly slow down
|
||||
// static body creation when there are many static shapes.
|
||||
// This is flag is ignored for dynamic and kinematic shapes which always invoke contact creation.
|
||||
invokeContactCreation: bool,
|
||||
|
||||
// Should the body update the mass properties when this shape is created. Default is true.
|
||||
updateBodyMass: bool,
|
||||
|
||||
// Used internally to detect a valid definition. DO NOT SET.
|
||||
internalValue: i32,
|
||||
}
|
||||
|
||||
|
||||
// Used to create a chain of edges. This is designed to eliminate ghost collisions with some limitations.
|
||||
// Used to create a chain of line segments. This is designed to eliminate ghost collisions with some limitations.
|
||||
// - chains are one-sided
|
||||
// - chains have no mass and should be used on static bodies
|
||||
// - chains have a counter-clockwise winding order
|
||||
// - chains have a counter-clockwise winding order (normal points right of segment direction)
|
||||
// - chains are either a loop or open
|
||||
// - a chain must have at least 4 points
|
||||
// - the distance between any two points must be greater than b2_linearSlop
|
||||
// - the distance between any two points must be greater than B2_LINEAR_SLOP
|
||||
// - a chain shape should not self intersect (this is not validated)
|
||||
// - an open chain shape has NO COLLISION on the first and final edge
|
||||
// - you may overlap two open chains on their first three and/or last three points to get smooth collision
|
||||
// - a chain shape creates multiple smooth edges shapes on the body
|
||||
// - a chain shape creates multiple line segment shapes on the body
|
||||
// https://en.wikipedia.org/wiki/Polygonal_chain
|
||||
// Must be initialized using b2DefaultChainDef().
|
||||
// @warning Do not use chain shapes unless you understand the limitations. This is an advanced feature.
|
||||
@@ -345,11 +404,12 @@ ChainDef :: struct {
|
||||
// The point count, must be 4 or more.
|
||||
count: i32,
|
||||
|
||||
// The friction coefficient, usually in the range [0,1].
|
||||
friction: f32,
|
||||
// Surface materials for each segment. These are cloned.
|
||||
materials: [^]SurfaceMaterial `fmt:"v,materialCount"`,
|
||||
|
||||
// The restitution (elasticity) usually in the range [0,1].
|
||||
restitution: f32,
|
||||
// The material count. Must be 1 or count. This allows you to provide one
|
||||
// material for all segments or a unique material per segment.
|
||||
materialCount: i32,
|
||||
|
||||
// Contact filtering data.
|
||||
filter: Filter,
|
||||
@@ -357,6 +417,9 @@ ChainDef :: struct {
|
||||
// Indicates a closed chain formed by connecting the first and last points
|
||||
isLoop: bool,
|
||||
|
||||
// Enable sensors to detect this chain. False by default.
|
||||
enableSensorEvents: bool,
|
||||
|
||||
// Used internally to detect a valid definition. DO NOT SET.
|
||||
internalValue: i32,
|
||||
}
|
||||
@@ -369,29 +432,28 @@ Profile :: struct {
|
||||
pairs: f32,
|
||||
collide: f32,
|
||||
solve: f32,
|
||||
buildIslands: f32,
|
||||
mergeIslands: f32,
|
||||
prepareStages: f32,
|
||||
solveConstraints: f32,
|
||||
prepareTasks: f32,
|
||||
solverTasks: f32,
|
||||
prepareConstraints: f32,
|
||||
integrateVelocities: f32,
|
||||
warmStart: f32,
|
||||
solveVelocities: f32,
|
||||
solveImpulses: f32,
|
||||
integratePositions: f32,
|
||||
relaxVelocities: f32,
|
||||
relaxImpulses: f32,
|
||||
applyRestitution: f32,
|
||||
storeImpulses: f32,
|
||||
finalizeBodies: f32,
|
||||
splitIslands: f32,
|
||||
sleepIslands: f32,
|
||||
transforms: f32,
|
||||
hitEvents: f32,
|
||||
broadphase: f32,
|
||||
continuous: f32,
|
||||
refit: f32,
|
||||
bullets: f32,
|
||||
sleepIslands: f32,
|
||||
sensors: f32,
|
||||
}
|
||||
|
||||
// Counters that give details of the simulation size.
|
||||
Counters :: struct {
|
||||
staticBodyCount: i32,
|
||||
bodyCount: i32,
|
||||
shapeCount: i32,
|
||||
contactCount: i32,
|
||||
@@ -413,6 +475,7 @@ Counters :: struct {
|
||||
// @ingroup joint
|
||||
JointType :: enum c.int {
|
||||
distanceJoint,
|
||||
filterJoint,
|
||||
motorJoint,
|
||||
mouseJoint,
|
||||
prismaticJoint,
|
||||
@@ -526,7 +589,7 @@ MotorJointDef :: struct {
|
||||
// applying huge forces. This also applies rotation constraint heuristic to improve control.
|
||||
// @ingroup mouse_joint
|
||||
MouseJointDef :: struct {
|
||||
// The first attached body.
|
||||
// The first attached body. This is assumed to be static.
|
||||
bodyIdA: BodyId,
|
||||
|
||||
// The second attached body.
|
||||
@@ -554,6 +617,22 @@ MouseJointDef :: struct {
|
||||
internalValue: i32,
|
||||
}
|
||||
|
||||
// A filter joint is used to disable collision between two specific bodies.
|
||||
//
|
||||
// @ingroup filter_joint
|
||||
FilterJointDef :: struct {
|
||||
/// The first attached body.
|
||||
bodyIdA: BodyId,
|
||||
|
||||
/// The second attached body.
|
||||
bodyIdB: BodyId,
|
||||
|
||||
/// User data pointer
|
||||
userData: rawptr,
|
||||
|
||||
/// Used internally to detect a valid definition. DO NOT SET.
|
||||
internalValue: i32,
|
||||
}
|
||||
|
||||
// Prismatic joint definition
|
||||
//
|
||||
@@ -660,10 +739,10 @@ RevoluteJointDef :: struct {
|
||||
// A flag to enable joint limits
|
||||
enableLimit: bool,
|
||||
|
||||
// The lower angle for the joint limit in radians
|
||||
// The lower angle for the joint limit in radians. Minimum of -0.95*pi radians.
|
||||
lowerAngle: f32,
|
||||
|
||||
// The upper angle for the joint limit in radians
|
||||
// The upper angle for the joint limit in radians. Maximum of 0.95*pi radians.
|
||||
upperAngle: f32,
|
||||
|
||||
// A flag to enable the joint motor
|
||||
@@ -794,6 +873,27 @@ WheelJointDef :: struct {
|
||||
internalValue: i32,
|
||||
}
|
||||
|
||||
// The explosion definition is used to configure options for explosions. Explosions
|
||||
// consider shape geometry when computing the impulse.
|
||||
// @ingroup world
|
||||
ExplosionDef :: struct {
|
||||
/// Mask bits to filter shapes
|
||||
maskBits: u64,
|
||||
|
||||
/// The center of the explosion in world space
|
||||
position: Vec2,
|
||||
|
||||
/// The radius of the explosion
|
||||
radius: f32,
|
||||
|
||||
/// The falloff distance beyond the radius. Impulse is reduced to zero at this distance.
|
||||
falloff: f32,
|
||||
|
||||
/// Impulse per unit length. This applies an impulse according to the shape perimeter that
|
||||
/// is facing the explosion. Explosions only apply to circles, capsules, and polygons. This
|
||||
/// may be negative for implosions.
|
||||
impulsePerLength: f32,
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup events Events
|
||||
@@ -822,11 +922,18 @@ SensorBeginTouchEvent :: struct {
|
||||
}
|
||||
|
||||
// An end touch event is generated when a shape stops overlapping a sensor shape.
|
||||
// These include things like setting the transform, destroying a body or shape, or changing
|
||||
// a filter. You will also get an end event if the sensor or visitor are destroyed.
|
||||
// Therefore you should always confirm the shape id is valid using b2Shape_IsValid.
|
||||
SensorEndTouchEvent :: struct {
|
||||
// The id of the sensor shape
|
||||
// @warning this shape may have been destroyed
|
||||
// @see b2Shape_IsValid
|
||||
sensorShapeId: ShapeId,
|
||||
|
||||
// The id of the dynamic shape that stopped touching the sensor shape
|
||||
// @warning this shape may have been destroyed
|
||||
// @see b2Shape_IsValid
|
||||
visitorShapeId: ShapeId,
|
||||
}
|
||||
|
||||
@@ -854,14 +961,25 @@ ContactBeginTouchEvent :: struct {
|
||||
|
||||
// Id of the second shape
|
||||
shapeIdB: ShapeId,
|
||||
|
||||
// The initial contact manifold. This is recorded before the solver is called,
|
||||
// so all the impulses will be zero.
|
||||
manifold: Manifold,
|
||||
}
|
||||
|
||||
// An end touch event is generated when two shapes stop touching.
|
||||
// You will get an end event if you do anything that destroys contacts previous to the last
|
||||
// world step. These include things like setting the transform, destroying a body
|
||||
// or shape, or changing a filter or body type.
|
||||
ContactEndTouchEvent :: struct {
|
||||
// Id of the first shape
|
||||
// @warning this shape may have been destroyed
|
||||
// @see b2Shape_IsValid
|
||||
shapeIdA: ShapeId,
|
||||
|
||||
// Id of the second shape
|
||||
// @warning this shape may have been destroyed
|
||||
// @see b2Shape_IsValid
|
||||
shapeIdB: ShapeId,
|
||||
}
|
||||
|
||||
@@ -998,201 +1116,191 @@ OverlapResultFcn :: #type proc "c" (shapeId: ShapeId, ctx: rawptr) -> bool
|
||||
// @ingroup world
|
||||
CastResultFcn :: #type proc "c" (shapeId: ShapeId, point: Vec2, normal: Vec2, fraction: f32, ctx: rawptr) -> f32
|
||||
|
||||
// These colors are used for debug draw.
|
||||
// See https://www.rapidtables.com/web/color/index.html
|
||||
// Used to collect collision planes for character movers.
|
||||
// Return true to continue gathering planes.
|
||||
PlaneResultFcn :: #type proc "c" (shapeId: ShapeId, plane: ^PlaneResult, ctx: rawptr)
|
||||
|
||||
// These colors are used for debug draw and mostly match the named SVG colors.
|
||||
// See https://www.rapidtables.com/web/color/index.html
|
||||
// https://johndecember.com/html/spec/colorsvg.html
|
||||
// https://upload.wikimedia.org/wikipedia/commons/2/2b/SVG_Recognized_color_keyword_names.svg
|
||||
HexColor :: enum c.int {
|
||||
AliceBlue = 0xf0f8ff,
|
||||
AntiqueWhite = 0xfaebd7,
|
||||
Aqua = 0x00ffff,
|
||||
Aquamarine = 0x7fffd4,
|
||||
Azure = 0xf0ffff,
|
||||
Beige = 0xf5f5dc,
|
||||
Bisque = 0xffe4c4,
|
||||
AliceBlue = 0xF0F8FF,
|
||||
AntiqueWhite = 0xFAEBD7,
|
||||
Aqua = 0x00FFFF,
|
||||
Aquamarine = 0x7FFFD4,
|
||||
Azure = 0xF0FFFF,
|
||||
Beige = 0xF5F5DC,
|
||||
Bisque = 0xFFE4C4,
|
||||
Black = 0x000000,
|
||||
BlanchedAlmond = 0xffebcd,
|
||||
Blue = 0x0000ff,
|
||||
BlueViolet = 0x8a2be2,
|
||||
Brown = 0xa52a2a,
|
||||
Burlywood = 0xdeb887,
|
||||
CadetBlue = 0x5f9ea0,
|
||||
Chartreuse = 0x7fff00,
|
||||
Chocolate = 0xd2691e,
|
||||
Coral = 0xff7f50,
|
||||
CornflowerBlue = 0x6495ed,
|
||||
Cornsilk = 0xfff8dc,
|
||||
Crimson = 0xdc143c,
|
||||
Cyan = 0x00ffff,
|
||||
DarkBlue = 0x00008b,
|
||||
DarkCyan = 0x008b8b,
|
||||
DarkGoldenrod = 0xb8860b,
|
||||
DarkGray = 0xa9a9a9,
|
||||
BlanchedAlmond = 0xFFEBCD,
|
||||
Blue = 0x0000FF,
|
||||
BlueViolet = 0x8A2BE2,
|
||||
Brown = 0xA52A2A,
|
||||
Burlywood = 0xDEB887,
|
||||
CadetBlue = 0x5F9EA0,
|
||||
Chartreuse = 0x7FFF00,
|
||||
Chocolate = 0xD2691E,
|
||||
Coral = 0xFF7F50,
|
||||
CornflowerBlue = 0x6495ED,
|
||||
Cornsilk = 0xFFF8DC,
|
||||
Crimson = 0xDC143C,
|
||||
Cyan = 0x00FFFF,
|
||||
DarkBlue = 0x00008B,
|
||||
DarkCyan = 0x008B8B,
|
||||
DarkGoldenRod = 0xB8860B,
|
||||
DarkGray = 0xA9A9A9,
|
||||
DarkGreen = 0x006400,
|
||||
DarkKhaki = 0xbdb76b,
|
||||
DarkMagenta = 0x8b008b,
|
||||
DarkOliveGreen = 0x556b2f,
|
||||
DarkOrange = 0xff8c00,
|
||||
DarkOrchid = 0x9932cc,
|
||||
DarkRed = 0x8b0000,
|
||||
DarkSalmon = 0xe9967a,
|
||||
DarkSeaGreen = 0x8fbc8f,
|
||||
DarkSlateBlue = 0x483d8b,
|
||||
DarkSlateGray = 0x2f4f4f,
|
||||
DarkTurquoise = 0x00ced1,
|
||||
DarkViolet = 0x9400d3,
|
||||
DeepPink = 0xff1493,
|
||||
DeepSkyBlue = 0x00bfff,
|
||||
DarkKhaki = 0xBDB76B,
|
||||
DarkMagenta = 0x8B008B,
|
||||
DarkOliveGreen = 0x556B2F,
|
||||
DarkOrange = 0xFF8C00,
|
||||
DarkOrchid = 0x9932CC,
|
||||
DarkRed = 0x8B0000,
|
||||
DarkSalmon = 0xE9967A,
|
||||
DarkSeaGreen = 0x8FBC8F,
|
||||
DarkSlateBlue = 0x483D8B,
|
||||
DarkSlateGray = 0x2F4F4F,
|
||||
DarkTurquoise = 0x00CED1,
|
||||
DarkViolet = 0x9400D3,
|
||||
DeepPink = 0xFF1493,
|
||||
DeepSkyBlue = 0x00BFFF,
|
||||
DimGray = 0x696969,
|
||||
DodgerBlue = 0x1e90ff,
|
||||
Firebrick = 0xb22222,
|
||||
FloralWhite = 0xfffaf0,
|
||||
ForestGreen = 0x228b22,
|
||||
Fuchsia = 0xff00ff,
|
||||
Gainsboro = 0xdcdcdc,
|
||||
GhostWhite = 0xf8f8ff,
|
||||
Gold = 0xffd700,
|
||||
Goldenrod = 0xdaa520,
|
||||
Gray = 0xbebebe,
|
||||
Gray1 = 0x1a1a1a,
|
||||
Gray2 = 0x333333,
|
||||
Gray3 = 0x4d4d4d,
|
||||
Gray4 = 0x666666,
|
||||
Gray5 = 0x7f7f7f,
|
||||
Gray6 = 0x999999,
|
||||
Gray7 = 0xb3b3b3,
|
||||
Gray8 = 0xcccccc,
|
||||
Gray9 = 0xe5e5e5,
|
||||
Green = 0x00ff00,
|
||||
GreenYellow = 0xadff2f,
|
||||
Honeydew = 0xf0fff0,
|
||||
HotPink = 0xff69b4,
|
||||
IndianRed = 0xcd5c5c,
|
||||
Indigo = 0x4b0082,
|
||||
Ivory = 0xfffff0,
|
||||
Khaki = 0xf0e68c,
|
||||
Lavender = 0xe6e6fa,
|
||||
LavenderBlush = 0xfff0f5,
|
||||
LawnGreen = 0x7cfc00,
|
||||
LemonChiffon = 0xfffacd,
|
||||
LightBlue = 0xadd8e6,
|
||||
LightCoral = 0xf08080,
|
||||
LightCyan = 0xe0ffff,
|
||||
LightGoldenrod = 0xeedd82,
|
||||
LightGoldenrodYellow = 0xfafad2,
|
||||
LightGray = 0xd3d3d3,
|
||||
LightGreen = 0x90ee90,
|
||||
LightPink = 0xffb6c1,
|
||||
LightSalmon = 0xffa07a,
|
||||
LightSeaGreen = 0x20b2aa,
|
||||
LightSkyBlue = 0x87cefa,
|
||||
LightSlateBlue = 0x8470ff,
|
||||
DodgerBlue = 0x1E90FF,
|
||||
FireBrick = 0xB22222,
|
||||
FloralWhite = 0xFFFAF0,
|
||||
ForestGreen = 0x228B22,
|
||||
Fuchsia = 0xFF00FF,
|
||||
Gainsboro = 0xDCDCDC,
|
||||
GhostWhite = 0xF8F8FF,
|
||||
Gold = 0xFFD700,
|
||||
GoldenRod = 0xDAA520,
|
||||
Gray = 0x808080,
|
||||
Green = 0x008000,
|
||||
GreenYellow = 0xADFF2F,
|
||||
HoneyDew = 0xF0FFF0,
|
||||
HotPink = 0xFF69B4,
|
||||
IndianRed = 0xCD5C5C,
|
||||
Indigo = 0x4B0082,
|
||||
Ivory = 0xFFFFF0,
|
||||
Khaki = 0xF0E68C,
|
||||
Lavender = 0xE6E6FA,
|
||||
LavenderBlush = 0xFFF0F5,
|
||||
LawnGreen = 0x7CFC00,
|
||||
LemonChiffon = 0xFFFACD,
|
||||
LightBlue = 0xADD8E6,
|
||||
LightCoral = 0xF08080,
|
||||
LightCyan = 0xE0FFFF,
|
||||
LightGoldenRodYellow = 0xFAFAD2,
|
||||
LightGray = 0xD3D3D3,
|
||||
LightGreen = 0x90EE90,
|
||||
LightPink = 0xFFB6C1,
|
||||
LightSalmon = 0xFFA07A,
|
||||
LightSeaGreen = 0x20B2AA,
|
||||
LightSkyBlue = 0x87CEFA,
|
||||
LightSlateGray = 0x778899,
|
||||
LightSteelBlue = 0xb0c4de,
|
||||
LightYellow = 0xffffe0,
|
||||
Lime = 0x00ff00,
|
||||
LimeGreen = 0x32cd32,
|
||||
Linen = 0xfaf0e6,
|
||||
Magenta = 0xff00ff,
|
||||
Maroon = 0xb03060,
|
||||
MediumAquamarine = 0x66cdaa,
|
||||
MediumBlue = 0x0000cd,
|
||||
MediumOrchid = 0xba55d3,
|
||||
MediumPurple = 0x9370db,
|
||||
MediumSeaGreen = 0x3cb371,
|
||||
MediumSlateBlue = 0x7b68ee,
|
||||
MediumSpringGreen = 0x00fa9a,
|
||||
MediumTurquoise = 0x48d1cc,
|
||||
MediumVioletRed = 0xc71585,
|
||||
LightSteelBlue = 0xB0C4DE,
|
||||
LightYellow = 0xFFFFE0,
|
||||
Lime = 0x00FF00,
|
||||
LimeGreen = 0x32CD32,
|
||||
Linen = 0xFAF0E6,
|
||||
Magenta = 0xFF00FF,
|
||||
Maroon = 0x800000,
|
||||
MediumAquaMarine = 0x66CDAA,
|
||||
MediumBlue = 0x0000CD,
|
||||
MediumOrchid = 0xBA55D3,
|
||||
MediumPurple = 0x9370DB,
|
||||
MediumSeaGreen = 0x3CB371,
|
||||
MediumSlateBlue = 0x7B68EE,
|
||||
MediumSpringGreen = 0x00FA9A,
|
||||
MediumTurquoise = 0x48D1CC,
|
||||
MediumVioletRed = 0xC71585,
|
||||
MidnightBlue = 0x191970,
|
||||
MintCream = 0xf5fffa,
|
||||
MistyRose = 0xffe4e1,
|
||||
Moccasin = 0xffe4b5,
|
||||
NavajoWhite = 0xffdead,
|
||||
MintCream = 0xF5FFFA,
|
||||
MistyRose = 0xFFE4E1,
|
||||
Moccasin = 0xFFE4B5,
|
||||
NavajoWhite = 0xFFDEAD,
|
||||
Navy = 0x000080,
|
||||
NavyBlue = 0x000080,
|
||||
OldLace = 0xfdf5e6,
|
||||
OldLace = 0xFDF5E6,
|
||||
Olive = 0x808000,
|
||||
OliveDrab = 0x6b8e23,
|
||||
Orange = 0xffa500,
|
||||
OrangeRed = 0xff4500,
|
||||
Orchid = 0xda70d6,
|
||||
PaleGoldenrod = 0xeee8aa,
|
||||
PaleGreen = 0x98fb98,
|
||||
PaleTurquoise = 0xafeeee,
|
||||
PaleVioletRed = 0xdb7093,
|
||||
PapayaWhip = 0xffefd5,
|
||||
PeachPuff = 0xffdab9,
|
||||
Peru = 0xcd853f,
|
||||
Pink = 0xffc0cb,
|
||||
Plum = 0xdda0dd,
|
||||
PowderBlue = 0xb0e0e6,
|
||||
Purple = 0xa020f0,
|
||||
OliveDrab = 0x6B8E23,
|
||||
Orange = 0xFFA500,
|
||||
OrangeRed = 0xFF4500,
|
||||
Orchid = 0xDA70D6,
|
||||
PaleGoldenRod = 0xEEE8AA,
|
||||
PaleGreen = 0x98FB98,
|
||||
PaleTurquoise = 0xAFEEEE,
|
||||
PaleVioletRed = 0xDB7093,
|
||||
PapayaWhip = 0xFFEFD5,
|
||||
PeachPuff = 0xFFDAB9,
|
||||
Peru = 0xCD853F,
|
||||
Pink = 0xFFC0CB,
|
||||
Plum = 0xDDA0DD,
|
||||
PowderBlue = 0xB0E0E6,
|
||||
Purple = 0x800080,
|
||||
RebeccaPurple = 0x663399,
|
||||
Red = 0xff0000,
|
||||
RosyBrown = 0xbc8f8f,
|
||||
RoyalBlue = 0x4169e1,
|
||||
SaddleBrown = 0x8b4513,
|
||||
Salmon = 0xfa8072,
|
||||
SandyBrown = 0xf4a460,
|
||||
SeaGreen = 0x2e8b57,
|
||||
Seashell = 0xfff5ee,
|
||||
Sienna = 0xa0522d,
|
||||
Silver = 0xc0c0c0,
|
||||
SkyBlue = 0x87ceeb,
|
||||
SlateBlue = 0x6a5acd,
|
||||
Red = 0xFF0000,
|
||||
RosyBrown = 0xBC8F8F,
|
||||
RoyalBlue = 0x4169E1,
|
||||
SaddleBrown = 0x8B4513,
|
||||
Salmon = 0xFA8072,
|
||||
SandyBrown = 0xF4A460,
|
||||
SeaGreen = 0x2E8B57,
|
||||
SeaShell = 0xFFF5EE,
|
||||
Sienna = 0xA0522D,
|
||||
Silver = 0xC0C0C0,
|
||||
SkyBlue = 0x87CEEB,
|
||||
SlateBlue = 0x6A5ACD,
|
||||
SlateGray = 0x708090,
|
||||
Snow = 0xfffafa,
|
||||
SpringGreen = 0x00ff7f,
|
||||
SteelBlue = 0x4682b4,
|
||||
Tan = 0xd2b48c,
|
||||
Snow = 0xFFFAFA,
|
||||
SpringGreen = 0x00FF7F,
|
||||
SteelBlue = 0x4682B4,
|
||||
Tan = 0xD2B48C,
|
||||
Teal = 0x008080,
|
||||
Thistle = 0xd8bfd8,
|
||||
Tomato = 0xff6347,
|
||||
Turquoise = 0x40e0d0,
|
||||
Violet = 0xee82ee,
|
||||
VioletRed = 0xd02090,
|
||||
Wheat = 0xf5deb3,
|
||||
White = 0xffffff,
|
||||
WhiteSmoke = 0xf5f5f5,
|
||||
Yellow = 0xffff00,
|
||||
YellowGreen = 0x9acd32,
|
||||
Box2DRed = 0xdc3132,
|
||||
Box2DBlue = 0x30aebf,
|
||||
Box2DGreen = 0x8cc924,
|
||||
Box2DYellow = 0xffee8c,
|
||||
Thistle = 0xD8BFD8,
|
||||
Tomato = 0xFF6347,
|
||||
Turquoise = 0x40E0D0,
|
||||
Violet = 0xEE82EE,
|
||||
Wheat = 0xF5DEB3,
|
||||
White = 0xFFFFFF,
|
||||
WhiteSmoke = 0xF5F5F5,
|
||||
Yellow = 0xFFFF00,
|
||||
YellowGreen = 0x9ACD32,
|
||||
Box2DRed = 0xDC3132,
|
||||
Box2DBlue = 0x30AEBF,
|
||||
Box2DGreen = 0x8CC924,
|
||||
Box2DYellow = 0xFFEE8C,
|
||||
}
|
||||
|
||||
// This struct holds callbacks you can implement to draw a Box2D world.
|
||||
// @ingroup world
|
||||
DebugDraw :: struct {
|
||||
// Draw a closed polygon provided in CCW order.
|
||||
DrawPolygon: proc "c" (vertices: [^]Vec2, vertexCount: c.int, color: HexColor, ctx: rawptr),
|
||||
DrawPolygonFcn: proc "c" (vertices: [^]Vec2, vertexCount: c.int, color: HexColor, ctx: rawptr),
|
||||
|
||||
// Draw a solid closed polygon provided in CCW order.
|
||||
DrawSolidPolygon: proc "c" (transform: Transform, vertices: [^]Vec2, vertexCount: c.int, radius: f32, colr: HexColor, ctx: rawptr ),
|
||||
DrawSolidPolygonFcn: proc "c" (transform: Transform, vertices: [^]Vec2, vertexCount: c.int, radius: f32, colr: HexColor, ctx: rawptr ),
|
||||
|
||||
// Draw a circle.
|
||||
DrawCircle: proc "c" (center: Vec2, radius: f32, color: HexColor, ctx: rawptr),
|
||||
DrawCircleFcn: proc "c" (center: Vec2, radius: f32, color: HexColor, ctx: rawptr),
|
||||
|
||||
// Draw a solid circle.
|
||||
DrawSolidCircle: proc "c" (transform: Transform, radius: f32, color: HexColor, ctx: rawptr),
|
||||
|
||||
// Draw a capsule.
|
||||
DrawCapsule: proc "c" (p1, p2: Vec2, radius: f32, color: HexColor, ctx: rawptr),
|
||||
DrawSolidCircleFcn: proc "c" (transform: Transform, radius: f32, color: HexColor, ctx: rawptr),
|
||||
|
||||
// Draw a solid capsule.
|
||||
DrawSolidCapsule: proc "c" (p1, p2: Vec2, radius: f32, color: HexColor, ctx: rawptr),
|
||||
DrawSolidCapsuleFcn: proc "c" (p1, p2: Vec2, radius: f32, color: HexColor, ctx: rawptr),
|
||||
|
||||
// Draw a line segment.
|
||||
DrawSegment: proc "c" (p1, p2: Vec2, color: HexColor, ctx: rawptr),
|
||||
DrawSegmentFcn: proc "c" (p1, p2: Vec2, color: HexColor, ctx: rawptr),
|
||||
|
||||
// Draw a transform. Choose your own length scale.
|
||||
DrawTransform: proc "c" (transform: Transform, ctx: rawptr),
|
||||
DrawTransformFcn: proc "c" (transform: Transform, ctx: rawptr),
|
||||
|
||||
// Draw a point.
|
||||
DrawPoint: proc "c" (p: Vec2, size: f32, color: HexColor, ctx: rawptr),
|
||||
DrawPointFcn: proc "c" (p: Vec2, size: f32, color: HexColor, ctx: rawptr),
|
||||
|
||||
// Draw a string.
|
||||
DrawString: proc "c" (p: Vec2, s: cstring, ctx: rawptr),
|
||||
// Draw a string in world space.
|
||||
DrawStringFcn: proc "c" (p: Vec2, s: cstring, color: HexColor, ctx: rawptr),
|
||||
|
||||
// Bounds to use if restricting drawing to a rectangular region
|
||||
drawingBounds: AABB,
|
||||
@@ -1210,11 +1318,14 @@ DebugDraw :: struct {
|
||||
drawJointExtras: bool,
|
||||
|
||||
// Option to draw the bounding boxes for shapes
|
||||
drawAABBs: bool,
|
||||
drawBounds: bool,
|
||||
|
||||
// Option to draw the mass and center of mass of dynamic bodies
|
||||
drawMass: bool,
|
||||
|
||||
// Option to draw body names
|
||||
drawBodyNames: bool,
|
||||
|
||||
// Option to draw contact points
|
||||
drawContacts: bool,
|
||||
|
||||
@@ -1227,9 +1338,15 @@ DebugDraw :: struct {
|
||||
// Option to draw contact normal impulses
|
||||
drawContactImpulses: bool,
|
||||
|
||||
// Option to draw contact feature ids
|
||||
drawContactFeatures: bool,
|
||||
|
||||
// Option to draw contact friction impulses
|
||||
drawFrictionImpulses: bool,
|
||||
|
||||
// Option to draw islands as bounding boxes
|
||||
drawIslands: bool,
|
||||
|
||||
// User context that is passed as an argument to drawing callback functions
|
||||
userContext: rawptr,
|
||||
}
|
||||
}
|
||||
|
||||
8
vendor/box2d/wasm.Makefile
vendored
8
vendor/box2d/wasm.Makefile
vendored
@@ -7,20 +7,20 @@
|
||||
# CC = $(shell brew --prefix llvm)/bin/clang
|
||||
# LD = $(shell brew --prefix llvm)/bin/wasm-ld
|
||||
|
||||
VERSION = 3.0.0
|
||||
VERSION = 3.1.0
|
||||
SRCS = $(wildcard box2d-$(VERSION)/src/*.c)
|
||||
OBJS_SIMD = $(SRCS:.c=_simd.o)
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
SYSROOT = $(shell odin root)/vendor/libc
|
||||
CFLAGS = -Ibox2d-$(VERSION)/include -Ibox2d-$(VERSION)/extern/simde --target=wasm32 -D__EMSCRIPTEN__ -DNDEBUG -O3 --sysroot=$(SYSROOT)
|
||||
CFLAGS = -Ibox2d-$(VERSION)/include --target=wasm32 -D__EMSCRIPTEN__ -DNDEBUG -O3 --sysroot=$(SYSROOT)
|
||||
|
||||
all: lib/box2d_wasm.o lib/box2d_wasm_simd.o clean
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
$(CC) -c $(CFLAGS) -DBOX2D_DISABLE_SIMD $< -o $@
|
||||
|
||||
%_simd.o: %.c
|
||||
$(CC) -c $(CFLAGS) -msimd128 $< -o $@
|
||||
$(CC) -c $(CFLAGS) -DBOX2D_DISABLE_SIMD -msimd128 $< -o $@
|
||||
|
||||
lib/box2d_wasm.o: $(OBJS)
|
||||
$(LD) -r -o lib/box2d_wasm.o $(OBJS)
|
||||
|
||||
6
vendor/libc/include/math.h
vendored
6
vendor/libc/include/math.h
vendored
@@ -47,19 +47,19 @@ bool __isnanf(float);
|
||||
bool __isnand(double);
|
||||
#define isnan(x) \
|
||||
( sizeof(x) == sizeof(float) ? __isnanf((float)(x)) \
|
||||
: : __isnand((double)(x)))
|
||||
: __isnand((double)(x)))
|
||||
|
||||
bool __isinff(float);
|
||||
bool __isinfd(double);
|
||||
#define isinf(x) \
|
||||
( sizeof(x) == sizeof(float) ? __isinff((float)(x)) \
|
||||
: : __isinfd((double)(x)))
|
||||
: __isinfd((double)(x)))
|
||||
|
||||
bool __isfinitef(float);
|
||||
bool __isfinited(double);
|
||||
#define isfinite(x) \
|
||||
( sizeof(x) == sizeof(float) ? __isfinitef((float)(x)) \
|
||||
: : __isfinited((double)(x)))
|
||||
: __isfinited((double)(x)))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
23
vendor/libc/include/sched.h
vendored
Normal file
23
vendor/libc/include/sched.h
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define CLOCK_MONOTONIC 1
|
||||
|
||||
struct timespec
|
||||
{
|
||||
int64_t tv_sec;
|
||||
int64_t tv_nsec;
|
||||
};
|
||||
|
||||
int clock_gettime(int clockid, struct timespec *tp);
|
||||
|
||||
int sched_yield();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
35
vendor/libc/sched.odin
vendored
Normal file
35
vendor/libc/sched.odin
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package odin_libc
|
||||
|
||||
import "core:time"
|
||||
import "core:thread"
|
||||
|
||||
Clock :: enum i32 {
|
||||
Monotonic = 1,
|
||||
}
|
||||
|
||||
Time_Spec :: struct {
|
||||
tv_sec: i64,
|
||||
tv_nsec: i64,
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="clock_gettime")
|
||||
clock_gettine :: proc "c" (clockid: Clock, tp: ^Time_Spec) -> i32 {
|
||||
switch clockid {
|
||||
case .Monotonic:
|
||||
tick := time.tick_now()
|
||||
tp.tv_sec = tick._nsec/1e9
|
||||
tp.tv_nsec = tick._nsec%1e9/1000
|
||||
return 0
|
||||
|
||||
case: return -1
|
||||
}
|
||||
}
|
||||
|
||||
@(require, linkage="strong", link_name="sched_yield")
|
||||
sched_yield :: proc "c" () -> i32 {
|
||||
when thread.IS_SUPPORTED {
|
||||
context = g_ctx
|
||||
thread.yield()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user