Create bindings for box2d

Currently missing lib binaries
This commit is contained in:
gingerBill
2024-08-13 16:18:24 +01:00
parent 55be3e60a0
commit f2ba3da895
7 changed files with 3780 additions and 0 deletions

21
vendor/box2d/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Erin Catto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

32
vendor/box2d/README.md vendored Normal file
View File

@@ -0,0 +1,32 @@
![Box2D Logo](https://box2d.org/images/logo.svg)
# Status
[![Build Status](https://github.com/erincatto/box2c/actions/workflows/build.yml/badge.svg)](https://github.com/erincatto/box2c/actions)
# Box2D v3.0 Notes
This repository is beta and ready for testing. It should build on recent versions of clang and gcc. However, you will need the latest Visual Studio version for C11 atomics to compile (17.8.3+).
AVX2 CPU support is assumed. You can turn this off in the CMake options and use SSE2 instead.
# Box2D
Box2D is a 2D physics engine for games.
## Contributing
Please do not submit pull requests with new features or core library changes. Instead, please file an issue first for discussion. For bugs, I prefer detailed bug reports over pull requests.
# Giving Feedback
Please visit the discussions tab, file an issue, or start a chat on discord.
## Community
- [Discord](https://discord.gg/NKYgCBP)
## License
Box2D is developed by Erin Catto, and uses the [MIT license](https://en.wikipedia.org/wiki/MIT_License).
## Sponsorship
Support development of Box2D through [Github Sponsors](https://github.com/sponsors/erincatto)
## Ports, wrappers, and Bindings
- https://github.com/odin-lang/Odin/tree/master/vendor/box2d
- https://github.com/EnokViking/Box2DBeef
- https://github.com/HolyBlackCat/box2cpp

1202
vendor/box2d/box2d.odin vendored Normal file

File diff suppressed because it is too large Load Diff

757
vendor/box2d/collision.odin vendored Normal file
View File

@@ -0,0 +1,757 @@
package vendor_box2d
foreign import lib {
"box2d.lib", // dummy
}
import "core:c"
// The maximum number of vertices on a convex polygon. Changing this affects performance even if you
// don't use more vertices.
maxPolygonVertices :: 8
// Low level ray-cast input data
RayCastInput :: struct {
// Start point of the ray cast
origin: Vec2,
// Translation of the ray cast
translation: Vec2,
// The maximum fraction of the translation to consider, typically 1
maxFraction: f32,
}
// Low level shape cast input in generic form. This allows casting an arbitrary point
// cloud wrap with a radius. For example, a circle is a single point with a non-zero radius.
// A capsule is two points with a non-zero radius. A box is four points with a zero radius.
ShapeCastInput :: struct {
// A point cloud to cast
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
// The number of points
count: i32,
// The radius around the point cloud
radius: f32,
// The translation of the shape cast
translation: Vec2,
// The maximum fraction of the translation to consider, typically 1
maxFraction: f32,
}
// Low level ray-cast or shape-cast output data
CastOutput :: struct {
// The surface normal at the hit point
normal: Vec2,
// The surface hit point
point: Vec2,
// The fraction of the input translation at collision
fraction: f32,
// The number of iterations used
iterations: i32,
// Did the cast hit?
hit: bool,
}
// This holds the mass data computed for a shape.
MassData :: struct {
// The mass of the shape, usually in kilograms.
mass: f32,
// The position of the shape's centroid relative to the shape's origin.
center: Vec2,
// The rotational inertia of the shape about the local origin.
rotationalInertia: f32,
}
// A solid circle
Circle :: struct {
// The local center
center: Vec2,
// The radius
radius: f32,
}
// A solid capsule can be viewed as two semicircles connected
// by a rectangle.
Capsule :: struct {
// Local center of the first semicircle
center1: Vec2,
// Local center of the second semicircle
center2: Vec2,
// The radius of the semicircles
radius: f32,
}
// A solid convex polygon. It is assumed that the interior of the polygon is to
// the left of each edge.
// Polygons have a maximum number of vertices equal to maxPolygonVertices.
// In most cases you should not need many vertices for a convex polygon.
// @warning DO NOT fill this out manually, instead use a helper function like
// b2MakePolygon or b2MakeBox.
Polygon :: struct {
// The polygon vertices
vertices: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
// The outward normal vectors of the polygon sides
normals: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
// The centroid of the polygon
centroid: Vec2,
// The external radius for rounded polygons
radius: f32,
// The number of polygon vertices
count: i32,
}
// A line segment with two-sided collision.
Segment :: struct {
// The first point
point1: Vec2,
// The second point
point2: Vec2,
}
// A smooth line segment with one-sided collision. Only collides on the right side.
// Several of these are generated for a chain shape.
// ghost1 -> point1 -> point2 -> ghost2
SmoothSegment :: struct {
// The tail ghost vertex
ghost1: Vec2,
// The line segment
segment: Segment,
// The head ghost vertex
ghost2: Vec2,
// The owning chain shape index (internal usage only)
chainId: i32,
}
@(link_prefix="b2", default_calling_convention="c")
foreign lib {
// Validate ray cast input data (NaN, etc)
IsValidRay :: proc(#by_ptr input: RayCastInput) -> bool ---
// Make a convex polygon from a convex hull. This will assert if the hull is not valid.
// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull
MakePolygon :: proc(#by_ptr hull: Hull, radius: f32) -> Polygon ---
// Make an offset convex polygon from a convex hull. This will assert if the hull is not valid.
// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull
MakeOffsetPolygon :: proc(#by_ptr hull: Hull, radius: f32, transform: Transform) -> Polygon ---
// Make a square polygon, bypassing the need for a convex hull.
MakeSquare :: proc(h: f32) -> Polygon ---
// Make a box (rectangle) polygon, bypassing the need for a convex hull.
MakeBox :: proc(hx, hy: f32) -> Polygon ---
// Make a rounded box, bypassing the need for a convex hull.
MakeRoundedBox :: proc(hx, hy: f32, radius: f32) -> Polygon ---
// Make an offset box, bypassing the need for a convex hull.
MakeOffsetBox :: proc(hx, hy: f32, center: Vec2, angle: f32) -> Polygon ---
// Transform a polygon. This is useful for transferring a shape from one body to another.
TransformPolygon :: proc(transform: Transform, #by_ptr polygon: Polygon) -> Polygon ---
// Compute mass properties of a circle
ComputeCircleMass :: proc(#by_ptr shape: Circle, density: f32) -> MassData ---
// Compute mass properties of a capsule
ComputeCapsuleMass :: proc(#by_ptr shape: Capsule, density: f32) -> MassData ---
// Compute mass properties of a polygon
ComputePolygonMass :: proc(#by_ptr shape: Polygon, density: f32) -> MassData ---
// Compute the bounding box of a transformed circle
ComputeCircleAABB :: proc(#by_ptr shape: Circle, transform: Transform) -> AABB ---
// Compute the bounding box of a transformed capsule
ComputeCapsuleAABB :: proc(#by_ptr shape: Capsule, transform: Transform) -> AABB ---
// Compute the bounding box of a transformed polygon
ComputePolygonAABB :: proc(#by_ptr shape: Polygon, transform: Transform) -> AABB ---
// Compute the bounding box of a transformed line segment
ComputeSegmentAABB :: proc(#by_ptr shape: Segment, transform: Transform) -> AABB ---
// Test a point for overlap with a circle in local space
PointInCircle :: proc(point: Vec2, #by_ptr shape: Circle) -> bool ---
// Test a point for overlap with a capsule in local space
PointInCapsule :: proc(point: Vec2, #by_ptr shape: Capsule) -> bool ---
// Test a point for overlap with a convex polygon in local space
PointInPolygon :: proc(point: Vec2, #by_ptr shape: Polygon) -> bool ---
// Ray cast versus circle in shape local space. Initial overlap is treated as a miss.
RayCastCircle :: proc(#by_ptr input: RayCastInput, #by_ptr shape: Circle) -> CastOutput ---
// Ray cast versus capsule in shape local space. Initial overlap is treated as a miss.
RayCastCapsule :: proc(#by_ptr input: RayCastInput, #by_ptr shape: Capsule) -> CastOutput ---
// Ray cast versus segment in shape local space. Optionally treat the segment as one-sided with hits from
// the left side being treated as a miss.
RayCastSegment :: proc(#by_ptr input: RayCastInput, #by_ptr shape: Segment, oneSided: bool) -> CastOutput ---
// Ray cast versus polygon in shape local space. Initial overlap is treated as a miss.
RayCastPolygon :: proc(#by_ptr input: RayCastInput, #by_ptr shape: Polygon) -> CastOutput ---
// Shape cast versus a circle. Initial overlap is treated as a miss.
ShapeCastCircle :: proc(#by_ptr input: ShapeCastInput, #by_ptr shape: Circle) -> CastOutput ---
// Shape cast versus a capsule. Initial overlap is treated as a miss.
ShapeCastCapsule :: proc(#by_ptr input: ShapeCastInput, #by_ptr shape: Capsule) -> CastOutput ---
// Shape cast versus a line segment. Initial overlap is treated as a miss.
ShapeCastSegment :: proc(#by_ptr input: ShapeCastInput, #by_ptr shape: Segment) -> CastOutput ---
// Shape cast versus a convex polygon. Initial overlap is treated as a miss.
ShapeCastPolygon :: proc(#by_ptr input: ShapeCastInput, #by_ptr shape: Polygon) -> CastOutput ---
}
// A convex hull. Used to create convex polygons.
// @warning Do not modify these values directly, instead use b2ComputeHull()
Hull :: struct {
// The final points of the hull
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
// The number of points
count: i32,
}
// Compute the convex hull of a set of points. Returns an empty hull if it fails.
// Some failure cases:
// - all points very close together
// - all points on a line
// - less than 3 points
// - more than maxPolygonVertices points
// This welds close points and removes collinear points.
// @warning Do not modify a hull once it has been computed
ComputeHull :: proc "c" (points: []Vec2) -> Hull {
foreign lib {
b2ComputeHull :: proc "c" (points: [^]Vec2, count: i32) -> Hull ---
}
return b2ComputeHull(raw_data(points), i32(len(points)))
}
@(link_prefix="b2", default_calling_convention="c")
foreign lib {
// This determines if a hull is valid. Checks for:
// - convexity
// - collinear points
// This is expensive and should not be called at runtime.
ValidateHull :: proc(#by_ptr hull: Hull) -> bool ---
}
/**
* @defgroup distance Distance
* Functions for computing the distance between shapes.
*
* These are advanced functions you can use to perform distance calculations. There
* are functions for computing the closest points between shapes, doing linear shape casts,
* and doing rotational shape casts. The latter is called time of impact (TOI).
*/
// Result of computing the distance between two line segments
SegmentDistanceResult :: struct {
// The closest point on the first segment
closest1: Vec2,
// The closest point on the second segment
closest2: Vec2,
// The barycentric coordinate on the first segment
fraction1: f32,
// The barycentric coordinate on the second segment
fraction2: f32,
// The squared distance between the closest points
distanceSquared: f32,
}
@(link_prefix="b2", default_calling_convention="c")
foreign lib {
// Compute the distance between two line segments, clamping at the end points if needed.
SegmentDistance :: proc(p1, q1: Vec2, p2, q2: Vec2) -> SegmentDistanceResult ---
}
// A distance proxy is used by the GJK algorithm. It encapsulates any shape.
DistanceProxy :: struct {
// The point cloud
points: [maxPolygonVertices]Vec2 `fmt:"v,count"`,
// The number of points
count: i32,
// The external radius of the point cloud
radius: f32,
}
// Used to warm start b2Distance. Set count to zero on first call or
// use zero initialization.
DistanceCache :: struct {
// The number of stored simplex points
count: u16,
// The cached simplex indices on shape A
indexA: [3]u8 `fmt:"v,count"`,
// The cached simplex indices on shape B
indexB: [3]u8 `fmt:"v,count"`,
}
emptyDistanceCache :: DistanceCache{}
// Input for b2ShapeDistance
DistanceInput :: struct {
// The proxy for shape A
proxyA: DistanceProxy,
// The proxy for shape B
proxyB: DistanceProxy,
// The world transform for shape A
transformA: Transform,
// The world transform for shape B
transformB: Transform,
// Should the proxy radius be considered?
useRadii: bool,
}
// Output for b2ShapeDistance
DistanceOutput :: struct {
pointA: Vec2, // Closest point on shapeA
pointB: Vec2, // Closest point on shapeB
distance: f32, // The final distance, zero if overlapped
iterations: i32, // Number of GJK iterations used
simplexCount: i32, // The number of simplexes stored in the simplex array
}
// Simplex vertex for debugging the GJK algorithm
SimplexVertex :: struct {
wA: Vec2, // support point in proxyA
wB: Vec2, // support point in proxyB
w: Vec2, // wB - wA
a: f32, // barycentric coordinate for closest point
indexA: i32, // wA index
indexB: i32, // wB index
}
// Simplex from the GJK algorithm
Simplex :: struct {
v1, v2, v3: SimplexVertex `fmt:"v,count"`, // vertices
count: i32, // number of valid vertices
}
// Input parameters for b2ShapeCast
ShapeCastPairInput :: struct {
proxyA: DistanceProxy, // The proxy for shape A
proxyB: DistanceProxy, // The proxy for shape B
transformA: Transform, // The world transform for shape A
transformB: Transform, // The world transform for shape B
translationB: Vec2, // The translation of shape B
maxFraction: f32, // The fraction of the translation to consider, typically 1
}
// This describes the motion of a body/shape for TOI computation. Shapes are defined with respect to the body origin,
// which may not coincide with the center of mass. However, to support dynamics we must interpolate the center of mass
// position.
Sweep :: struct {
localCenter: Vec2, // Local center of mass position
c1: Vec2, // Starting center of mass world position
c2: Vec2, // Ending center of mass world position
q1: Rot, // Starting world rotation
q2: Rot, // Ending world rotation
}
// Input parameters for b2TimeOfImpact
TOIInput :: struct {
proxyA: DistanceProxy, // The proxy for shape A
proxyB: DistanceProxy, // The proxy for shape B
sweepA: Sweep, // The movement of shape A
sweepB: Sweep, // The movement of shape B
tMax: f32, // Defines the sweep interval [0, tMax]
}
// Describes the TOI output
TOIState :: enum c.int {
Unknown,
Failed,
Overlapped,
Hit,
Separated,
}
// Output parameters for b2TimeOfImpact.
TOIOutput :: struct {
state: TOIState, // The type of result
t: f32, // The time of the collision
}
// Compute the closest points between two shapes represented as point clouds.
// DistanceCache cache is input/output. On the first call set DistanceCache.count to zero.
// The underlying GJK algorithm may be debugged by passing in debug simplexes and capacity. You may pass in NULL and 0 for these.
ShapeDistance :: proc "c" (cache: ^DistanceCache, #by_ptr input: DistanceInput, simplexes: []Simplex) -> DistanceOutput {
foreign lib {
b2ShapeDistance :: proc "c" (cache: ^DistanceCache, #by_ptr input: DistanceInput, simplexes: [^]Simplex, simplexCapacity: c.int) -> DistanceOutput ---
}
return b2ShapeDistance(cache, input, raw_data(simplexes), i32(len(simplexes)))
}
// Make a proxy for use in GJK and related functions.
MakeProxy :: proc "c" (vertices: []Vec2, radius: f32) -> DistanceProxy {
foreign lib {
b2MakeProxy :: proc "c" (vertices: [^]Vec2, count: i32, radius: f32) -> DistanceProxy ---
}
return b2MakeProxy(raw_data(vertices), i32(len(vertices)), radius)
}
@(link_prefix="b2", default_calling_convention="c")
foreign lib {
// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction.
ShapeCast :: proc(#by_ptr input: ShapeCastPairInput) -> CastOutput ---
// Evaluate the transform sweep at a specific time.
GetSweepTransform :: proc(#by_ptr sweep: Sweep, time: f32) -> Transform ---
// Compute the upper bound on time before two shapes penetrate. Time is represented as
// a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate,
// non-tunneling collisions. If you change the time interval, you should call this function
// again.
TimeOfImpact :: proc(#by_ptr input: TOIInput) -> TOIOutput ---
}
/**
* @defgroup collision Collision
* @brief Functions for colliding pairs of shapes
*/
// A manifold point is a contact point belonging to a contact
// manifold. It holds details related to the geometry and dynamics
// of the contact points.
ManifoldPoint :: struct {
// Location of the contact point in world space. Subject to precision loss at large coordinates.
// @note Should only be used for debugging.
point: Vec2,
// Location of the contact point relative to bodyA's origin in world space
// @note When used internally to the Box2D solver, these are relative to the center of mass.
anchorA: Vec2,
// Location of the contact point relative to bodyB's origin in world space
anchorB: Vec2,
// The separation of the contact point, negative if penetrating
separation: f32,
// The impulse along the manifold normal vector.
normalImpulse: f32,
// The friction impulse
tangentImpulse: f32,
// The maximum normal impulse applied during sub-stepping
// todo not sure this is needed
maxNormalImpulse: f32,
// Relative normal velocity pre-solve. Used for hit events. If the normal impulse is
// zero then there was no hit. Negative means shapes are approaching.
normalVelocity: f32,
// Uniquely identifies a contact point between two shapes
id: u16,
// Did this contact point exist the previous step?
persisted: bool,
}
// A contact manifold describes the contact points between colliding shapes
Manifold :: struct {
// The manifold points, up to two are possible in 2D
points: [2]ManifoldPoint,
// The unit normal vector in world space, points from shape A to bodyB
normal: Vec2,
// The number of contacts points, will be 0, 1, or 2
pointCount: i32,
}
@(link_prefix="b2", default_calling_convention="c")
foreign lib {
// Compute the contact manifold between two circles
CollideCircles :: proc(#by_ptr circleA: Circle, xfA: Transform, #by_ptr circleB: Circle, xfB: Transform) -> Manifold ---
// Compute the contact manifold between a capsule and circle
CollideCapsuleAndCircle :: proc(#by_ptr capsuleA: Capsule, xfA: Transform, #by_ptr circleB: Circle, xfB: Transform) -> Manifold ---
// Compute the contact manifold between an segment and a circle
CollideSegmentAndCircle :: proc(#by_ptr segmentA: Segment, xfA: Transform, #by_ptr circleB: Circle, xfB: Transform) -> Manifold ---
// Compute the contact manifold between a polygon and a circle
CollidePolygonAndCircle :: proc(#by_ptr polygonA: Polygon, xfA: Transform, #by_ptr circleB: Circle, xfB: Transform) -> Manifold ---
// Compute the contact manifold between a capsule and circle
CollideCapsules :: proc(#by_ptr capsuleA: Capsule, xfA: Transform, #by_ptr capsuleB: Capsule, xfB: Transform) -> Manifold ---
// Compute the contact manifold between an segment and a capsule
CollideSegmentAndCapsule :: proc(#by_ptr segmentA: Segment, xfA: Transform, #by_ptr capsuleB: Capsule, xfB: Transform) -> Manifold ---
// Compute the contact manifold between a polygon and capsule
CollidePolygonAndCapsule :: proc(#by_ptr polygonA: Polygon, xfA: Transform, #by_ptr capsuleB: Capsule, xfB: Transform) -> Manifold ---
// Compute the contact manifold between two polygons
CollidePolygons :: proc(#by_ptr polygonA: Polygon, xfA: Transform, #by_ptr polygonB: Polygon, xfB: Transform) -> Manifold ---
// Compute the contact manifold between an segment and a polygon
CollideSegmentAndPolygon :: proc(#by_ptr segmentA: Segment, xfA: Transform, #by_ptr polygonB: Polygon, xfB: Transform) -> Manifold ---
// Compute the contact manifold between a smooth segment and a circle
CollideSmoothSegmentAndCircle :: proc(#by_ptr smoothSegmentA: SmoothSegment, xfA: Transform, #by_ptr circleB: Circle, xfB: Transform) -> Manifold ---
// Compute the contact manifold between an segment and a capsule
CollideSmoothSegmentAndCapsule :: proc(#by_ptr smoothSegmentA: SmoothSegment, xfA: Transform, #by_ptr capsuleB: Capsule, xfB: Transform, cache: ^DistanceCache) -> Manifold ---
// Compute the contact manifold between a smooth segment and a rounded polygon
CollideSmoothSegmentAndPolygon :: proc(#by_ptr smoothSegmentA: SmoothSegment, xfA: Transform, #by_ptr polygonB: Polygon, xfB: Transform, cache: ^DistanceCache) -> Manifold ---
}
/**
* @defgroup tree Dynamic Tree
* The dynamic tree is a binary AABB tree to organize and query large numbers of geometric objects
*
* Box2D uses the dynamic tree internally to sort collision shapes into a binary bounding volume hierarchy.
* This data structure may have uses in games for organizing other geometry data and may be used independently
* of Box2D rigid body simulation.
*
* A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
* A dynamic tree arranges data in a binary tree to accelerate
* queries such as AABB queries and ray casts. Leaf nodes are proxies
* with an AABB. These are used to hold a user collision object, such as a reference to a b2Shape.
* Nodes are pooled and relocatable, so I use node indices rather than pointers.
* The dynamic tree is made available for advanced users that would like to use it to organize
* spatial game data besides rigid bodies.
*
* @note This is an advanced feature and normally not used by applications directly.
*/
// The default category bit for a tree proxy. Used for collision filtering.
defaultCategoryBits :: 0x00000001
// Convenience mask bits to use when you don't need collision filtering and just want
// all results.
defaultMaskBits :: 0xFFFFFFFF
// A node in the dynamic tree. This is private data placed here for performance reasons.
// 16 + 16 + 8 + pad(8)
TreeNode :: struct {
// The node bounding box
aabb: AABB, // 16
// Category bits for collision filtering
categoryBits: u32, // 4
using _: struct #raw_union {
// The node parent index
parent: i32,
// The node freelist next index
next: i32,
}, // 4
// Child 1 index
child1: i32, // 4
// Child 2 index
child2: i32, // 4
// User data
// todo could be union with child index
userData: i32, // 4
// Leaf = 0, free node = -1
height: i16, // 2
// Has the AABB been enlarged?
enlarged: bool, // 1
// Padding for clarity
pad: [9]byte,
}
// The dynamic tree structure. This should be considered private data.
// It is placed here for performance reasons.
DynamicTree :: struct {
// The tree nodes
nodes: [^]TreeNode `fmt"v,nodeCount"`,
// The root index
root: i32,
// The number of nodes
nodeCount: i32,
// The allocated node space
nodeCapacity: i32,
// Node free list
freeList: i32,
// Number of proxies created
proxyCount: i32,
// Leaf indices for rebuild
leafIndices: [^]i32,
// Leaf bounding boxes for rebuild
leafBoxes: [^]AABB,
// Leaf bounding box centers for rebuild
leafCenters: [^]Vec2,
// Bins for sorting during rebuild
binIndices: [^]i32,
// Allocated space for rebuilding
rebuildCapacity: i32,
}
// This function receives proxies found in the AABB query.
// @return true if the query should continue
TreeQueryCallbackFcn :: #type proc "c" (proxyId: i32, userData: i32, ctx: rawptr) -> bool
// This function receives clipped ray-cast input for a proxy. The function
// returns the new ray fraction.
// - return a value of 0 to terminate the ray-cast
// - return a value less than input->maxFraction to clip the ray
// - return a value of input->maxFraction to continue the ray cast without clipping
TreeShapeCastCallbackFcn :: #type proc "c" (#by_ptr input: ShapeCastInput, proxyId: i32, userData: i32, ctx: rawptr) -> f32
// This function receives clipped raycast input for a proxy. The function
// returns the new ray fraction.
// - return a value of 0 to terminate the ray cast
// - return a value less than input->maxFraction to clip the ray
// - return a value of input->maxFraction to continue the ray cast without clipping
TreeRayCastCallbackFcn :: #type proc "c" (#by_ptr input: RayCastInput, proxyId: i32, userData: i32, ctx: rawptr) -> f32
@(link_prefix="b2", default_calling_convention="c")
foreign lib {
// Constructing the tree initializes the node pool.
DynamicTree_Create :: proc() -> DynamicTree ---
// Destroy the tree, freeing the node pool.
DynamicTree_Destroy :: proc(tree: ^DynamicTree) ---
// Create a proxy. Provide an AABB and a userData value.
DynamicTree_CreateProxy :: proc(tree: ^DynamicTree, aabb: AABB, categoryBits: u32, userData: i32) -> i32 ---
// Destroy a proxy. This asserts if the id is invalid.
DynamicTree_DestroyProxy :: proc(tree: ^DynamicTree, proxyId: i32) ---
// Move a proxy to a new AABB by removing and reinserting into the tree.
DynamicTree_MoveProxy :: proc(tree: ^DynamicTree, proxyId: i32, aabb: AABB) ---
// Enlarge a proxy and enlarge ancestors as necessary.
DynamicTree_EnlargeProxy :: proc(tree: ^DynamicTree, proxyId: i32, aabb: AABB) ---
// Query an AABB for overlapping proxies. The callback class
// is called for each proxy that overlaps the supplied AABB.
DynamicTree_Query :: proc(#by_ptr tree: DynamicTree, aabb: AABB, maskBits: u32, callback: TreeQueryCallbackFcn, ctx: rawptr) ---
// Ray-cast against the proxies in the tree. This relies on the callback
// to perform a exact ray-cast in the case were the proxy contains a shape.
// The callback also performs the any collision filtering. This has performance
// roughly equal to k * log(n), where k is the number of collisions and n is the
// number of proxies in the tree.
// Bit-wise filtering using mask bits can greatly improve performance in some scenarios.
// @param tree the dynamic tree to ray cast
// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1)
// @param maskBits filter bits: `bool accept = (maskBits & node->categoryBits) != 0 ---`
// @param callback a callback class that is called for each proxy that is hit by the ray
// @param context user context that is passed to the callback
DynamicTree_RayCast :: proc(#by_ptr tree: DynamicTree, #by_ptr input: RayCastInput, maskBits: u32, callback: TreeRayCastCallbackFcn, ctx: rawptr) ---
// Ray-cast against the proxies in the tree. This relies on the callback
// to perform a exact ray-cast in the case were the proxy contains a shape.
// The callback also performs the any collision filtering. This has performance
// roughly equal to k * log(n), where k is the number of collisions and n is the
// number of proxies in the tree.
// @param tree the dynamic tree to ray cast
// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
// @param maskBits filter bits: `bool accept = (maskBits & node->categoryBits) != 0 ---`
// @param callback a callback class that is called for each proxy that is hit by the shape
// @param context user context that is passed to the callback
DynamicTree_ShapeCast :: proc(#by_ptr tree: DynamicTree, #by_ptr input: ShapeCastInput, maskBits: u32, callback: TreeShapeCastCallbackFcn, ctx: rawptr) ---
// Validate this tree. For testing.
DynamicTree_Validate :: proc(#by_ptr tree: DynamicTree) ---
// Compute the height of the binary tree in O(N) time. Should not be
// called often.
DynamicTree_GetHeight :: proc(#by_ptr tree: DynamicTree) -> c.int ---
// Get the maximum balance of the tree. The balance is the difference in height of the two children of a node.
DynamicTree_GetMaxBalance :: proc(#by_ptr tree: DynamicTree) -> c.int ---
// Get the ratio of the sum of the node areas to the root area.
DynamicTree_GetAreaRatio :: proc(#by_ptr tree: DynamicTree) -> f32 ---
// Build an optimal tree. Very expensive. For testing.
DynamicTree_RebuildBottomUp :: proc(tree: ^DynamicTree) ---
// Get the number of proxies created
DynamicTree_GetProxyCount :: proc(#by_ptr tree: DynamicTree) -> c.int ---
// Rebuild the tree while retaining subtrees that haven't changed. Returns the number of boxes sorted.
DynamicTree_Rebuild :: proc(tree: ^DynamicTree, fullBuild: bool) -> c.int ---
// Shift the world origin. Useful for large worlds.
// The shift formula is: position -= newOrigin
// @param tree the tree to shift
// @param newOrigin the new origin with respect to the old origin
DynamicTree_ShiftOrigin :: proc(tree: ^DynamicTree, newOrigin: Vec2) ---
// Get the number of bytes used by this tree
DynamicTree_GetByteCount :: proc(#by_ptr tree: DynamicTree) -> c.int ---
}
// Get proxy user data
// @return the proxy user data or 0 if the id is invalid
DynamicTree_GetUserData :: proc "contextless" (tree: DynamicTree, proxyId: i32) -> i32 {
return tree.nodes[proxyId].userData
}
// Get the AABB of a proxy
DynamicTree_GetAABB :: proc "contextless" (tree: DynamicTree, proxyId: i32) -> AABB {
return tree.nodes[proxyId].aabb
}

77
vendor/box2d/id.odin vendored Normal file
View File

@@ -0,0 +1,77 @@
package vendor_box2d
/**
* @defgroup id Ids
* These ids serve as handles to internal Box2D objects.
* These should be considered opaque data and passed by value.
* Include this header if you need the id types and not the whole Box2D API.
* All ids are considered null if initialized to zero.
*
* For example in C++:
*
* @code{.cxx}
* b2WorldId worldId = {};
* @endcode
*
* Or in C:
*
* @code{.c}
* b2WorldId worldId = {0};
* @endcode
*
* These are both considered null.
*
* @warning Do not use the internals of these ids. They are subject to change. Ids should be treated as opaque objects.
* @warning You should use ids to access objects in Box2D. Do not access files within the src folder. Such usage is unsupported.
*/
/// World id references a world instance. This should be treated as an opaque handle.
WorldId :: struct {
index1: u16,
revision: u16,
}
/// Body id references a body instance. This should be treated as an opaque handle.
BodyId :: struct {
index1: i32,
world0: u16,
revision: u16,
}
/// Shape id references a shape instance. This should be treated as an opaque handle.
ShapeId :: struct {
index1: i32,
world0: u16,
revision: u16,
}
/// Joint id references a joint instance. This should be treated as an opaque handle.
JointId :: struct {
index1: i32,
world0: u16,
revision: u16,
}
/// Chain id references a chain instances. This should be treated as an opaque handle.
ChainId :: struct {
index1: i32,
world0: u16,
revision: u16,
}
/// Use these to make your identifiers null.
/// You may also use zero initialization to get null.
nullWorldId :: WorldId{}
nullBodyId :: BodyId{}
nullShapeId :: ShapeId{}
nullJointId :: JointId{}
nullChainId :: ChainId{}
/// Macro to determine if any id is null.
IS_NULL :: proc "c" (id: $T) -> bool { return id.index1 == 0 }
/// Macro to determine if any id is non-null.
IS_NON_NULL :: proc "c" (id: $T) -> bool { return id.index1 != 0 }
/// Compare two ids for equality. Doesn't work for b2WorldId.
ID_EQUALS :: proc "c" (id1, id2: $T) -> bool { return id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.revision == id2.revision }

460
vendor/box2d/math_functions.odin vendored Normal file
View File

@@ -0,0 +1,460 @@
package vendor_box2d
import "core:c"
import "core:math"
pi :: 3.14159265359
Vec2 :: [2]f32
Rot :: struct {
c, s: f32, // cosine and sine
}
Transform :: struct {
p: Vec2,
q: Rot,
}
Mat22 :: matrix[2, 2]f32
AABB :: struct {
lowerBound: Vec2,
upperBound: Vec2,
}
Vec2_zero :: Vec2{0, 0}
Rot_identity :: Rot{1, 0}
Transform_identity :: Transform{{0, 0}, {1, 0}}
Mat22_zero :: Mat22{0, 0, 0, 0}
// @return the minimum of two floats
MinFloat :: proc "c" (a, b: f32) -> f32 {
return min(a, b)
}
// @return the maximum of two floats
MaxFloat :: proc "c" (a, b: f32) -> f32 {
return max(a, b)
}
// @return the absolute value of a float
AbsFloat :: proc "c" (a: f32) -> f32 {
return abs(a)
}
// @return a f32 clamped between a lower and upper bound
ClampFloat :: proc "c" (a, lower, upper: f32) -> f32 {
return clamp(a, lower, upper)
}
// @return the minimum of two integers
MinInt :: proc "c" (a, b: c.int) -> c.int {
return min(a, b)
}
// @return the maximum of two integers
MaxInt :: proc "c" (a, b: c.int) -> c.int {
return max(a, b)
}
// @return the absolute value of an integer
AbsInt :: proc "c" (a: c.int) -> c.int {
return abs(a)
}
// @return an integer clamped between a lower and upper bound
ClampInt :: proc "c" (a, lower, upper: c.int) -> c.int {
return clamp(a, lower, upper)
}
// Vector dot product
Dot :: proc "c" (a, b: Vec2) -> f32 {
return a.x * b.x + a.y * b.y
}
// Vector cross product. In 2D this yields a scalar.
Cross :: proc "c" (a, b: Vec2) -> f32 {
return a.x * b.y - a.y * b.x
}
// Perform the cross product on a vector and a scalar. In 2D this produces a vector.
CrossVS :: proc "c" (v: Vec2, s: f32) -> Vec2 {
return {s * v.y, -s * v.x}
}
// Perform the cross product on a scalar and a vector. In 2D this produces a vector.
CrossSV :: proc "c" (s: f32, v: Vec2) -> Vec2 {
return {-s * v.y, s * v.x}
}
// Get a left pointing perpendicular vector. Equivalent to b2CrossSV(1, v)
LeftPerp :: proc "c" (v: Vec2) -> Vec2 {
return {-v.y, v.x}
}
// Get a right pointing perpendicular vector. Equivalent to b2CrossVS(v, 1)
RightPerp :: proc "c" (v: Vec2) -> Vec2 {
return {v.y, -v.x}
}
// Vector addition
Add :: proc "c" (a, b: Vec2) -> Vec2 {
return a + b
}
// Vector subtraction
Sub :: proc "c" (a, b: Vec2) -> Vec2 {
return a - b
}
// Vector negation
Neg :: proc "c" (a: Vec2) -> Vec2 {
return -a
}
// Vector linear interpolation
// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
Lerp :: proc "c" (a, b: Vec2, t: f32) -> Vec2 {
return {(1 - t) * a.x + t * b.x, (1 - t) * a.y + t * b.y}
}
// Component-wise multiplication
Mul :: proc "c" (a, b: Vec2) -> Vec2 {
return a * b
}
// Multiply a scalar and vector
MulSV :: proc "c" (s: f32, v: Vec2) -> Vec2 {
return s * v
}
// a + s * b
MulAdd :: proc "c" (a: Vec2, s: f32, b: Vec2) -> Vec2 {
return a + s * b
}
// a - s * b
MulSub :: proc "c" (a: Vec2, s: f32, b: Vec2) -> Vec2 {
return a - s * b
}
// Component-wise absolute vector
Abs :: proc "c" (a: Vec2) -> (b: Vec2) {
b.x = AbsFloat(a.x)
b.y = AbsFloat(a.y)
return
}
// Component-wise minimum vector
Min :: proc "c" (a, b: Vec2) -> (c: Vec2) {
c.x = MinFloat(a.x, b.x)
c.y = MinFloat(a.y, b.y)
return
}
// Component-wise maximum vector
Max :: proc "c" (a, b: Vec2) -> (c: Vec2) {
c.x = MaxFloat(a.x, b.x)
c.y = MaxFloat(a.y, b.y)
return
}
// Component-wise clamp vector v into the range [a, b]
Clamp :: proc "c" (v: Vec2, a, b: Vec2) -> (c: Vec2) {
c.x = ClampFloat(v.x, a.x, b.x)
c.y = ClampFloat(v.y, a.y, b.y)
return
}
// Get the length of this vector (the norm)
Length :: proc "c" (v: Vec2) -> f32 {
return math.sqrt(v.x * v.x + v.y * v.y)
}
// Get the length squared of this vector
LengthSquared :: proc "c" (v: Vec2) -> f32 {
return v.x * v.x + v.y * v.y
}
// Get the distance between two points
Distance :: proc "c" (a, b: Vec2) -> f32 {
dx := b.x - a.x
dy := b.y - a.y
return math.sqrt(dx * dx + dy * dy)
}
// Get the distance squared between points
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
MakeRot :: proc "c" (angle: f32) -> Rot {
// todo determinism
return {math.cos(angle), math.sin(angle)}
}
// Normalize rotation
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}
}
// Is this rotation normalized?
IsNormalized :: proc "c" (q: Rot) -> bool {
// larger tolerance due to failure on mingw 32-bit
qq := q.s * q.s + q.c * q.c
return 1.0 - 0.0006 < qq && qq < 1 + 0.0006
}
// Normalized linear interpolation
// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
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
// @param q1 initial rotation
// @param deltaAngle the angular displacement in radians
IntegrateRotation :: proc "c" (q1: Rot, deltaAngle: f32) -> Rot {
// dc/dt = -omega * sin(t)
// ds/dt = omega * cos(t)
// c2 = c1 - omega * h * s1
// s2 = s1 + omega * h * c1
q2 := Rot{q1.c - deltaAngle * q1.s, q1.s + deltaAngle * q1.c}
mag := math.sqrt(q2.s * q2.s + q2.c * q2.c)
invMag := f32(mag > 0.0 ? 1 / mag : 0.0)
return {q2.c * invMag, q2.s * invMag}
}
// Compute the angular velocity necessary to rotate between two rotations over a give time
// @param q1 initial rotation
// @param q2 final rotation
// @param inv_h inverse time step
ComputeAngularVelocity :: proc "c" (q1: Rot, q2: Rot, inv_h: f32) -> f32 {
// ds/dt = omega * cos(t)
// dc/dt = -omega * sin(t)
// s2 = s1 + omega * h * c1
// c2 = c1 - omega * h * s1
// omega * h * s1 = c1 - c2
// omega * h * c1 = s2 - s1
// omega * h = (c1 - c2) * s1 + (s2 - s1) * c1
// omega * h = s1 * c1 - c2 * s1 + s2 * c1 - s1 * c1
// omega * h = s2 * c1 - c2 * s1 = sin(a2 - a1) ~= a2 - a1 for small delta
omega := inv_h * (q2.s * q1.c - q2.c * q1.s)
return omega
}
// Get the angle in radians in the range [-pi, pi]
Rot_GetAngle :: proc "c" (q: Rot) -> f32 {
// todo determinism
return math.atan2(q.s, q.c)
}
// Get the x-axis
Rot_GetXAxis :: proc "c" (q: Rot) -> Vec2 {
return {q.c, q.s}
}
// Get the y-axis
Rot_GetYAxis :: proc "c" (q: Rot) -> Vec2 {
return {-q.s, q.c}
}
// Multiply two rotations: q * r
MulRot :: proc "c" (q, r: Rot) -> (qr: Rot) {
// [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
// [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
// s(q + r) = qs * rc + qc * rs
// c(q + r) = qc * rc - qs * rs
qr.s = q.s * r.c + q.c * r.s
qr.c = q.c * r.c - q.s * r.s
return
}
// Transpose multiply two rotations: qT * r
InvMulRot :: proc "c" (q, r: Rot) -> (qr: Rot) {
// [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
// [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
// s(q - r) = qc * rs - qs * rc
// c(q - r) = qc * rc + qs * rs
qr.s = q.c * r.s - q.s * r.c
qr.c = q.c * r.c + q.s * r.s
return
}
// relative angle between b and a (rot_b * inv(rot_a))
RelativeAngle :: proc "c" (b, a: Rot) -> f32 {
// sin(b - a) = bs * ac - bc * as
// cos(b - a) = bc * ac + bs * as
s := b.s * a.c - b.c * a.s
c := b.c * a.c + b.s * a.s
return math.atan2(s, c)
}
// Convert an angle in the range [-2*pi, 2*pi] into the range [-pi, pi]
UnwindAngle :: proc "c" (angle: f32) -> f32 {
if angle < -pi {
return angle + 2.0 * pi
} else if angle > pi {
return angle - 2.0 * pi
}
return angle
}
// Rotate a vector
RotateVector :: proc "c" (q: Rot, v: Vec2) -> Vec2 {
return {q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y}
}
// Inverse rotate a vector
InvRotateVector :: proc "c" (q: Rot, v: Vec2) -> Vec2 {
return {q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y}
}
// Transform a point (e.g. local space to world space)
TransformPoint :: proc "c" (t: Transform, p: Vec2) -> Vec2 {
x := (t.q.c * p.x - t.q.s * p.y) + t.p.x
y := (t.q.s * p.x + t.q.c * p.y) + t.p.y
return {x, y}
}
// Inverse transform a point (e.g. world space to local space)
InvTransformPoint :: proc "c" (t: Transform, p: Vec2) -> Vec2 {
vx := p.x - t.p.x
vy := p.y - t.p.y
return {t.q.c * vx + t.q.s * vy, -t.q.s * vx + t.q.c * vy}
}
// 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
MulTransforms :: proc "c" (A, B: Transform) -> (C: Transform) {
C.q = MulRot(A.q, B.q)
C.p = RotateVector(A.q, B.p) + A.p
return
}
// v2 = A.q' * (B.q * v1 + B.p - A.p)
// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
InvMulTransforms :: proc "c" (A, B: Transform) -> (C: Transform) {
C.q = InvMulRot(A.q, B.q)
C.p = InvRotateVector(A.q, B.p-A.p)
return
}
// Multiply a 2-by-2 matrix times a 2D vector
MulMV :: proc "c" (A: Mat22, v: Vec2) -> Vec2 {
return A * v
}
// Get the inverse of a 2-by-2 matrix
GetInverse22 :: proc "c" (A: Mat22) -> Mat22 {
a := A[0, 0]
b := A[0, 1]
c := A[1, 0]
d := A[1, 1]
det := a * d - b * c
if det != 0.0 {
det = 1 / det
}
return Mat22{
det * d, -det * b,
-det * c, det * a,
}
}
// Solve A * x = b, where b is a column vector. This is more efficient
// than computing the inverse in one-shot cases.
Solve22 :: proc "c" (A: Mat22, b: Vec2) -> Vec2 {
a11 := A[0, 0]
a12 := A[0, 1]
a21 := A[1, 0]
a22 := A[1, 1]
det := a11 * a22 - a12 * a21
if det != 0.0 {
det = 1 / det
}
return {det * (a22 * b.x - a12 * b.y), det * (a11 * b.y - a21 * b.x)}
}
// Does a fully contain b
AABB_Contains :: proc "c" (a, b: AABB) -> bool {
(a.lowerBound.x <= b.lowerBound.x) or_return
(a.lowerBound.y <= b.lowerBound.y) or_return
(b.upperBound.x <= a.upperBound.x) or_return
(b.upperBound.y <= a.upperBound.y) or_return
return true
}
// Get the center of the AABB.
AABB_Center :: proc "c" (a: AABB) -> Vec2 {
return {0.5 * (a.lowerBound.x + a.upperBound.x), 0.5 * (a.lowerBound.y + a.upperBound.y)}
}
// Get the extents of the AABB (half-widths).
AABB_Extents :: proc "c" (a: AABB) -> Vec2 {
return {0.5 * (a.upperBound.x - a.lowerBound.x), 0.5 * (a.upperBound.y - a.lowerBound.y)}
}
// Union of two AABBs
AABB_Union :: proc "c" (a, b: AABB) -> (c: AABB) {
c.lowerBound.x = MinFloat(a.lowerBound.x, b.lowerBound.x)
c.lowerBound.y = MinFloat(a.lowerBound.y, b.lowerBound.y)
c.upperBound.x = MaxFloat(a.upperBound.x, b.upperBound.x)
c.upperBound.y = MaxFloat(a.upperBound.y, b.upperBound.y)
return
}
Float_IsValid :: proc "c" (a: f32) -> bool {
math.is_nan(a) or_return
math.is_inf(a) or_return
return true
}
Vec2_IsValid :: proc "c" (v: Vec2) -> bool {
(math.is_nan(v.x) || math.is_nan(v.y)) or_return
(math.is_inf(v.x) || math.is_inf(v.y)) or_return
return true
}
Rot_IsValid :: proc "c" (q: Rot) -> bool {
(math.is_nan(q.s) || math.is_nan(q.c)) or_return
(math.is_inf(q.s) || math.is_inf(q.c)) or_return
return IsNormalized(q)
}
Normalize :: proc "c" (v: Vec2) -> Vec2 {
length := Length(v)
if length < 1e-23 {
return Vec2_zero
}
invLength := 1 / length
return invLength * v
}
NormalizeChecked :: proc "odin" (v: Vec2) -> Vec2 {
length := Length(v)
if length < 1e-23 {
panic("zero-length Vec2")
}
invLength := 1 / length
return invLength * v
}
GetLengthAndNormalize :: proc "c" (v: Vec2) -> (length: f32, vn: Vec2) {
length = Length(v)
if length < 1e-23 {
return
}
invLength := 1 / length
vn = invLength * v
return
}

1231
vendor/box2d/types.odin vendored Normal file

File diff suppressed because it is too large Load Diff