mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-14 18:02:22 -07:00
Merge pull request #5069 from laytan/box2d-3.1.0
box2d: update to 3.1.0
This commit is contained in:
Vendored
+416
-211
File diff suppressed because it is too large
Load Diff
Vendored
+3
-3
@@ -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"
|
||||
|
||||
Vendored
+143
-126
@@ -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,
|
||||
}
|
||||
|
||||
Vendored
+22
-21
@@ -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
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+211
-106
@@ -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
|
||||
}
|
||||
|
||||
Vendored
+349
-232
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+4
-4
@@ -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)
|
||||
|
||||
Vendored
+3
-3
@@ -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
|
||||
}
|
||||
|
||||
Vendored
+23
@@ -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
|
||||
Vendored
+35
@@ -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