mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
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
|
#!/usr/bin/env bash
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
VERSION="3.0.0"
|
VERSION="3.1.0"
|
||||||
RELEASE="https://github.com/erincatto/box2d/archive/refs/tags/v$VERSION.tar.gz"
|
RELEASE="https://github.com/erincatto/box2d/archive/refs/tags/v$VERSION.tar.gz"
|
||||||
|
|
||||||
cd "$(odin root)"/vendor/box2d
|
cd "$(odin root)"/vendor/box2d
|
||||||
@@ -75,5 +75,5 @@ if [[ $? -ne 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
rm -rf v3.0.0.tar.gz
|
rm -rf "v$VERSION.tar.gz"
|
||||||
rm -rf box2d-3.0.0
|
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
|
// The maximum number of vertices on a convex polygon. Changing this affects performance even if you
|
||||||
// don't use more vertices.
|
// 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 {
|
RayCastInput :: struct {
|
||||||
// Start point of the ray cast
|
// Start point of the ray cast
|
||||||
origin: Vec2,
|
origin: Vec2,
|
||||||
@@ -19,27 +19,37 @@ RayCastInput :: struct {
|
|||||||
maxFraction: f32,
|
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
|
// 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.
|
// 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.
|
// A capsule is two points with a non-zero radius. A box is four points with a zero radius.
|
||||||
ShapeCastInput :: struct {
|
ShapeCastInput :: struct {
|
||||||
// A point cloud to cast
|
// A generic shape
|
||||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
proxy: ShapeProxy,
|
||||||
|
|
||||||
// The number of points
|
|
||||||
count: i32,
|
|
||||||
|
|
||||||
// The radius around the point cloud
|
|
||||||
radius: f32,
|
|
||||||
|
|
||||||
// The translation of the shape cast
|
// The translation of the shape cast
|
||||||
translation: Vec2,
|
translation: Vec2,
|
||||||
|
|
||||||
// The maximum fraction of the translation to consider, typically 1
|
// The maximum fraction of the translation to consider, typically 1
|
||||||
maxFraction: f32,
|
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 {
|
CastOutput :: struct {
|
||||||
// The surface normal at the hit point
|
// The surface normal at the hit point
|
||||||
normal: Vec2,
|
normal: Vec2,
|
||||||
@@ -51,7 +61,7 @@ CastOutput :: struct {
|
|||||||
fraction: f32,
|
fraction: f32,
|
||||||
|
|
||||||
// The number of iterations used
|
// The number of iterations used
|
||||||
iterations: i32,
|
iterations: c.int,
|
||||||
|
|
||||||
// Did the cast hit?
|
// Did the cast hit?
|
||||||
hit: bool,
|
hit: bool,
|
||||||
@@ -93,16 +103,16 @@ Capsule :: struct {
|
|||||||
|
|
||||||
// A solid convex polygon. It is assumed that the interior of the polygon is to
|
// A solid convex polygon. It is assumed that the interior of the polygon is to
|
||||||
// the left of each edge.
|
// 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.
|
// 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
|
// @warning DO NOT fill this out manually, instead use a helper function like
|
||||||
// b2MakePolygon or b2MakeBox.
|
// b2MakePolygon or b2MakeBox.
|
||||||
Polygon :: struct {
|
Polygon :: struct {
|
||||||
// The polygon vertices
|
// 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
|
// 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
|
// The centroid of the polygon
|
||||||
centroid: Vec2,
|
centroid: Vec2,
|
||||||
@@ -111,7 +121,7 @@ Polygon :: struct {
|
|||||||
radius: f32,
|
radius: f32,
|
||||||
|
|
||||||
// The number of polygon vertices
|
// The number of polygon vertices
|
||||||
count: i32,
|
count: c.int,
|
||||||
}
|
}
|
||||||
|
|
||||||
// A line segment with two-sided collision.
|
// A line segment with two-sided collision.
|
||||||
@@ -123,10 +133,10 @@ Segment :: struct {
|
|||||||
point2: Vec2,
|
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.
|
// Several of these are generated for a chain shape.
|
||||||
// ghost1 -> point1 -> point2 -> ghost2
|
// ghost1 -> point1 -> point2 -> ghost2
|
||||||
SmoothSegment :: struct {
|
ChainSegment :: struct {
|
||||||
// The tail ghost vertex
|
// The tail ghost vertex
|
||||||
ghost1: Vec2,
|
ghost1: Vec2,
|
||||||
|
|
||||||
@@ -137,7 +147,7 @@ SmoothSegment :: struct {
|
|||||||
ghost2: Vec2,
|
ghost2: Vec2,
|
||||||
|
|
||||||
// The owning chain shape index (internal usage only)
|
// 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()
|
// @warning Do not modify these values directly, instead use b2ComputeHull()
|
||||||
Hull :: struct {
|
Hull :: struct {
|
||||||
// The final points of the hull
|
// The final points of the hull
|
||||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
points: [MAX_POLYGON_VERTICES]Vec2 `fmt:"v,count"`,
|
||||||
|
|
||||||
// The number of points
|
// The number of points
|
||||||
count: i32,
|
count: c.int,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,21 +188,11 @@ SegmentDistanceResult :: struct {
|
|||||||
distanceSquared: f32,
|
distanceSquared: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// A distance proxy is used by the GJK algorithm. It encapsulates any shape.
|
// Used to warm start the GJK simplex. If you call this function multiple times with nearby
|
||||||
DistanceProxy :: struct {
|
// transforms this might improve performance. Otherwise you can zero initialize this.
|
||||||
// The point cloud
|
// The distance cache must be initialized to zero on the first call.
|
||||||
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
|
// Users should generally just zero initialize this structure for each call.
|
||||||
|
SimplexCache :: struct {
|
||||||
// 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 {
|
|
||||||
// The number of stored simplex points
|
// The number of stored simplex points
|
||||||
count: u16,
|
count: u16,
|
||||||
|
|
||||||
@@ -203,15 +203,15 @@ DistanceCache :: struct {
|
|||||||
indexB: [3]u8 `fmt:"v,count"`,
|
indexB: [3]u8 `fmt:"v,count"`,
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyDistanceCache :: DistanceCache{}
|
emptySimplexCache :: SimplexCache{}
|
||||||
|
|
||||||
// Input for b2ShapeDistance
|
// Input for b2ShapeDistance
|
||||||
DistanceInput :: struct {
|
DistanceInput :: struct {
|
||||||
// The proxy for shape A
|
// The proxy for shape A
|
||||||
proxyA: DistanceProxy,
|
proxyA: ShapeProxy,
|
||||||
|
|
||||||
// The proxy for shape B
|
// The proxy for shape B
|
||||||
proxyB: DistanceProxy,
|
proxyB: ShapeProxy,
|
||||||
|
|
||||||
// The world transform for shape A
|
// The world transform for shape A
|
||||||
transformA: Transform,
|
transformA: Transform,
|
||||||
@@ -227,6 +227,7 @@ DistanceInput :: struct {
|
|||||||
DistanceOutput :: struct {
|
DistanceOutput :: struct {
|
||||||
pointA: Vec2, // Closest point on shapeA
|
pointA: Vec2, // Closest point on shapeA
|
||||||
pointB: Vec2, // Closest point on shapeB
|
pointB: Vec2, // Closest point on shapeB
|
||||||
|
normal: Vec2, // Normal vector that points from A to B
|
||||||
distance: f32, // The final distance, zero if overlapped
|
distance: f32, // The final distance, zero if overlapped
|
||||||
iterations: i32, // Number of GJK iterations used
|
iterations: i32, // Number of GJK iterations used
|
||||||
simplexCount: i32, // The number of simplexes stored in the simplex array
|
simplexCount: i32, // The number of simplexes stored in the simplex array
|
||||||
@@ -234,28 +235,29 @@ DistanceOutput :: struct {
|
|||||||
|
|
||||||
// Simplex vertex for debugging the GJK algorithm
|
// Simplex vertex for debugging the GJK algorithm
|
||||||
SimplexVertex :: struct {
|
SimplexVertex :: struct {
|
||||||
wA: Vec2, // support point in proxyA
|
wA: Vec2, // support point in proxyA
|
||||||
wB: Vec2, // support point in proxyB
|
wB: Vec2, // support point in proxyB
|
||||||
w: Vec2, // wB - wA
|
w: Vec2, // wB - wA
|
||||||
a: f32, // barycentric coordinate for closest point
|
a: f32, // barycentric coordinate for closest point
|
||||||
indexA: i32, // wA index
|
indexA: c.int, // wA index
|
||||||
indexB: i32, // wB index
|
indexB: c.int, // wB index
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simplex from the GJK algorithm
|
// Simplex from the GJK algorithm
|
||||||
Simplex :: struct {
|
Simplex :: struct {
|
||||||
v1, v2, v3: SimplexVertex `fmt:"v,count"`, // vertices
|
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
|
// Input parameters for b2ShapeCast
|
||||||
ShapeCastPairInput :: struct {
|
ShapeCastPairInput :: struct {
|
||||||
proxyA: DistanceProxy, // The proxy for shape A
|
proxyA: ShapeProxy, // The proxy for shape A
|
||||||
proxyB: DistanceProxy, // The proxy for shape B
|
proxyB: ShapeProxy, // The proxy for shape B
|
||||||
transformA: Transform, // The world transform for shape A
|
transformA: Transform, // The world transform for shape A
|
||||||
transformB: Transform, // The world transform for shape B
|
transformB: Transform, // The world transform for shape B
|
||||||
translationB: Vec2, // The translation of shape B
|
translationB: Vec2, // The translation of shape B
|
||||||
maxFraction: f32, // The fraction of the translation to consider, typically 1
|
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
|
// Input parameters for b2TimeOfImpact
|
||||||
TOIInput :: struct {
|
TOIInput :: struct {
|
||||||
proxyA: DistanceProxy, // The proxy for shape A
|
proxyA: ShapeProxy, // The proxy for shape A
|
||||||
proxyB: DistanceProxy, // The proxy for shape B
|
proxyB: ShapeProxy, // The proxy for shape B
|
||||||
sweepA: Sweep, // The movement of shape A
|
sweepA: Sweep, // The movement of shape A
|
||||||
sweepB: Sweep, // The movement of shape B
|
sweepB: Sweep, // The movement of shape B
|
||||||
tMax: f32, // Defines the sweep interval [0, tMax]
|
maxFraction: f32, // Defines the sweep interval [0, maxFraction]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describes the TOI output
|
// Describes the TOI output
|
||||||
@@ -290,8 +292,8 @@ TOIState :: enum c.int {
|
|||||||
|
|
||||||
// Output parameters for b2TimeOfImpact.
|
// Output parameters for b2TimeOfImpact.
|
||||||
TOIOutput :: struct {
|
TOIOutput :: struct {
|
||||||
state: TOIState, // The type of result
|
state: TOIState, // The type of result
|
||||||
t: f32, // The time of the collision
|
fraction: f32, // The sweep time of the collision
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -301,26 +303,30 @@ TOIOutput :: struct {
|
|||||||
* @brief Functions for colliding pairs of shapes
|
* @brief Functions for colliding pairs of shapes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// A manifold point is a contact point belonging to a contact
|
// A manifold point is a contact point belonging to a contact manifold.
|
||||||
// manifold. It holds details related to the geometry and dynamics
|
// It holds details related to the geometry and dynamics of the contact points.
|
||||||
// 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 {
|
ManifoldPoint :: struct {
|
||||||
// Location of the contact point in world space. Subject to precision loss at large coordinates.
|
// Location of the contact point in world space. Subject to precision loss at large coordinates.
|
||||||
// @note Should only be used for debugging.
|
// @note Should only be used for debugging.
|
||||||
point: Vec2,
|
point: Vec2,
|
||||||
|
|
||||||
// Location of the contact point relative to bodyA's origin in world space
|
// Location of the contact point relative to shapeA's origin in world space
|
||||||
// @note When used internally to the Box2D solver, these are relative to the center of mass.
|
// @note When used internally to the Box2D solver, this is relative to the body center of mass.
|
||||||
anchorA: Vec2,
|
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,
|
anchorB: Vec2,
|
||||||
|
|
||||||
// The separation of the contact point, negative if penetrating
|
// The separation of the contact point, negative if penetrating
|
||||||
separation: f32,
|
separation: f32,
|
||||||
|
|
||||||
// The impulse along the manifold normal vector.
|
// The total normal impulse applied across sub-stepping and restitution. This is important
|
||||||
normalImpulse: f32,
|
// to identify speculative contact points that had an interaction in the time step.
|
||||||
|
totalNormalImpulse: f32,
|
||||||
|
|
||||||
// The friction impulse
|
// The friction impulse
|
||||||
tangentImpulse: f32,
|
tangentImpulse: f32,
|
||||||
@@ -340,16 +346,21 @@ ManifoldPoint :: struct {
|
|||||||
persisted: bool,
|
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 {
|
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
|
// 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
|
// 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 AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
|
||||||
* A dynamic tree arranges data in a binary tree to accelerate
|
* A dynamic tree arranges data in a binary tree to accelerate
|
||||||
* queries such as AABB queries and ray casts. Leaf nodes are proxies
|
* 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.
|
* 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
|
* The dynamic tree is made available for advanced users that would like to use it to organize
|
||||||
* spatial game data besides rigid bodies.
|
* 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.
|
// The dynamic tree structure. This should be considered private data.
|
||||||
// It is placed here for performance reasons.
|
// It is placed here for performance reasons.
|
||||||
DynamicTree :: struct {
|
DynamicTree :: struct {
|
||||||
// The tree nodes
|
// The tree nodes
|
||||||
nodes: [^]TreeNode `fmt"v,nodeCount"`,
|
nodes: rawptr,
|
||||||
|
|
||||||
// The root index
|
// The root index
|
||||||
root: i32,
|
root: i32,
|
||||||
@@ -453,16 +418,25 @@ DynamicTree :: struct {
|
|||||||
rebuildCapacity: i32,
|
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.
|
// This function receives proxies found in the AABB query.
|
||||||
// @return true if the query should continue
|
// @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.
|
// 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 less than input->maxFraction to clip the ray
|
||||||
// - return a value of input->maxFraction to continue the ray cast without clipping
|
// - 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
|
// 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 of 0 to terminate the ray cast
|
||||||
// - return a value less than input->maxFraction to clip the ray
|
// - return a value less than input->maxFraction to clip the ray
|
||||||
// - return a value of input->maxFraction to continue the ray cast without clipping
|
// - 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.
|
/// World id references a world instance. This should be treated as an opaque handle.
|
||||||
WorldId :: struct {
|
WorldId :: struct {
|
||||||
index1: u16,
|
index1: u16,
|
||||||
revision: u16,
|
generation: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Body id references a body instance. This should be treated as an opaque handle.
|
/// Body id references a body instance. This should be treated as an opaque handle.
|
||||||
BodyId :: struct {
|
BodyId :: struct {
|
||||||
index1: i32,
|
index1: i32,
|
||||||
world0: u16,
|
world0: u16,
|
||||||
revision: u16,
|
generation: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shape id references a shape instance. This should be treated as an opaque handle.
|
/// Shape id references a shape instance. This should be treated as an opaque handle.
|
||||||
ShapeId :: struct {
|
ShapeId :: struct {
|
||||||
index1: i32,
|
index1: i32,
|
||||||
world0: u16,
|
world0: u16,
|
||||||
revision: u16,
|
generation: u16,
|
||||||
}
|
|
||||||
|
|
||||||
/// Joint id references a joint instance. This should be treated as an opaque handle.
|
|
||||||
JointId :: struct {
|
|
||||||
index1: i32,
|
|
||||||
world0: u16,
|
|
||||||
revision: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Chain id references a chain instances. This should be treated as an opaque handle.
|
/// Chain id references a chain instances. This should be treated as an opaque handle.
|
||||||
ChainId :: struct {
|
ChainId :: struct {
|
||||||
index1: i32,
|
index1: i32,
|
||||||
world0: u16,
|
world0: u16,
|
||||||
revision: 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.
|
/// Use these to make your identifiers null.
|
||||||
/// You may also use zero initialization to get null.
|
/// You may also use zero initialization to get null.
|
||||||
nullWorldId :: WorldId{}
|
nullWorldId :: WorldId{}
|
||||||
nullBodyId :: BodyId{}
|
nullBodyId :: BodyId{}
|
||||||
nullShapeId :: ShapeId{}
|
nullShapeId :: ShapeId{}
|
||||||
nullJointId :: JointId{}
|
|
||||||
nullChainId :: ChainId{}
|
nullChainId :: ChainId{}
|
||||||
|
nullJointId :: JointId{}
|
||||||
|
|
||||||
/// Macro to determine if any id is null.
|
/// Macro to determine if any id is null.
|
||||||
IS_NULL :: #force_inline proc "c" (id: $T) -> bool
|
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),
|
where intrinsics.type_is_struct(T),
|
||||||
intrinsics.type_has_field(T, "index1"),
|
intrinsics.type_has_field(T, "index1"),
|
||||||
intrinsics.type_has_field(T, "world0"),
|
intrinsics.type_has_field(T, "world0"),
|
||||||
intrinsics.type_has_field(T, "revision") {
|
intrinsics.type_has_field(T, "generation") {
|
||||||
return id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.revision == id2.revision
|
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.
Vendored
+211
-106
@@ -3,9 +3,18 @@ package vendor_box2d
|
|||||||
import "core:c"
|
import "core:c"
|
||||||
import "core:math"
|
import "core:math"
|
||||||
|
|
||||||
pi :: 3.14159265359
|
EPSILON :: 1e-23
|
||||||
|
|
||||||
Vec2 :: [2]f32
|
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 {
|
Rot :: struct {
|
||||||
c, s: f32, // cosine and sine
|
c, s: f32, // cosine and sine
|
||||||
}
|
}
|
||||||
@@ -21,11 +30,43 @@ AABB :: struct {
|
|||||||
upperBound: Vec2,
|
upperBound: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// separation = dot(normal, point) - offset
|
||||||
|
Plane :: struct {
|
||||||
|
normal: Vec2,
|
||||||
|
offset: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
PI :: math.PI
|
||||||
|
|
||||||
Vec2_zero :: Vec2{0, 0}
|
Vec2_zero :: Vec2{0, 0}
|
||||||
Rot_identity :: Rot{1, 0}
|
Rot_identity :: Rot{1, 0}
|
||||||
Transform_identity :: Transform{{0, 0}, {1, 0}}
|
Transform_identity :: Transform{{0, 0}, {1, 0}}
|
||||||
Mat22_zero :: Mat22{0, 0, 0, 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
|
// @return the minimum of two floats
|
||||||
@(deprecated="Prefer the built-in 'min(a, b)'", require_results)
|
@(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 clamp(a, lower, upper)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @return the minimum of two integers
|
@(require_results)
|
||||||
@(deprecated="Prefer the built-in 'min(a, b)'", require_results)
|
Atan2 :: proc "c" (y, x: f32) -> f32 {
|
||||||
MinInt :: proc "c" (a, b: c.int) -> c.int {
|
return math.atan2(y, x)
|
||||||
return min(a, b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @return the maximum of two integers
|
@(require_results)
|
||||||
@(deprecated="Prefer the built-in 'max(a, b)'", require_results)
|
ComputeCosSin :: proc "c" (radians: f32) -> (res: CosSin) {
|
||||||
MaxInt :: proc "c" (a, b: c.int) -> c.int {
|
res.sine, res.cosine = math.sincos(radians)
|
||||||
return max(a, b)
|
return
|
||||||
}
|
|
||||||
|
|
||||||
// @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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vector dot product
|
// Vector dot product
|
||||||
@@ -198,12 +226,6 @@ Length :: proc "c" (v: Vec2) -> f32 {
|
|||||||
return math.sqrt(v.x * v.x + v.y * v.y)
|
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
|
// Get the distance between two points
|
||||||
@(require_results)
|
@(require_results)
|
||||||
Distance :: proc "c" (a, b: Vec2) -> f32 {
|
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)
|
return math.sqrt(dx * dx + dy * dy)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the distance squared between points
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
DistanceSquared :: proc "c" (a, b: Vec2) -> f32 {
|
Normalize :: proc "c" (v: Vec2) -> Vec2 {
|
||||||
c := Vec2{b.x - a.x, b.y - a.y}
|
length := Length(v)
|
||||||
return c.x * c.x + c.y * c.y
|
if length < EPSILON {
|
||||||
|
return Vec2_zero
|
||||||
|
}
|
||||||
|
invLength := 1 / length
|
||||||
|
return invLength * v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a rotation using an angle in radians
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
MakeRot :: proc "c" (angle: f32) -> Rot {
|
IsNormalized :: proc "c" (v: Vec2) -> bool {
|
||||||
// todo determinism
|
aa := Dot(v, v)
|
||||||
return {math.cos(angle), math.sin(angle)}
|
return abs(1. - aa) < 10. * EPSILON
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize rotation
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
NormalizeRot :: proc "c" (q: Rot) -> Rot {
|
NormalizeChecked :: proc "odin" (v: Vec2) -> Vec2 {
|
||||||
mag := math.sqrt(q.s * q.s + q.c * q.c)
|
length := Length(v)
|
||||||
invMag := f32(mag > 0.0 ? 1.0 / mag : 0.0)
|
if length < 1e-23 {
|
||||||
return {q.c * invMag, q.s * invMag}
|
panic("zero-length Vec2")
|
||||||
|
}
|
||||||
|
invLength := 1 / length
|
||||||
|
return invLength * v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this rotation normalized?
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
IsNormalized :: proc "c" (q: Rot) -> bool {
|
GetLengthAndNormalize :: proc "c" (v: Vec2) -> (length: f32, vn: Vec2) {
|
||||||
// larger tolerance due to failure on mingw 32-bit
|
length = Length(v)
|
||||||
qq := q.s * q.s + q.c * q.c
|
if length < 1e-23 {
|
||||||
return 1.0 - 0.0006 < qq && qq < 1 + 0.0006
|
return
|
||||||
}
|
}
|
||||||
|
invLength := 1 / length
|
||||||
// Normalized linear interpolation
|
vn = invLength * v
|
||||||
// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
|
return
|
||||||
@(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,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Integration rotation from angular velocity
|
// Integration rotation from angular velocity
|
||||||
@@ -268,6 +286,63 @@ IntegrateRotation :: proc "c" (q1: Rot, deltaAngle: f32) -> Rot {
|
|||||||
return {q2.c * invMag, q2.s * invMag}
|
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
|
// Compute the angular velocity necessary to rotate between two rotations over a give time
|
||||||
// @param q1 initial rotation
|
// @param q1 initial rotation
|
||||||
// @param q2 final 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]
|
// Get the angle in radians in the range [-pi, pi]
|
||||||
@(require_results)
|
@(require_results)
|
||||||
Rot_GetAngle :: proc "c" (q: Rot) -> f32 {
|
Rot_GetAngle :: proc "c" (q: Rot) -> f32 {
|
||||||
// todo determinism
|
return Atan2(q.s, q.c)
|
||||||
return math.atan2(q.s, q.c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the x-axis
|
// Get the x-axis
|
||||||
@@ -338,18 +412,34 @@ RelativeAngle :: proc "c" (b, a: Rot) -> f32 {
|
|||||||
// cos(b - a) = bc * ac + bs * as
|
// cos(b - a) = bc * ac + bs * as
|
||||||
s := b.s * a.c - b.c * a.s
|
s := b.s * a.c - b.c * a.s
|
||||||
c := b.c * a.c + b.s * 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]
|
// Convert an angle in the range [-2*pi, 2*pi] into the range [-pi, pi]
|
||||||
@(require_results)
|
@(require_results)
|
||||||
UnwindAngle :: proc "c" (angle: f32) -> f32 {
|
UnwindAngle :: proc "c" (radians: f32) -> f32 {
|
||||||
if angle < -pi {
|
if radians < -PI {
|
||||||
return angle + 2.0 * pi
|
return radians + 2.0 * PI
|
||||||
} else if angle > pi {
|
} else if radians > PI {
|
||||||
return angle - 2.0 * 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
|
// 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}
|
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
|
// 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
|
// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -389,6 +482,7 @@ MulTransforms :: proc "c" (A, B: Transform) -> (C: Transform) {
|
|||||||
return
|
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)
|
// v2 = A.q' * (B.q * v1 + B.p - A.p)
|
||||||
// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
|
// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
|
||||||
@(require_results)
|
@(require_results)
|
||||||
@@ -469,54 +563,65 @@ AABB_Union :: proc "c" (a, b: AABB) -> (c: AABB) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute the bounding box of an array of circles
|
||||||
@(require_results)
|
@(require_results)
|
||||||
Float_IsValid :: proc "c" (a: f32) -> bool {
|
MakeAABB :: proc "c" (points: []Vec2, radius: f32) -> AABB {
|
||||||
math.is_nan(a) or_return
|
a := AABB{points[0], points[0]}
|
||||||
math.is_inf(a) or_return
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
Vec2_IsValid :: proc "c" (v: Vec2) -> bool {
|
IsValidRotation :: proc "c" (q: Rot) -> bool {
|
||||||
(math.is_nan(v.x) || math.is_nan(v.y)) or_return
|
IsValidFloat(q.s) or_return
|
||||||
(math.is_inf(v.x) || math.is_inf(v.y)) 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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is this a valid plane? Normal is a unit vector. Not Nan or infinity.
|
||||||
@(require_results)
|
@(require_results)
|
||||||
Rot_IsValid :: proc "c" (q: Rot) -> bool {
|
IsValidPlane :: proc "c" (plane: Plane) -> bool {
|
||||||
(math.is_nan(q.s) || math.is_nan(q.c)) or_return
|
IsValidFloat(plane.offset) or_return
|
||||||
(math.is_inf(q.s) || math.is_inf(q.c)) or_return
|
IsValidVec2(plane.normal) or_return
|
||||||
return IsNormalized(q)
|
IsNormalized(plane.normal) or_return
|
||||||
}
|
return true
|
||||||
|
|
||||||
@(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
|
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+348
-231
@@ -37,14 +37,28 @@ EnqueueTaskCallback :: #type proc "c" (task: TaskCallback, itemCount: i32, minRa
|
|||||||
// @ingroup world
|
// @ingroup world
|
||||||
FinishTaskCallback :: #type proc "c" (userTask: rawptr, userContext: rawptr)
|
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
|
// Result from b2World_RayCastClosest
|
||||||
// @ingroup world
|
// @ingroup world
|
||||||
RayResult :: struct {
|
RayResult :: struct {
|
||||||
shapeId: ShapeId,
|
shapeId: ShapeId,
|
||||||
point: Vec2,
|
point: Vec2,
|
||||||
normal: Vec2,
|
normal: Vec2,
|
||||||
fraction: f32,
|
fraction: f32,
|
||||||
hit: bool,
|
nodeVisits: i32,
|
||||||
|
leafVisits: i32,
|
||||||
|
hit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// World definition used to create a simulation world.
|
// World definition used to create a simulation world.
|
||||||
@@ -54,37 +68,53 @@ WorldDef :: struct {
|
|||||||
// Gravity vector. Box2D has no up-vector defined.
|
// Gravity vector. Box2D has no up-vector defined.
|
||||||
gravity: Vec2,
|
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).
|
// speed have restitution applied (will bounce).
|
||||||
restitutionThreshold: f32,
|
restitutionThreshold: f32,
|
||||||
|
|
||||||
// This parameter controls how fast overlap is resolved and has units of meters per second
|
// Threshold speed for hit events. Usually meters per second.
|
||||||
contactPushoutVelocity: f32,
|
|
||||||
|
|
||||||
// Threshold velocity for hit events. Usually meters per second.
|
|
||||||
hitEventThreshold: f32,
|
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,
|
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,
|
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.
|
// Joint stiffness. Cycles per second.
|
||||||
jointHertz: f32,
|
jointHertz: f32,
|
||||||
|
|
||||||
// Joint bounciness. Non-dimensional.
|
// Joint bounciness. Non-dimensional.
|
||||||
jointDampingRatio: f32,
|
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
|
// Can bodies go to sleep to improve performance
|
||||||
enableSleep: bool,
|
enableSleep: bool,
|
||||||
|
|
||||||
// Enable continuous collision
|
// Enable continuous collision
|
||||||
enableContinous: bool,
|
enableContinuous: bool,
|
||||||
|
|
||||||
// Number of workers to use with the provided task system. Box2D performs best when using only
|
// 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
|
// performance cores and accessing a single L2 cache. Efficiency cores and hyper-threading provide
|
||||||
// little benefit and may even harm performance.
|
// 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,
|
workerCount: i32,
|
||||||
|
|
||||||
// Function to spawn tasks
|
// Function to spawn tasks
|
||||||
@@ -96,6 +126,9 @@ WorldDef :: struct {
|
|||||||
// User context that is provided to enqueueTask and finishTask
|
// User context that is provided to enqueueTask and finishTask
|
||||||
userTaskContext: rawptr,
|
userTaskContext: rawptr,
|
||||||
|
|
||||||
|
// User data
|
||||||
|
userData: rawptr,
|
||||||
|
|
||||||
// Used internally to detect a valid definition. DO NOT SET.
|
// Used internally to detect a valid definition. DO NOT SET.
|
||||||
internalValue: i32,
|
internalValue: i32,
|
||||||
}
|
}
|
||||||
@@ -138,20 +171,20 @@ BodyDef :: struct {
|
|||||||
// The initial world rotation of the body. Use b2MakeRot() if you have an angle.
|
// The initial world rotation of the body. Use b2MakeRot() if you have an angle.
|
||||||
rotation: Rot,
|
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,
|
linearVelocity: Vec2,
|
||||||
|
|
||||||
// The initial angular velocity of the body. Radians per second.
|
// The initial angular velocity of the body. Radians per second.
|
||||||
angularVelocity: f32,
|
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
|
// can be larger than 1 but the damping effect becomes sensitive to the
|
||||||
// time step when the damping parameter is large.
|
// time step when the damping parameter is large.
|
||||||
// Generally linear damping is undesirable because it makes objects move slowly
|
// Generally linear damping is undesirable because it makes objects move slowly
|
||||||
// as if they are f32ing.
|
// as if they are f32ing.
|
||||||
linearDamping: f32,
|
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
|
// can be larger than 1.0f but the damping effect becomes sensitive to the
|
||||||
// time step when the damping parameter is large.
|
// time step when the damping parameter is large.
|
||||||
// Angular damping can be use slow down rotating bodies.
|
// Angular damping can be use slow down rotating bodies.
|
||||||
@@ -160,9 +193,12 @@ BodyDef :: struct {
|
|||||||
// Scale the gravity applied to this body. Non-dimensional.
|
// Scale the gravity applied to this body. Non-dimensional.
|
||||||
gravityScale: f32,
|
gravityScale: f32,
|
||||||
|
|
||||||
// Sleep velocity threshold, default is 0.05 meter per second
|
// Sleep speed threshold, default is 0.05 meters per second
|
||||||
sleepThreshold: f32,
|
sleepThreshold: f32,
|
||||||
|
|
||||||
|
// Optional body name for debugging. Up to 32 characters (excluding null termination)
|
||||||
|
name: cstring,
|
||||||
|
|
||||||
// Use this to store application specific body data.
|
// Use this to store application specific body data.
|
||||||
userData: rawptr,
|
userData: rawptr,
|
||||||
|
|
||||||
@@ -184,10 +220,6 @@ BodyDef :: struct {
|
|||||||
// Used to disable a body. A disabled body does not move or collide.
|
// Used to disable a body. A disabled body does not move or collide.
|
||||||
isEnabled: bool,
|
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
|
// This allows this body to bypass rotational speed limits. Should only be used
|
||||||
// for circular objects, like wheels.
|
// for circular objects, like wheels.
|
||||||
allowFastRotation: bool,
|
allowFastRotation: bool,
|
||||||
@@ -204,7 +236,7 @@ Filter :: struct {
|
|||||||
// The collision category bits. Normally you would just set one bit. The category bits should
|
// The collision category bits. Normally you would just set one bit. The category bits should
|
||||||
// represent your application object types. For example:
|
// represent your application object types. For example:
|
||||||
// @code{.odin}
|
// @code{.odin}
|
||||||
// My_Categories :: enum u32 {
|
// My_Categories :: enum u64 {
|
||||||
// Static = 0x00000001,
|
// Static = 0x00000001,
|
||||||
// Dynamic = 0x00000002,
|
// Dynamic = 0x00000002,
|
||||||
// Debris = 0x00000004,
|
// Debris = 0x00000004,
|
||||||
@@ -213,16 +245,16 @@ Filter :: struct {
|
|||||||
// };
|
// };
|
||||||
// @endcode
|
// @endcode
|
||||||
// Or use a bit_set.
|
// Or use a bit_set.
|
||||||
categoryBits: u32,
|
categoryBits: u64,
|
||||||
|
|
||||||
// The collision mask bits. This states the categories that this
|
// The collision mask bits. This states the categories that this
|
||||||
// shape would accept for collision.
|
// shape would accept for collision.
|
||||||
// For example, you may want your player to only collide with static objects
|
// For example, you may want your player to only collide with static objects
|
||||||
// and other players.
|
// and other players.
|
||||||
// @code{.odin}
|
// @code{.odin}
|
||||||
// maskBits = u32(My_Categories.Static | My_Categories.Player);
|
// maskBits = u64(My_Categories.Static | My_Categories.Player);
|
||||||
// @endcode
|
// @endcode
|
||||||
maskBits: u32,
|
maskBits: u64,
|
||||||
|
|
||||||
// Collision groups allow a certain group of objects to never collide (negative)
|
// 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
|
// or always collide (positive). A group index of zero has no effect. Non-zero group filtering
|
||||||
@@ -240,11 +272,11 @@ Filter :: struct {
|
|||||||
// @ingroup shape
|
// @ingroup shape
|
||||||
QueryFilter :: struct {
|
QueryFilter :: struct {
|
||||||
// The collision category bits of this query. Normally you would just set one bit.
|
// 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
|
// The collision mask bits. This states the shape categories that this
|
||||||
// query would accept for collision.
|
// query would accept for collision.
|
||||||
maskBits: u32,
|
maskBits: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -263,13 +295,37 @@ ShapeType :: enum c.int {
|
|||||||
// A convex polygon
|
// A convex polygon
|
||||||
polygonShape,
|
polygonShape,
|
||||||
|
|
||||||
// A smooth segment owned by a chain shape
|
// A line segment owned by a chain shape
|
||||||
smoothSegmentShape,
|
chainSegmentShape,
|
||||||
}
|
}
|
||||||
|
|
||||||
// The number of shape types
|
// The number of shape types
|
||||||
shapeTypeCount :: len(ShapeType)
|
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.
|
// Used to create a shape.
|
||||||
// This is a temporary object used to bundle shape creation parameters. You may use
|
// This is a temporary object used to bundle shape creation parameters. You may use
|
||||||
// the same shape definition to create multiple shapes.
|
// the same shape definition to create multiple shapes.
|
||||||
@@ -279,58 +335,61 @@ ShapeDef :: struct {
|
|||||||
// Use this to store application specific shape data.
|
// Use this to store application specific shape data.
|
||||||
userData: rawptr,
|
userData: rawptr,
|
||||||
|
|
||||||
// The Coulomb (dry) friction coefficient, usually in the range [0,1].
|
// The surface material for this shape.
|
||||||
friction: f32,
|
material: SurfaceMaterial,
|
||||||
|
|
||||||
// The restitution (bounce) usually in the range [0,1].
|
|
||||||
restitution: f32,
|
|
||||||
|
|
||||||
// The density, usually in kg/m^2.
|
// 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,
|
density: f32,
|
||||||
|
|
||||||
// Collision filtering data.
|
// Collision filtering data.
|
||||||
filter: Filter,
|
filter: Filter,
|
||||||
|
|
||||||
// Custom debug draw color.
|
|
||||||
customColor: u32,
|
|
||||||
|
|
||||||
// A sensor shape generates overlap events but never generates a collision response.
|
// 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,
|
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,
|
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,
|
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,
|
enableHitEvents: bool,
|
||||||
|
|
||||||
// Enable pre-solve contact events for this shape. Only applies to dynamic bodies. These are expensive
|
// 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.
|
// and must be carefully handled due to threading. Ignored for sensors.
|
||||||
enablePreSolveEvents: bool,
|
enablePreSolveEvents: bool,
|
||||||
|
|
||||||
// Normally shapes on static bodies don't invoke contact creation when they are added to the world. This overrides
|
// When shapes are created they will scan the environment for collision the next time step. This can significantly slow down
|
||||||
// that behavior and causes contact creation. This significantly slows down static body creation which can be important
|
// static body creation when there are many static shapes.
|
||||||
// when there are many static shapes.
|
// This is flag is ignored for dynamic and kinematic shapes which always invoke contact creation.
|
||||||
forceContactCreation: bool,
|
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.
|
// Used internally to detect a valid definition. DO NOT SET.
|
||||||
internalValue: i32,
|
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 are one-sided
|
||||||
// - chains have no mass and should be used on static bodies
|
// - 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
|
// - chains are either a loop or open
|
||||||
// - a chain must have at least 4 points
|
// - 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)
|
// - a chain shape should not self intersect (this is not validated)
|
||||||
// - an open chain shape has NO COLLISION on the first and final edge
|
// - 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
|
// - 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
|
// https://en.wikipedia.org/wiki/Polygonal_chain
|
||||||
// Must be initialized using b2DefaultChainDef().
|
// Must be initialized using b2DefaultChainDef().
|
||||||
// @warning Do not use chain shapes unless you understand the limitations. This is an advanced feature.
|
// @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.
|
// The point count, must be 4 or more.
|
||||||
count: i32,
|
count: i32,
|
||||||
|
|
||||||
// The friction coefficient, usually in the range [0,1].
|
// Surface materials for each segment. These are cloned.
|
||||||
friction: f32,
|
materials: [^]SurfaceMaterial `fmt:"v,materialCount"`,
|
||||||
|
|
||||||
// The restitution (elasticity) usually in the range [0,1].
|
// The material count. Must be 1 or count. This allows you to provide one
|
||||||
restitution: f32,
|
// material for all segments or a unique material per segment.
|
||||||
|
materialCount: i32,
|
||||||
|
|
||||||
// Contact filtering data.
|
// Contact filtering data.
|
||||||
filter: Filter,
|
filter: Filter,
|
||||||
@@ -357,6 +417,9 @@ ChainDef :: struct {
|
|||||||
// Indicates a closed chain formed by connecting the first and last points
|
// Indicates a closed chain formed by connecting the first and last points
|
||||||
isLoop: bool,
|
isLoop: bool,
|
||||||
|
|
||||||
|
// Enable sensors to detect this chain. False by default.
|
||||||
|
enableSensorEvents: bool,
|
||||||
|
|
||||||
// Used internally to detect a valid definition. DO NOT SET.
|
// Used internally to detect a valid definition. DO NOT SET.
|
||||||
internalValue: i32,
|
internalValue: i32,
|
||||||
}
|
}
|
||||||
@@ -369,29 +432,28 @@ Profile :: struct {
|
|||||||
pairs: f32,
|
pairs: f32,
|
||||||
collide: f32,
|
collide: f32,
|
||||||
solve: f32,
|
solve: f32,
|
||||||
buildIslands: f32,
|
mergeIslands: f32,
|
||||||
|
prepareStages: f32,
|
||||||
solveConstraints: f32,
|
solveConstraints: f32,
|
||||||
prepareTasks: f32,
|
|
||||||
solverTasks: f32,
|
|
||||||
prepareConstraints: f32,
|
prepareConstraints: f32,
|
||||||
integrateVelocities: f32,
|
integrateVelocities: f32,
|
||||||
warmStart: f32,
|
warmStart: f32,
|
||||||
solveVelocities: f32,
|
solveImpulses: f32,
|
||||||
integratePositions: f32,
|
integratePositions: f32,
|
||||||
relaxVelocities: f32,
|
relaxImpulses: f32,
|
||||||
applyRestitution: f32,
|
applyRestitution: f32,
|
||||||
storeImpulses: f32,
|
storeImpulses: f32,
|
||||||
finalizeBodies: f32,
|
|
||||||
splitIslands: f32,
|
splitIslands: f32,
|
||||||
sleepIslands: f32,
|
transforms: f32,
|
||||||
hitEvents: f32,
|
hitEvents: f32,
|
||||||
broadphase: f32,
|
refit: f32,
|
||||||
continuous: f32,
|
bullets: f32,
|
||||||
|
sleepIslands: f32,
|
||||||
|
sensors: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Counters that give details of the simulation size.
|
// Counters that give details of the simulation size.
|
||||||
Counters :: struct {
|
Counters :: struct {
|
||||||
staticBodyCount: i32,
|
|
||||||
bodyCount: i32,
|
bodyCount: i32,
|
||||||
shapeCount: i32,
|
shapeCount: i32,
|
||||||
contactCount: i32,
|
contactCount: i32,
|
||||||
@@ -413,6 +475,7 @@ Counters :: struct {
|
|||||||
// @ingroup joint
|
// @ingroup joint
|
||||||
JointType :: enum c.int {
|
JointType :: enum c.int {
|
||||||
distanceJoint,
|
distanceJoint,
|
||||||
|
filterJoint,
|
||||||
motorJoint,
|
motorJoint,
|
||||||
mouseJoint,
|
mouseJoint,
|
||||||
prismaticJoint,
|
prismaticJoint,
|
||||||
@@ -526,7 +589,7 @@ MotorJointDef :: struct {
|
|||||||
// applying huge forces. This also applies rotation constraint heuristic to improve control.
|
// applying huge forces. This also applies rotation constraint heuristic to improve control.
|
||||||
// @ingroup mouse_joint
|
// @ingroup mouse_joint
|
||||||
MouseJointDef :: struct {
|
MouseJointDef :: struct {
|
||||||
// The first attached body.
|
// The first attached body. This is assumed to be static.
|
||||||
bodyIdA: BodyId,
|
bodyIdA: BodyId,
|
||||||
|
|
||||||
// The second attached body.
|
// The second attached body.
|
||||||
@@ -554,6 +617,22 @@ MouseJointDef :: struct {
|
|||||||
internalValue: i32,
|
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
|
// Prismatic joint definition
|
||||||
//
|
//
|
||||||
@@ -660,10 +739,10 @@ RevoluteJointDef :: struct {
|
|||||||
// A flag to enable joint limits
|
// A flag to enable joint limits
|
||||||
enableLimit: bool,
|
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,
|
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,
|
upperAngle: f32,
|
||||||
|
|
||||||
// A flag to enable the joint motor
|
// A flag to enable the joint motor
|
||||||
@@ -794,6 +873,27 @@ WheelJointDef :: struct {
|
|||||||
internalValue: i32,
|
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
|
* @defgroup events Events
|
||||||
@@ -822,11 +922,18 @@ SensorBeginTouchEvent :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// An end touch event is generated when a shape stops overlapping a sensor shape.
|
// 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 {
|
SensorEndTouchEvent :: struct {
|
||||||
// The id of the sensor shape
|
// The id of the sensor shape
|
||||||
|
// @warning this shape may have been destroyed
|
||||||
|
// @see b2Shape_IsValid
|
||||||
sensorShapeId: ShapeId,
|
sensorShapeId: ShapeId,
|
||||||
|
|
||||||
// The id of the dynamic shape that stopped touching the sensor shape
|
// The id of the dynamic shape that stopped touching the sensor shape
|
||||||
|
// @warning this shape may have been destroyed
|
||||||
|
// @see b2Shape_IsValid
|
||||||
visitorShapeId: ShapeId,
|
visitorShapeId: ShapeId,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -854,14 +961,25 @@ ContactBeginTouchEvent :: struct {
|
|||||||
|
|
||||||
// Id of the second shape
|
// Id of the second shape
|
||||||
shapeIdB: ShapeId,
|
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.
|
// 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 {
|
ContactEndTouchEvent :: struct {
|
||||||
// Id of the first shape
|
// Id of the first shape
|
||||||
|
// @warning this shape may have been destroyed
|
||||||
|
// @see b2Shape_IsValid
|
||||||
shapeIdA: ShapeId,
|
shapeIdA: ShapeId,
|
||||||
|
|
||||||
// Id of the second shape
|
// Id of the second shape
|
||||||
|
// @warning this shape may have been destroyed
|
||||||
|
// @see b2Shape_IsValid
|
||||||
shapeIdB: ShapeId,
|
shapeIdB: ShapeId,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -998,201 +1116,191 @@ OverlapResultFcn :: #type proc "c" (shapeId: ShapeId, ctx: rawptr) -> bool
|
|||||||
// @ingroup world
|
// @ingroup world
|
||||||
CastResultFcn :: #type proc "c" (shapeId: ShapeId, point: Vec2, normal: Vec2, fraction: f32, ctx: rawptr) -> f32
|
CastResultFcn :: #type proc "c" (shapeId: ShapeId, point: Vec2, normal: Vec2, fraction: f32, ctx: rawptr) -> f32
|
||||||
|
|
||||||
// These colors are used for debug draw.
|
// Used to collect collision planes for character movers.
|
||||||
// See https://www.rapidtables.com/web/color/index.html
|
// 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 {
|
HexColor :: enum c.int {
|
||||||
AliceBlue = 0xf0f8ff,
|
AliceBlue = 0xF0F8FF,
|
||||||
AntiqueWhite = 0xfaebd7,
|
AntiqueWhite = 0xFAEBD7,
|
||||||
Aqua = 0x00ffff,
|
Aqua = 0x00FFFF,
|
||||||
Aquamarine = 0x7fffd4,
|
Aquamarine = 0x7FFFD4,
|
||||||
Azure = 0xf0ffff,
|
Azure = 0xF0FFFF,
|
||||||
Beige = 0xf5f5dc,
|
Beige = 0xF5F5DC,
|
||||||
Bisque = 0xffe4c4,
|
Bisque = 0xFFE4C4,
|
||||||
Black = 0x000000,
|
Black = 0x000000,
|
||||||
BlanchedAlmond = 0xffebcd,
|
BlanchedAlmond = 0xFFEBCD,
|
||||||
Blue = 0x0000ff,
|
Blue = 0x0000FF,
|
||||||
BlueViolet = 0x8a2be2,
|
BlueViolet = 0x8A2BE2,
|
||||||
Brown = 0xa52a2a,
|
Brown = 0xA52A2A,
|
||||||
Burlywood = 0xdeb887,
|
Burlywood = 0xDEB887,
|
||||||
CadetBlue = 0x5f9ea0,
|
CadetBlue = 0x5F9EA0,
|
||||||
Chartreuse = 0x7fff00,
|
Chartreuse = 0x7FFF00,
|
||||||
Chocolate = 0xd2691e,
|
Chocolate = 0xD2691E,
|
||||||
Coral = 0xff7f50,
|
Coral = 0xFF7F50,
|
||||||
CornflowerBlue = 0x6495ed,
|
CornflowerBlue = 0x6495ED,
|
||||||
Cornsilk = 0xfff8dc,
|
Cornsilk = 0xFFF8DC,
|
||||||
Crimson = 0xdc143c,
|
Crimson = 0xDC143C,
|
||||||
Cyan = 0x00ffff,
|
Cyan = 0x00FFFF,
|
||||||
DarkBlue = 0x00008b,
|
DarkBlue = 0x00008B,
|
||||||
DarkCyan = 0x008b8b,
|
DarkCyan = 0x008B8B,
|
||||||
DarkGoldenrod = 0xb8860b,
|
DarkGoldenRod = 0xB8860B,
|
||||||
DarkGray = 0xa9a9a9,
|
DarkGray = 0xA9A9A9,
|
||||||
DarkGreen = 0x006400,
|
DarkGreen = 0x006400,
|
||||||
DarkKhaki = 0xbdb76b,
|
DarkKhaki = 0xBDB76B,
|
||||||
DarkMagenta = 0x8b008b,
|
DarkMagenta = 0x8B008B,
|
||||||
DarkOliveGreen = 0x556b2f,
|
DarkOliveGreen = 0x556B2F,
|
||||||
DarkOrange = 0xff8c00,
|
DarkOrange = 0xFF8C00,
|
||||||
DarkOrchid = 0x9932cc,
|
DarkOrchid = 0x9932CC,
|
||||||
DarkRed = 0x8b0000,
|
DarkRed = 0x8B0000,
|
||||||
DarkSalmon = 0xe9967a,
|
DarkSalmon = 0xE9967A,
|
||||||
DarkSeaGreen = 0x8fbc8f,
|
DarkSeaGreen = 0x8FBC8F,
|
||||||
DarkSlateBlue = 0x483d8b,
|
DarkSlateBlue = 0x483D8B,
|
||||||
DarkSlateGray = 0x2f4f4f,
|
DarkSlateGray = 0x2F4F4F,
|
||||||
DarkTurquoise = 0x00ced1,
|
DarkTurquoise = 0x00CED1,
|
||||||
DarkViolet = 0x9400d3,
|
DarkViolet = 0x9400D3,
|
||||||
DeepPink = 0xff1493,
|
DeepPink = 0xFF1493,
|
||||||
DeepSkyBlue = 0x00bfff,
|
DeepSkyBlue = 0x00BFFF,
|
||||||
DimGray = 0x696969,
|
DimGray = 0x696969,
|
||||||
DodgerBlue = 0x1e90ff,
|
DodgerBlue = 0x1E90FF,
|
||||||
Firebrick = 0xb22222,
|
FireBrick = 0xB22222,
|
||||||
FloralWhite = 0xfffaf0,
|
FloralWhite = 0xFFFAF0,
|
||||||
ForestGreen = 0x228b22,
|
ForestGreen = 0x228B22,
|
||||||
Fuchsia = 0xff00ff,
|
Fuchsia = 0xFF00FF,
|
||||||
Gainsboro = 0xdcdcdc,
|
Gainsboro = 0xDCDCDC,
|
||||||
GhostWhite = 0xf8f8ff,
|
GhostWhite = 0xF8F8FF,
|
||||||
Gold = 0xffd700,
|
Gold = 0xFFD700,
|
||||||
Goldenrod = 0xdaa520,
|
GoldenRod = 0xDAA520,
|
||||||
Gray = 0xbebebe,
|
Gray = 0x808080,
|
||||||
Gray1 = 0x1a1a1a,
|
Green = 0x008000,
|
||||||
Gray2 = 0x333333,
|
GreenYellow = 0xADFF2F,
|
||||||
Gray3 = 0x4d4d4d,
|
HoneyDew = 0xF0FFF0,
|
||||||
Gray4 = 0x666666,
|
HotPink = 0xFF69B4,
|
||||||
Gray5 = 0x7f7f7f,
|
IndianRed = 0xCD5C5C,
|
||||||
Gray6 = 0x999999,
|
Indigo = 0x4B0082,
|
||||||
Gray7 = 0xb3b3b3,
|
Ivory = 0xFFFFF0,
|
||||||
Gray8 = 0xcccccc,
|
Khaki = 0xF0E68C,
|
||||||
Gray9 = 0xe5e5e5,
|
Lavender = 0xE6E6FA,
|
||||||
Green = 0x00ff00,
|
LavenderBlush = 0xFFF0F5,
|
||||||
GreenYellow = 0xadff2f,
|
LawnGreen = 0x7CFC00,
|
||||||
Honeydew = 0xf0fff0,
|
LemonChiffon = 0xFFFACD,
|
||||||
HotPink = 0xff69b4,
|
LightBlue = 0xADD8E6,
|
||||||
IndianRed = 0xcd5c5c,
|
LightCoral = 0xF08080,
|
||||||
Indigo = 0x4b0082,
|
LightCyan = 0xE0FFFF,
|
||||||
Ivory = 0xfffff0,
|
LightGoldenRodYellow = 0xFAFAD2,
|
||||||
Khaki = 0xf0e68c,
|
LightGray = 0xD3D3D3,
|
||||||
Lavender = 0xe6e6fa,
|
LightGreen = 0x90EE90,
|
||||||
LavenderBlush = 0xfff0f5,
|
LightPink = 0xFFB6C1,
|
||||||
LawnGreen = 0x7cfc00,
|
LightSalmon = 0xFFA07A,
|
||||||
LemonChiffon = 0xfffacd,
|
LightSeaGreen = 0x20B2AA,
|
||||||
LightBlue = 0xadd8e6,
|
LightSkyBlue = 0x87CEFA,
|
||||||
LightCoral = 0xf08080,
|
|
||||||
LightCyan = 0xe0ffff,
|
|
||||||
LightGoldenrod = 0xeedd82,
|
|
||||||
LightGoldenrodYellow = 0xfafad2,
|
|
||||||
LightGray = 0xd3d3d3,
|
|
||||||
LightGreen = 0x90ee90,
|
|
||||||
LightPink = 0xffb6c1,
|
|
||||||
LightSalmon = 0xffa07a,
|
|
||||||
LightSeaGreen = 0x20b2aa,
|
|
||||||
LightSkyBlue = 0x87cefa,
|
|
||||||
LightSlateBlue = 0x8470ff,
|
|
||||||
LightSlateGray = 0x778899,
|
LightSlateGray = 0x778899,
|
||||||
LightSteelBlue = 0xb0c4de,
|
LightSteelBlue = 0xB0C4DE,
|
||||||
LightYellow = 0xffffe0,
|
LightYellow = 0xFFFFE0,
|
||||||
Lime = 0x00ff00,
|
Lime = 0x00FF00,
|
||||||
LimeGreen = 0x32cd32,
|
LimeGreen = 0x32CD32,
|
||||||
Linen = 0xfaf0e6,
|
Linen = 0xFAF0E6,
|
||||||
Magenta = 0xff00ff,
|
Magenta = 0xFF00FF,
|
||||||
Maroon = 0xb03060,
|
Maroon = 0x800000,
|
||||||
MediumAquamarine = 0x66cdaa,
|
MediumAquaMarine = 0x66CDAA,
|
||||||
MediumBlue = 0x0000cd,
|
MediumBlue = 0x0000CD,
|
||||||
MediumOrchid = 0xba55d3,
|
MediumOrchid = 0xBA55D3,
|
||||||
MediumPurple = 0x9370db,
|
MediumPurple = 0x9370DB,
|
||||||
MediumSeaGreen = 0x3cb371,
|
MediumSeaGreen = 0x3CB371,
|
||||||
MediumSlateBlue = 0x7b68ee,
|
MediumSlateBlue = 0x7B68EE,
|
||||||
MediumSpringGreen = 0x00fa9a,
|
MediumSpringGreen = 0x00FA9A,
|
||||||
MediumTurquoise = 0x48d1cc,
|
MediumTurquoise = 0x48D1CC,
|
||||||
MediumVioletRed = 0xc71585,
|
MediumVioletRed = 0xC71585,
|
||||||
MidnightBlue = 0x191970,
|
MidnightBlue = 0x191970,
|
||||||
MintCream = 0xf5fffa,
|
MintCream = 0xF5FFFA,
|
||||||
MistyRose = 0xffe4e1,
|
MistyRose = 0xFFE4E1,
|
||||||
Moccasin = 0xffe4b5,
|
Moccasin = 0xFFE4B5,
|
||||||
NavajoWhite = 0xffdead,
|
NavajoWhite = 0xFFDEAD,
|
||||||
Navy = 0x000080,
|
Navy = 0x000080,
|
||||||
NavyBlue = 0x000080,
|
OldLace = 0xFDF5E6,
|
||||||
OldLace = 0xfdf5e6,
|
|
||||||
Olive = 0x808000,
|
Olive = 0x808000,
|
||||||
OliveDrab = 0x6b8e23,
|
OliveDrab = 0x6B8E23,
|
||||||
Orange = 0xffa500,
|
Orange = 0xFFA500,
|
||||||
OrangeRed = 0xff4500,
|
OrangeRed = 0xFF4500,
|
||||||
Orchid = 0xda70d6,
|
Orchid = 0xDA70D6,
|
||||||
PaleGoldenrod = 0xeee8aa,
|
PaleGoldenRod = 0xEEE8AA,
|
||||||
PaleGreen = 0x98fb98,
|
PaleGreen = 0x98FB98,
|
||||||
PaleTurquoise = 0xafeeee,
|
PaleTurquoise = 0xAFEEEE,
|
||||||
PaleVioletRed = 0xdb7093,
|
PaleVioletRed = 0xDB7093,
|
||||||
PapayaWhip = 0xffefd5,
|
PapayaWhip = 0xFFEFD5,
|
||||||
PeachPuff = 0xffdab9,
|
PeachPuff = 0xFFDAB9,
|
||||||
Peru = 0xcd853f,
|
Peru = 0xCD853F,
|
||||||
Pink = 0xffc0cb,
|
Pink = 0xFFC0CB,
|
||||||
Plum = 0xdda0dd,
|
Plum = 0xDDA0DD,
|
||||||
PowderBlue = 0xb0e0e6,
|
PowderBlue = 0xB0E0E6,
|
||||||
Purple = 0xa020f0,
|
Purple = 0x800080,
|
||||||
RebeccaPurple = 0x663399,
|
RebeccaPurple = 0x663399,
|
||||||
Red = 0xff0000,
|
Red = 0xFF0000,
|
||||||
RosyBrown = 0xbc8f8f,
|
RosyBrown = 0xBC8F8F,
|
||||||
RoyalBlue = 0x4169e1,
|
RoyalBlue = 0x4169E1,
|
||||||
SaddleBrown = 0x8b4513,
|
SaddleBrown = 0x8B4513,
|
||||||
Salmon = 0xfa8072,
|
Salmon = 0xFA8072,
|
||||||
SandyBrown = 0xf4a460,
|
SandyBrown = 0xF4A460,
|
||||||
SeaGreen = 0x2e8b57,
|
SeaGreen = 0x2E8B57,
|
||||||
Seashell = 0xfff5ee,
|
SeaShell = 0xFFF5EE,
|
||||||
Sienna = 0xa0522d,
|
Sienna = 0xA0522D,
|
||||||
Silver = 0xc0c0c0,
|
Silver = 0xC0C0C0,
|
||||||
SkyBlue = 0x87ceeb,
|
SkyBlue = 0x87CEEB,
|
||||||
SlateBlue = 0x6a5acd,
|
SlateBlue = 0x6A5ACD,
|
||||||
SlateGray = 0x708090,
|
SlateGray = 0x708090,
|
||||||
Snow = 0xfffafa,
|
Snow = 0xFFFAFA,
|
||||||
SpringGreen = 0x00ff7f,
|
SpringGreen = 0x00FF7F,
|
||||||
SteelBlue = 0x4682b4,
|
SteelBlue = 0x4682B4,
|
||||||
Tan = 0xd2b48c,
|
Tan = 0xD2B48C,
|
||||||
Teal = 0x008080,
|
Teal = 0x008080,
|
||||||
Thistle = 0xd8bfd8,
|
Thistle = 0xD8BFD8,
|
||||||
Tomato = 0xff6347,
|
Tomato = 0xFF6347,
|
||||||
Turquoise = 0x40e0d0,
|
Turquoise = 0x40E0D0,
|
||||||
Violet = 0xee82ee,
|
Violet = 0xEE82EE,
|
||||||
VioletRed = 0xd02090,
|
Wheat = 0xF5DEB3,
|
||||||
Wheat = 0xf5deb3,
|
White = 0xFFFFFF,
|
||||||
White = 0xffffff,
|
WhiteSmoke = 0xF5F5F5,
|
||||||
WhiteSmoke = 0xf5f5f5,
|
Yellow = 0xFFFF00,
|
||||||
Yellow = 0xffff00,
|
YellowGreen = 0x9ACD32,
|
||||||
YellowGreen = 0x9acd32,
|
Box2DRed = 0xDC3132,
|
||||||
Box2DRed = 0xdc3132,
|
Box2DBlue = 0x30AEBF,
|
||||||
Box2DBlue = 0x30aebf,
|
Box2DGreen = 0x8CC924,
|
||||||
Box2DGreen = 0x8cc924,
|
Box2DYellow = 0xFFEE8C,
|
||||||
Box2DYellow = 0xffee8c,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This struct holds callbacks you can implement to draw a Box2D world.
|
// This struct holds callbacks you can implement to draw a Box2D world.
|
||||||
// @ingroup world
|
// @ingroup world
|
||||||
DebugDraw :: struct {
|
DebugDraw :: struct {
|
||||||
// Draw a closed polygon provided in CCW order.
|
// 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.
|
// 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.
|
// 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.
|
// Draw a solid circle.
|
||||||
DrawSolidCircle: proc "c" (transform: Transform, radius: f32, color: HexColor, ctx: rawptr),
|
DrawSolidCircleFcn: 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),
|
|
||||||
|
|
||||||
// Draw a solid capsule.
|
// 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.
|
// 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.
|
// 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.
|
// 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.
|
// Draw a string in world space.
|
||||||
DrawString: proc "c" (p: Vec2, s: cstring, ctx: rawptr),
|
DrawStringFcn: proc "c" (p: Vec2, s: cstring, color: HexColor, ctx: rawptr),
|
||||||
|
|
||||||
// Bounds to use if restricting drawing to a rectangular region
|
// Bounds to use if restricting drawing to a rectangular region
|
||||||
drawingBounds: AABB,
|
drawingBounds: AABB,
|
||||||
@@ -1210,11 +1318,14 @@ DebugDraw :: struct {
|
|||||||
drawJointExtras: bool,
|
drawJointExtras: bool,
|
||||||
|
|
||||||
// Option to draw the bounding boxes for shapes
|
// Option to draw the bounding boxes for shapes
|
||||||
drawAABBs: bool,
|
drawBounds: bool,
|
||||||
|
|
||||||
// Option to draw the mass and center of mass of dynamic bodies
|
// Option to draw the mass and center of mass of dynamic bodies
|
||||||
drawMass: bool,
|
drawMass: bool,
|
||||||
|
|
||||||
|
// Option to draw body names
|
||||||
|
drawBodyNames: bool,
|
||||||
|
|
||||||
// Option to draw contact points
|
// Option to draw contact points
|
||||||
drawContacts: bool,
|
drawContacts: bool,
|
||||||
|
|
||||||
@@ -1227,9 +1338,15 @@ DebugDraw :: struct {
|
|||||||
// Option to draw contact normal impulses
|
// Option to draw contact normal impulses
|
||||||
drawContactImpulses: bool,
|
drawContactImpulses: bool,
|
||||||
|
|
||||||
|
// Option to draw contact feature ids
|
||||||
|
drawContactFeatures: bool,
|
||||||
|
|
||||||
// Option to draw contact friction impulses
|
// Option to draw contact friction impulses
|
||||||
drawFrictionImpulses: bool,
|
drawFrictionImpulses: bool,
|
||||||
|
|
||||||
|
// Option to draw islands as bounding boxes
|
||||||
|
drawIslands: bool,
|
||||||
|
|
||||||
// User context that is passed as an argument to drawing callback functions
|
// User context that is passed as an argument to drawing callback functions
|
||||||
userContext: rawptr,
|
userContext: rawptr,
|
||||||
}
|
}
|
||||||
Vendored
+4
-4
@@ -7,20 +7,20 @@
|
|||||||
# CC = $(shell brew --prefix llvm)/bin/clang
|
# CC = $(shell brew --prefix llvm)/bin/clang
|
||||||
# LD = $(shell brew --prefix llvm)/bin/wasm-ld
|
# LD = $(shell brew --prefix llvm)/bin/wasm-ld
|
||||||
|
|
||||||
VERSION = 3.0.0
|
VERSION = 3.1.0
|
||||||
SRCS = $(wildcard box2d-$(VERSION)/src/*.c)
|
SRCS = $(wildcard box2d-$(VERSION)/src/*.c)
|
||||||
OBJS_SIMD = $(SRCS:.c=_simd.o)
|
OBJS_SIMD = $(SRCS:.c=_simd.o)
|
||||||
OBJS = $(SRCS:.c=.o)
|
OBJS = $(SRCS:.c=.o)
|
||||||
SYSROOT = $(shell odin root)/vendor/libc
|
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
|
all: lib/box2d_wasm.o lib/box2d_wasm_simd.o clean
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) -c $(CFLAGS) $< -o $@
|
$(CC) -c $(CFLAGS) -DBOX2D_DISABLE_SIMD $< -o $@
|
||||||
|
|
||||||
%_simd.o: %.c
|
%_simd.o: %.c
|
||||||
$(CC) -c $(CFLAGS) -msimd128 $< -o $@
|
$(CC) -c $(CFLAGS) -DBOX2D_DISABLE_SIMD -msimd128 $< -o $@
|
||||||
|
|
||||||
lib/box2d_wasm.o: $(OBJS)
|
lib/box2d_wasm.o: $(OBJS)
|
||||||
$(LD) -r -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);
|
bool __isnand(double);
|
||||||
#define isnan(x) \
|
#define isnan(x) \
|
||||||
( sizeof(x) == sizeof(float) ? __isnanf((float)(x)) \
|
( sizeof(x) == sizeof(float) ? __isnanf((float)(x)) \
|
||||||
: : __isnand((double)(x)))
|
: __isnand((double)(x)))
|
||||||
|
|
||||||
bool __isinff(float);
|
bool __isinff(float);
|
||||||
bool __isinfd(double);
|
bool __isinfd(double);
|
||||||
#define isinf(x) \
|
#define isinf(x) \
|
||||||
( sizeof(x) == sizeof(float) ? __isinff((float)(x)) \
|
( sizeof(x) == sizeof(float) ? __isinff((float)(x)) \
|
||||||
: : __isinfd((double)(x)))
|
: __isinfd((double)(x)))
|
||||||
|
|
||||||
bool __isfinitef(float);
|
bool __isfinitef(float);
|
||||||
bool __isfinited(double);
|
bool __isfinited(double);
|
||||||
#define isfinite(x) \
|
#define isfinite(x) \
|
||||||
( sizeof(x) == sizeof(float) ? __isfinitef((float)(x)) \
|
( sizeof(x) == sizeof(float) ? __isfinitef((float)(x)) \
|
||||||
: : __isfinited((double)(x)))
|
: __isfinited((double)(x)))
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#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
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package odin_libc
|
||||||
|
|
||||||
|
import "core:time"
|
||||||
|
|
||||||
|
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 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user