add bindings

This commit is contained in:
2026-06-09 17:36:38 +02:00
commit 8425f05116
19 changed files with 5694 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
build
recovery
BeefSpace_user.toml
+3
View File
@@ -0,0 +1,3 @@
[submodule "box2d"]
path = box2d
url = https://github.com/erincatto/box2d.git
+70
View File
@@ -0,0 +1,70 @@
FileVersion = 1
[Project]
Name = "Box2D"
TargetType = "BeefLib"
StartupObject = "Box2D.Program"
[Dependencies]
corlib = "*"
"CxxBuildTool.git" = {Git = "https://git.unicon-gmbh.de/Rune/CxxBuildTool.git"}
[Configs.Debug.Win32]
LibPaths = ["$(BuildDir)/src/box2d.lib"]
[Configs.Debug.Win64]
LibPaths = ["$(BuildDir)/src/box2d.lib"]
[Configs.Debug.Linux32]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Debug.Linux64]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Debug.macOS]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Release.Win32]
LibPaths = ["$(BuildDir)/src/box2d.lib"]
[Configs.Release.Win64]
LibPaths = ["$(BuildDir)/src/box2d.lib"]
[Configs.Release.Linux32]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Release.Linux64]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Release.macOS]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Paranoid.Win32]
LibPaths = ["$(BuildDir)/src/box2d.lib"]
[Configs.Paranoid.Win64]
LibPaths = ["$(BuildDir)/src/box2d.lib"]
[Configs.Paranoid.Linux32]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Paranoid.Linux64]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Paranoid.macOS]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Test.Win32]
LibPaths = ["$(BuildDir)/src/box2d.lib"]
[Configs.Test.Win64]
LibPaths = ["$(BuildDir)/src/box2d.lib"]
[Configs.Test.Linux32]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Test.Linux64]
LibPaths = ["$(BuildDir)/src/box2d.a"]
[Configs.Test.macOS]
LibPaths = ["$(BuildDir)/src/box2d.a"]
+9
View File
@@ -0,0 +1,9 @@
FileVersion = 1
ExtraPlatforms = ["Linux32", "Linux64", "macOS"]
[Workspace]
StartupProject = "Box2D"
[Projects]
Box2D = {Path = "."}
"CxxBuildTool.git" = {Git = "https://git.unicon-gmbh.de/Rune/CxxBuildTool.git"}
+6
View File
@@ -0,0 +1,6 @@
FileVersion = 1
[Locks."CxxBuildTool.git".Git]
URL = "https://git.unicon-gmbh.de/Rune/CxxBuildTool.git"
Tag = ""
Hash = "b64a6221b8cb235a5e040c8597365dabeef849ca"
+9
View File
@@ -0,0 +1,9 @@
FileVersion = 1
[Project]
Name = "Box2D.Setup"
StartupObject = "Box2D.Setup.Program"
[Dependencies]
corlib = "*"
"Cpp2Beef.git" = {Git = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git"}
+8
View File
@@ -0,0 +1,8 @@
FileVersion = 1
[Workspace]
StartupProject = "Box2D.Setup"
[Projects]
"Box2D.Setup" = {Path = "."}
"Cpp2Beef.git" = {Git = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git"}
+11
View File
@@ -0,0 +1,11 @@
FileVersion = 1
[Locks."Clang-C.git".Git]
URL = "https://git.unicon-gmbh.de/BeefBindings/Clang-C.git"
Tag = ""
Hash = "86db0167f15d08a63a91a19e46f983a5511bac1a"
[Locks."Cpp2Beef.git".Git]
URL = "https://git.unicon-gmbh.de/Rune/Cpp2Beef.git"
Tag = ""
Hash = "91ddcd4f79cf6df28adff5abfc59cbdc489c7deb"
+7
View File
@@ -0,0 +1,7 @@
#include <box2d/base.h>
#include <box2d/box2d.h>
#include <box2d/collision.h>
#include <box2d/constants.h>
#include <box2d/id.h>
#include <box2d/math_functions.h>
#include <box2d/types.h>
+223
View File
@@ -0,0 +1,223 @@
using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
using Cpp2Beef;
using LibClang;
namespace Box2D.Setup;
class Box2DGenerator : Cpp2BeefGenerator, this(Span<char8*> args)
{
protected override Span<char8*> Args => args;
protected override Flags Flags => .None;
Dictionary<String, StreamWriter> writers = new .() ~ DeleteDictionaryAndKeysAndValues!(_);
protected override StreamWriter GetWriterForHeader(StringView header)
{
if (!header.Contains("include/box2d") && !header.Contains(@"include\box2d"))
return null;
let filename = Path.GetFileNameWithoutExtension(header, ..scope .(64));
if (writers.TryAdd(filename, let keyPtr, let valuePtr))
{
*keyPtr = new .(filename);
String outFilename = scope .(64);
outFilename.Append("../src/");
UpperSnakeCase2PascalCase(filename, outFilename);
outFilename.Append(".bf");
*valuePtr = new .()..Create(outFilename)..Write("""
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace Box2D;
""");
}
return *valuePtr;
}
protected override Block GetCursorBlock(CXCursor cursor)
{
if (cursor.kind == .FunctionDecl && GetCursorSpelling!(cursor).StartsWith("b2"))
return .CustomBlock("Box2D");
return base.GetCursorBlock(cursor);
}
protected override void HandleCursor(CXCursor cursor)
{
switch (cursor.kind)
{
case .StructDecl when GetFilePath!(fileInfo.file).EndsWith("math_functions.h"):
base.HandleCursor(cursor);
str.Append("\n\tpublic this(");
bool comma = false;
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
{
if (cursor.kind != .FieldDecl) return .Continue;
(Self self, bool* comma) = *(.)client_data;
if (*comma) self.str.Append(", ");
*comma = true;
self.WriteTypeAndName(cursor, Clang.GetCursorType(cursor));
return .Continue;
}, &(this, &comma));
str.Append(") { ");
Clang.VisitChildren(cursor, (cursor, parent, client_data) =>
{
if (cursor.kind != .FieldDecl) return .Continue;
Self self = *(.)client_data;
self.str.Append("this.", GetCursorSpelling!(cursor), " = ", GetCursorSpelling!(cursor), "; ");
return .Continue;
}, &(this, default(void)));
str.Append('}');
case .MacroDefinition:
let spelling = GetCursorSpelling!(cursor);
if (spelling == "B2_BREAKPOINT" || spelling == "B2_API" || spelling == "B2_INLINE" || spelling == "B2_ID_INLINE" || spelling == "B2_ZERO_INIT" || spelling == "B2_NULL_ID")
return;
fallthrough;
default:
if (_ == .VarDecl && GetCursorSpelling!(cursor) == "b2_emptySimplexCache")
return;
base.HandleCursor(cursor);
}
}
List<String> functionNonPtrs = new .(8) ~ DeleteContainerAndItems!(_);
protected override void TypeAlias(CXCursor cursor)
{
if (cursor.kind == .TypedefDecl)
{
CXType type = Clang.GetTypedefDeclUnderlyingType(cursor);
if (type.kind == .FunctionProto || type.kind == .FunctionNoProto)
{
functionNonPtrs.Add(new .(GetCursorSpelling!(cursor)));
WriteCustomAttributes(cursor);
AccessSpecifier(cursor);
str.Append("function ");
WriteTypeAndName(cursor, Clang.GetResultType(type));
WriteFunctionProtoParams(type, ScopeTokenize!(cursor, unit));
str.Append(';');
return;
}
}
base.TypeAlias(cursor);
}
protected override void Type(CXType type, TypeParamMode paramMode = .None)
{
if (type.kind == .Pointer)
{
let pointee = Clang.GetPointeeType(type);
if (paramMode == .OutParam) str.Append("out ");
Type(pointee);
if (functionNonPtrs.ContainsAlt(GetTypeSpelling!(pointee)))
return;
if (paramMode != .OutParam && pointee.kind != .FunctionProto && pointee.kind != .FunctionNoProto)
str.Append('*');
return;
}
base.Type(type, paramMode);
}
protected override void GetNameInBindings(CXCursor cursor, String outString)
{
gnib: switch (cursor.kind)
{
case .FunctionDecl:
StringView spelling = GetCursorSpelling!(cursor);
if (spelling.StartsWith("b2"))
spelling.RemoveFromStart(2);
outString.Append(spelling);
case .EnumConstantDecl:
StringView pre, post;
switch (GetCursorSpelling!(Clang.GetCursorSemanticParent(cursor)))
{
case "b2RecQueryType": pre = "b2_recQuery"; post = "";
case "b2TOIState": pre = "b2_toiState"; post = "";
case "b2TreeNodeFlags": pre = "b2_"; post = "Node";
case "b2BodyType": pre = "b2_"; post = "";
case "b2ShapeType": pre = "b2_"; post = "Shape";
case "b2JointType": pre = "b2_"; post = "Joint";
case "b2HexColor": pre = "b2_color"; post = "";
default: Runtime.FatalError("Unhandled enum");
}
StringView spelling = GetCursorSpelling!(cursor);
if (spelling.StartsWith(pre)) spelling.RemoveFromStart(pre.Length);
if (spelling.EndsWith (post)) spelling.RemoveFromEnd(post.Length);
str.Append(spelling[0].ToUpper);
str.Append(spelling[1...]);
case .MacroDefinition:
let spelling = GetCursorSpelling!(cursor);
switch (spelling)
{
case "UINT64_MAX": outString.Append("uint64.MaxValue");
case "B2_ZERO_INIT", "B2_NULL_ID": outString.Append("default");
default: fallthrough gnib;
}
default:
base.GetNameInBindings(cursor, outString);
}
}
protected override void WriteToken(CXToken token)
{
if (currentCursor.kind == .VarDecl &&
fileInfo.prevEnd.int_data > Clang.GetCursorLocation(currentCursor).int_data &&
Clang.GetTokenKind(token) == .Punctuation)
{
switch (GetTokenSpelling!(token))
{
case "{": str.Append(".("); return;
case "}": str.Append( ")"); return;
}
}
if (Clang.GetTokenKind(token) == .Identifier)
{
let spelling = GetTokenSpelling!(token);
bool invoke = spelling.StartsWith("b2");
if (invoke || spelling == "B2_LINEAR_SLOP")
str.Replace("const let", "static var");
if (invoke)
{
str.Append("Box2D.", spelling[2...]);
return;
}
}
base.WriteToken(token);
}
// There are functions you can override, but these are the most common
}
class Program
{
[CLink] static extern int32 system(char8*);
public static int Main(String[] args)
{
if (system("git -C .. submodule update") != 0)
{
Console.WriteLine("Failed to fetch Box2D, check your internet connection");
return 1;
}
{
StreamWriter all = scope .()..Create("b2_all.h");
for (let file in Directory.EnumerateFiles("../box2d/include/box2d"))
{
let filename = file.GetFileName(..scope .(64));
all.Write("#include <box2d/");
all.Write(filename);
all.Write(">\n");
}
}
scope Box2DGenerator(char8*[?]("--language=c", "-I../box2d/include")).Generate("b2_all.h");
return 0;
}
}
Submodule
+1
Submodule box2d added at 436365a246
+189
View File
@@ -0,0 +1,189 @@
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace Box2D;
static
{
// SPDX-FileCopyrightText: 2023 Erin Catto
// SPDX-License-Identifier: MIT
/// Used to indicate an unset or invalid index value.
public const let B2_NULL_INDEX = ( -1 );
// clang-format off
//
// Shared library macros
// build the Windows DLL
// using the Windows DLL
// building or using the shared library
// static library
// C++ macros
/// Used for C literals like (b2Vec2){1.0f, 2.0f} where C++ requires b2Vec2{1.0f, 2.0f}
// clang-format on
public const let B2_ENABLE_VALIDATION = 0;
}
/**
* @defgroup base Base
* Base functionality
* @{
*/
/// Prototype for user allocation function
/// @param size the allocation size in bytes
/// @param alignment the required alignment, guaranteed to be a power of 2
public function void* b2AllocFcn(c_size, c_int);
/// Prototype for user free function
/// @param mem the memory previously allocated through `b2AllocFcn`
/// @param size the allocation size in bytes
public function void b2FreeFcn(void*, c_size);
/// Prototype for the user assert callback. Return 0 to skip the debugger break.
public function c_int b2AssertFcn(c_char*, c_char*, c_int);
/// Prototype for user log callback. Used to log warnings.
public function void b2LogFcn(c_char*);
extension Box2D
{
/// This allows the user to override the allocation functions. These should be
/// set during application startup.
[LinkName("b2SetAllocator")] public static extern void SetAllocator(b2AllocFcn allocFcn, b2FreeFcn freeFcn);
/// @return the total bytes allocated by Box2D
[LinkName("b2GetByteCount")] public static extern int64 GetByteCount();
/// Override the default assert function
/// @param assertFcn a non-null assert callback
[LinkName("b2SetAssertFcn")] public static extern void SetAssertFcn(b2AssertFcn assertFcn);
/// Override the default log function
/// @param logFcn a non-null log callback
[LinkName("b2SetLogFcn")] public static extern void SetLogFcn(b2LogFcn logFcn);
}
/// Version numbering scheme.
/// See https://semver.org/
[CRepr] public struct b2Version
{
/// Significant changes
public c_int major;
/// Incremental changes
public c_int minor;
/// Bug fixes
public c_int revision;
}
extension Box2D
{
/// Get the current version of Box2D
[LinkName("b2GetVersion")] public static extern b2Version GetVersion();
}
static
{
/**@}*/
//! @cond
// see https://github.com/scottt/debugbreak
}
extension Box2D
{
// Unknown compiler
[LinkName("b2InternalAssert")] public static extern c_int InternalAssert(c_char* condition, c_char* fileName, c_int lineNumber);
}
static
{
// Validation is used in debug builds
}
extension Box2D
{
/// Get the absolute number of system ticks. The value is platform specific.
[LinkName("b2GetTicks")] public static extern uint64 GetTicks();
/// Get the milliseconds passed from an initial tick value.
[LinkName("b2GetMilliseconds")] public static extern float GetMilliseconds(uint64 ticks);
/// Get the milliseconds passed from an initial tick value. Resets the passed in
/// value to the current tick value.
[LinkName("b2GetMillisecondsAndReset")] public static extern float GetMillisecondsAndReset(uint64* ticks);
/// Yield to be used in a busy loop.
[LinkName("b2Yield")] public static extern void Yield();
}
static
{
/// Simple djb2 hash function for determinism testing
public const let B2_HASH_INIT = 5381;
}
extension Box2D
{
[LinkName("b2Hash")] public static extern uint32 Hash(uint32 hash, uint8* data, c_int count);
}
//! @endcond
+1596
View File
File diff suppressed because it is too large Load Diff
+939
View File
@@ -0,0 +1,939 @@
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace Box2D;
// SPDX-FileCopyrightText: 2023 Erin Catto
// SPDX-License-Identifier: MIT
[CRepr] public struct b2SimplexCache;
[CRepr] public struct b2Hull;
static
{
/**
* @defgroup geometry Geometry
* @brief Geometry types and algorithms
*
* Definitions of circles, capsules, segments, and polygons. Various algorithms to compute hulls, mass properties, and so on.
* Functions should take the shape as the first argument to assist editor auto-complete.
* @{
*/
/// The maximum number of vertices on a convex polygon. Changing this affects performance even if you
/// don't use more vertices.
public const let B2_MAX_POLYGON_VERTICES = 8;
}
/// Low level ray cast input data
[CRepr] public struct b2RayCastInput
{
/// Start point of the ray cast
public b2Vec2 origin;
/// Translation of the ray cast
public b2Vec2 translation;
/// The maximum fraction of the translation to consider, typically 1
public float maxFraction;
}
/// A distance proxy is used by the GJK algorithm. It encapsulates any shape.
/// You can provide between 1 and B2_MAX_POLYGON_VERTICES and a radius.
[CRepr] public struct b2ShapeProxy
{
/// The point cloud
public b2Vec2[8] points;
/// The number of points. Must be greater than 0.
public c_int count;
/// The external radius of the point cloud. May be zero.
public float radius;
}
/// 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.
[CRepr] public struct b2ShapeCastInput
{
/// A generic shape
public b2ShapeProxy proxy;
/// The translation of the shape cast
public b2Vec2 translation;
/// The maximum fraction of the translation to consider, typically 1
public float maxFraction;
/// Allow shape cast to encroach when initially touching. This only works if the radius is greater than zero.
public bool canEncroach;
}
/// Low level ray cast or shape-cast output data. Returns a zero fraction and normal in the case of initial overlap.
[CRepr] public struct b2CastOutput
{
/// The surface normal at the hit point
public b2Vec2 normal;
/// The surface hit point
public b2Vec2 point;
/// The fraction of the input translation at collision
public float fraction;
/// The number of iterations used
public c_int iterations;
/// Did the cast hit?
public bool hit;
}
/// This holds the mass data computed for a shape.
[CRepr] public struct b2MassData
{
/// The mass of the shape, usually in kilograms.
public float mass;
/// The position of the shape's centroid relative to the shape's origin.
public b2Vec2 center;
/// The rotational inertia of the shape about the shape center.
public float rotationalInertia;
}
/// A solid circle
[CRepr] public struct b2Circle
{
/// The local center
public b2Vec2 center;
/// The radius
public float radius;
}
/// A solid capsule can be viewed as two semicircles connected
/// by a rectangle.
[CRepr] public struct b2Capsule
{
/// Local center of the first semicircle
public b2Vec2 center1;
/// Local center of the second semicircle
public b2Vec2 center2;
/// The radius of the semicircles
public float radius;
}
/// 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 B2_MAX_POLYGON_VERTICES.
/// In most cases you should not need many vertices for a convex polygon.
/// @warning DO NOT fill this out manually, instead use a helper function like
/// b2MakePolygon or b2MakeBox.
[CRepr] public struct b2Polygon
{
/// The polygon vertices
public b2Vec2[8] vertices;
/// The outward normal vectors of the polygon sides
public b2Vec2[8] normals;
/// The centroid of the polygon
public b2Vec2 centroid;
/// The external radius for rounded polygons
public float radius;
/// The number of polygon vertices
public c_int count;
}
/// A line segment with two-sided collision.
[CRepr] public struct b2Segment
{
/// The first point
public b2Vec2 point1;
/// The second point
public b2Vec2 point2;
}
/// A line segment with one-sided collision. Only collides on the right side.
/// Several of these are generated for a chain shape.
/// ghost1 -> point1 -> point2 -> ghost2
[CRepr] public struct b2ChainSegment
{
/// The tail ghost vertex
public b2Vec2 ghost1;
/// The line segment
public b2Segment segment;
/// The head ghost vertex
public b2Vec2 ghost2;
/// The owning chain shape index (internal usage only)
public c_int chainId;
}
extension Box2D
{
/// Validate ray cast input data (NaN, etc)
[LinkName("b2IsValidRay")] public static extern bool IsValidRay(b2RayCastInput* input);
/// 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
[LinkName("b2MakePolygon")] public static extern b2Polygon MakePolygon(b2Hull* hull, float radius);
/// 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
[LinkName("b2MakeOffsetPolygon")] public static extern b2Polygon MakeOffsetPolygon(b2Hull* hull, b2Vec2 position, b2Rot rotation);
/// 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
[LinkName("b2MakeOffsetRoundedPolygon")] public static extern b2Polygon MakeOffsetRoundedPolygon(b2Hull* hull, b2Vec2 position, b2Rot rotation, float radius);
/// Make a square polygon, bypassing the need for a convex hull.
/// @param halfWidth the half-width
[LinkName("b2MakeSquare")] public static extern b2Polygon MakeSquare(float halfWidth);
/// Make a box (rectangle) polygon, bypassing the need for a convex hull.
/// @param halfWidth the half-width (x-axis)
/// @param halfHeight the half-height (y-axis)
[LinkName("b2MakeBox")] public static extern b2Polygon MakeBox(float halfWidth, float halfHeight);
/// Make a rounded box, bypassing the need for a convex hull.
/// @param halfWidth the half-width (x-axis)
/// @param halfHeight the half-height (y-axis)
/// @param radius the radius of the rounded extension
[LinkName("b2MakeRoundedBox")] public static extern b2Polygon MakeRoundedBox(float halfWidth, float halfHeight, float radius);
/// Make an offset box, bypassing the need for a convex hull.
/// @param halfWidth the half-width (x-axis)
/// @param halfHeight the half-height (y-axis)
/// @param center the local center of the box
/// @param rotation the local rotation of the box
[LinkName("b2MakeOffsetBox")] public static extern b2Polygon MakeOffsetBox(float halfWidth, float halfHeight, b2Vec2 center, b2Rot rotation);
/// Make an offset rounded box, bypassing the need for a convex hull.
/// @param halfWidth the half-width (x-axis)
/// @param halfHeight the half-height (y-axis)
/// @param center the local center of the box
/// @param rotation the local rotation of the box
/// @param radius the radius of the rounded extension
[LinkName("b2MakeOffsetRoundedBox")] public static extern b2Polygon MakeOffsetRoundedBox(float halfWidth, float halfHeight, b2Vec2 center, b2Rot rotation, float radius);
/// Transform a polygon. This is useful for transferring a shape from one body to another.
[LinkName("b2TransformPolygon")] public static extern b2Polygon TransformPolygon(b2Transform transform, b2Polygon* polygon);
/// Compute mass properties of a circle
[LinkName("b2ComputeCircleMass")] public static extern b2MassData ComputeCircleMass(b2Circle* shape, float density);
/// Compute mass properties of a capsule
[LinkName("b2ComputeCapsuleMass")] public static extern b2MassData ComputeCapsuleMass(b2Capsule* shape, float density);
/// Compute mass properties of a polygon
[LinkName("b2ComputePolygonMass")] public static extern b2MassData ComputePolygonMass(b2Polygon* shape, float density);
/// Compute the bounding box of a transformed circle
[LinkName("b2ComputeCircleAABB")] public static extern b2AABB ComputeCircleAABB(b2Circle* shape, b2Transform transform);
/// Compute the bounding box of a transformed capsule
[LinkName("b2ComputeCapsuleAABB")] public static extern b2AABB ComputeCapsuleAABB(b2Capsule* shape, b2Transform transform);
/// Compute the bounding box of a transformed polygon
[LinkName("b2ComputePolygonAABB")] public static extern b2AABB ComputePolygonAABB(b2Polygon* shape, b2Transform transform);
/// Compute the bounding box of a transformed line segment
[LinkName("b2ComputeSegmentAABB")] public static extern b2AABB ComputeSegmentAABB(b2Segment* shape, b2Transform transform);
/// Test a point for overlap with a circle in local space
[LinkName("b2PointInCircle")] public static extern bool PointInCircle(b2Circle* shape, b2Vec2 point);
/// Test a point for overlap with a capsule in local space
[LinkName("b2PointInCapsule")] public static extern bool PointInCapsule(b2Capsule* shape, b2Vec2 point);
/// Test a point for overlap with a convex polygon in local space
[LinkName("b2PointInPolygon")] public static extern bool PointInPolygon(b2Polygon* shape, b2Vec2 point);
/// Ray cast versus circle shape in local space.
[LinkName("b2RayCastCircle")] public static extern b2CastOutput RayCastCircle(b2Circle* shape, b2RayCastInput* input);
/// Ray cast versus capsule shape in local space.
[LinkName("b2RayCastCapsule")] public static extern b2CastOutput RayCastCapsule(b2Capsule* shape, b2RayCastInput* input);
/// Ray cast versus segment shape in local space. Optionally treat the segment as one-sided with hits from
/// the left side being treated as a miss.
[LinkName("b2RayCastSegment")] public static extern b2CastOutput RayCastSegment(b2Segment* shape, b2RayCastInput* input, bool oneSided);
/// Ray cast versus polygon shape in local space.
[LinkName("b2RayCastPolygon")] public static extern b2CastOutput RayCastPolygon(b2Polygon* shape, b2RayCastInput* input);
/// Shape cast versus a circle.
[LinkName("b2ShapeCastCircle")] public static extern b2CastOutput ShapeCastCircle(b2Circle* shape, b2ShapeCastInput* input);
/// Shape cast versus a capsule.
[LinkName("b2ShapeCastCapsule")] public static extern b2CastOutput ShapeCastCapsule(b2Capsule* shape, b2ShapeCastInput* input);
/// Shape cast versus a line segment.
[LinkName("b2ShapeCastSegment")] public static extern b2CastOutput ShapeCastSegment(b2Segment* shape, b2ShapeCastInput* input);
/// Shape cast versus a convex polygon.
[LinkName("b2ShapeCastPolygon")] public static extern b2CastOutput ShapeCastPolygon(b2Polygon* shape, b2ShapeCastInput* input);
/// A convex hull. Used to create convex polygons.
/// @warning Do not modify these values directly, instead use b2ComputeHull()
/// The final points of the hull
/// The number of points
/// 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 B2_MAX_POLYGON_VERTICES points
/// This welds close points and removes collinear points.
/// @warning Do not modify a hull once it has been computed
[LinkName("b2ComputeHull")] public static extern b2Hull ComputeHull(b2Vec2* points, c_int count);
/// This determines if a hull is valid. Checks for:
/// - convexity
/// - collinear points
/// This is expensive and should not be called at runtime.
[LinkName("b2ValidateHull")] public static extern bool ValidateHull(b2Hull* hull);
}
/**@}*/
/**
* @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
[CRepr] public struct b2SegmentDistanceResult
{
/// The closest point on the first segment
public b2Vec2 closest1;
/// The closest point on the second segment
public b2Vec2 closest2;
/// The barycentric coordinate on the first segment
public float fraction1;
/// The barycentric coordinate on the second segment
public float fraction2;
/// The squared distance between the closest points
public float distanceSquared;
}
extension Box2D
{
/// Compute the distance between two line segments, clamping at the end points if needed.
[LinkName("b2SegmentDistance")] public static extern b2SegmentDistanceResult SegmentDistance(b2Vec2 p1, b2Vec2 q1, b2Vec2 p2, b2Vec2 q2);
}
/// Used to warm start the GJK simplex. If you call this function multiple times with nearby
/// transforms this might improve performance. Otherwise you can zero initialize this.
/// The distance cache must be initialized to zero on the first call.
/// Users should generally just zero initialize this structure for each call.
/// The number of stored simplex points
/// The cached simplex indices on shape A
/// The cached simplex indices on shape B
/// Input for b2ShapeDistance
[CRepr] public struct b2DistanceInput
{
/// The proxy for shape A
public b2ShapeProxy proxyA;
/// The proxy for shape B
public b2ShapeProxy proxyB;
/// The world transform for shape A
public b2Transform transformA;
/// The world transform for shape B
public b2Transform transformB;
/// Should the proxy radius be considered?
public bool useRadii;
}
/// Output for b2ShapeDistance
[CRepr] public struct b2DistanceOutput
{
public b2Vec2 pointA; ///< Closest point on shapeA
public b2Vec2 pointB; ///< Closest point on shapeB
public b2Vec2 normal; ///< Normal vector that points from A to B. Invalid if distance is zero.
public float distance; ///< The final distance, zero if overlapped
public c_int iterations; ///< Number of GJK iterations used
public c_int simplexCount; ///< The number of simplexes stored in the simplex array
}
/// Simplex vertex for debugging the GJK algorithm
[CRepr] public struct b2SimplexVertex
{
public b2Vec2 wA; ///< support point in proxyA
public b2Vec2 wB; ///< support point in proxyB
public b2Vec2 w; ///< wB - wA
public float a; ///< barycentric coordinate for closest point
public c_int indexA; ///< wA index
public c_int indexB; ///< wB index
}
/// Simplex from the GJK algorithm
[CRepr] public struct b2Simplex
{
public b2SimplexVertex v1; public b2SimplexVertex v2; public b2SimplexVertex v3; ///< vertices
public c_int count; ///< number of valid vertices
}
/// Compute the closest points between two shapes represented as point clouds.
/// b2SimplexCache cache is input/output. On the first call set b2SimplexCache.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.
extension Box2D
{
[LinkName("b2ShapeDistance")] public static extern b2DistanceOutput ShapeDistance(b2DistanceInput* input, b2SimplexCache* cache, b2Simplex* simplexes, c_int simplexCapacity);
}
/// Input parameters for b2ShapeCast
[CRepr] public struct b2ShapeCastPairInput
{
public b2ShapeProxy proxyA; ///< The proxy for shape A
public b2ShapeProxy proxyB; ///< The proxy for shape B
public b2Transform transformA; ///< The world transform for shape A
public b2Transform transformB; ///< The world transform for shape B
public b2Vec2 translationB; ///< The translation of shape B
public float maxFraction; ///< The fraction of the translation to consider, typically 1
public bool canEncroach; ///< Allows shapes with a radius to move slightly closer if already touching
}
/// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction.
/// Initially touching shapes are treated as a miss.
extension Box2D
{
[LinkName("b2ShapeCast")] public static extern b2CastOutput ShapeCast(b2ShapeCastPairInput* input);
/// Make a proxy for use in overlap, shape cast, and related functions. This is a deep copy of the points.
[LinkName("b2MakeProxy")] public static extern b2ShapeProxy MakeProxy(b2Vec2* points, c_int count, float radius);
/// Make a proxy with a transform. This is a deep copy of the points.
[LinkName("b2MakeOffsetProxy")] public static extern b2ShapeProxy MakeOffsetProxy(b2Vec2* points, c_int count, float radius, b2Vec2 position, b2Rot rotation);
}
/// 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.
[CRepr] public struct b2Sweep
{
public b2Vec2 localCenter; ///< Local center of mass position
public b2Vec2 c1; ///< Starting center of mass world position
public b2Vec2 c2; ///< Ending center of mass world position
public b2Rot q1; ///< Starting world rotation
public b2Rot q2; ///< Ending world rotation
}
/// Evaluate the transform sweep at a specific time.
extension Box2D
{
[LinkName("b2GetSweepTransform")] public static extern b2Transform GetSweepTransform(b2Sweep* sweep, float time);
}
/// Time of impact input
[CRepr] public struct b2TOIInput
{
public b2ShapeProxy proxyA; ///< The proxy for shape A
public b2ShapeProxy proxyB; ///< The proxy for shape B
public b2Sweep sweepA; ///< The movement of shape A
public b2Sweep sweepB; ///< The movement of shape B
public float maxFraction; ///< Defines the sweep interval [0, maxFraction]
}
/// Describes the TOI output
[AllowDuplicates] public enum b2TOIState : c_int
{
Unknown,
Failed,
Overlapped,
Hit,
Separated,
}
/// Time of impact output
[CRepr] public struct b2TOIOutput
{
/// The type of result
public b2TOIState state;
/// The hit point
public b2Vec2 point;
/// The hit normal
public b2Vec2 normal;
/// The sweep time of the collision
public float fraction;
}
extension Box2D
{
/// 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.
[LinkName("b2TimeOfImpact")] public static extern b2TOIOutput TimeOfImpact(b2TOIInput* input);
}
/**@}*/
/**
* @defgroup collision Collision
* @brief Functions for colliding pairs of shapes
* @{
*/
/// A manifold point is a contact point belonging to a contact manifold.
/// It holds details related to the geometry and dynamics of the contact points.
/// Box2D uses speculative collision so some contact points may be separated.
/// You may use the totalNormalImpulse to determine if there was an interaction during
/// the time step.
[CRepr] public struct b2ManifoldPoint
{
/// Location of the contact point in world space when first clipped. Subject to precision
/// loss at large coordinates. This point lags behind when contact recycling is used.
/// @note Should only be used for debugging. Use anchorA and/or anchorB for game logic.
public b2Vec2 clipPoint;
/// Location of the contact point relative to shapeA's origin in world space.
/// This can be converted to a world point using:
/// b2Vec2 worldPointA = b2Add(b2Body_GetWorldCenterOfMass(myBodyIdA), anchorA);
/// @note When used internally to the Box2D solver, this is relative to the body center of mass.
public b2Vec2 anchorA;
/// Location of the contact point relative to shapeB's origin in world space
/// This can be converted to a world point using:
/// b2Vec2 worldPointB = b2Add(b2Body_GetWorldCenterOfMass(myBodyIdB), anchorB);
/// @note When used internally to the Box2D solver, this is relative to the body center of mass.
public b2Vec2 anchorB;
/// The separation of the contact point, negative if penetrating
public float separation;
/// Cached separation used for contact recycling
public float baseSeparation;
/// The impulse along the manifold normal vector.
public float normalImpulse;
/// The friction impulse
public float tangentImpulse;
/// The total normal impulse applied across sub-stepping and restitution. This is important
/// to identify speculative contact points that had an interaction in the time step.
/// This includes the warm starting impulse, the sub-step delta impulse, and the restitution
/// impulse.
public float totalNormalImpulse;
/// 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.
public float normalVelocity;
/// Uniquely identifies a contact point between two shapes
public uint16 id;
/// Did this contact point exist the previous step?
public bool persisted;
}
/// A contact manifold describes the contact points between colliding shapes.
/// @note Box2D uses speculative collision so some contact points may be separated.
[CRepr] public struct b2Manifold
{
/// The unit normal vector in world space, points from shape A to bodyB
public b2Vec2 normal;
/// Angular impulse applied for rolling resistance. N * m * s = kg * m^2 / s
public float rollingImpulse;
/// The manifold points, up to two are possible in 2D
public b2ManifoldPoint[2] points;
/// The number of contacts points, will be 0, 1, or 2
public c_int pointCount;
}
extension Box2D
{
/// Compute the contact manifold between two circles
[LinkName("b2CollideCircles")] public static extern b2Manifold CollideCircles(b2Circle* circleA, b2Transform xfA, b2Circle* circleB, b2Transform xfB);
/// Compute the contact manifold between a capsule and circle
[LinkName("b2CollideCapsuleAndCircle")] public static extern b2Manifold CollideCapsuleAndCircle(b2Capsule* capsuleA, b2Transform xfA, b2Circle* circleB, b2Transform xfB);
/// Compute the contact manifold between an segment and a circle
[LinkName("b2CollideSegmentAndCircle")] public static extern b2Manifold CollideSegmentAndCircle(b2Segment* segmentA, b2Transform xfA, b2Circle* circleB, b2Transform xfB);
/// Compute the contact manifold between a polygon and a circle
[LinkName("b2CollidePolygonAndCircle")] public static extern b2Manifold CollidePolygonAndCircle(b2Polygon* polygonA, b2Transform xfA, b2Circle* circleB, b2Transform xfB);
/// Compute the contact manifold between a capsule and circle
[LinkName("b2CollideCapsules")] public static extern b2Manifold CollideCapsules(b2Capsule* capsuleA, b2Transform xfA, b2Capsule* capsuleB, b2Transform xfB);
/// Compute the contact manifold between an segment and a capsule
[LinkName("b2CollideSegmentAndCapsule")] public static extern b2Manifold CollideSegmentAndCapsule(b2Segment* segmentA, b2Transform xfA, b2Capsule* capsuleB, b2Transform xfB);
/// Compute the contact manifold between a polygon and capsule
[LinkName("b2CollidePolygonAndCapsule")] public static extern b2Manifold CollidePolygonAndCapsule(b2Polygon* polygonA, b2Transform xfA, b2Capsule* capsuleB, b2Transform xfB);
/// Compute the contact manifold between two polygons
[LinkName("b2CollidePolygons")] public static extern b2Manifold CollidePolygons(b2Polygon* polygonA, b2Transform xfA, b2Polygon* polygonB, b2Transform xfB);
/// Compute the contact manifold between an segment and a polygon
[LinkName("b2CollideSegmentAndPolygon")] public static extern b2Manifold CollideSegmentAndPolygon(b2Segment* segmentA, b2Transform xfA, b2Polygon* polygonB, b2Transform xfB);
/// Compute the contact manifold between a chain segment and a circle
[LinkName("b2CollideChainSegmentAndCircle")] public static extern b2Manifold CollideChainSegmentAndCircle(b2ChainSegment* segmentA, b2Transform xfA, b2Circle* circleB, b2Transform xfB);
/// Compute the contact manifold between a chain segment and a capsule
[LinkName("b2CollideChainSegmentAndCapsule")] public static extern b2Manifold CollideChainSegmentAndCapsule(b2ChainSegment* segmentA, b2Transform xfA, b2Capsule* capsuleB, b2Transform xfB, b2SimplexCache* cache);
/// Compute the contact manifold between a chain segment and a rounded polygon
[LinkName("b2CollideChainSegmentAndPolygon")] public static extern b2Manifold CollideChainSegmentAndPolygon(b2ChainSegment* segmentA, b2Transform xfA, b2Polygon* polygonB, b2Transform xfB, b2SimplexCache* cache);
}
/**@}*/
/**
* @defgroup tree Dynamic Tree
* The dynamic tree is a binary AABB tree to organize and query large numbers of geometric objects
*
* Box2D uses the dynamic tree internally to sort collision shapes into a binary bounding volume hierarchy.
* This data structure may have uses in games for organizing other geometry data and may be used independently
* of Box2D rigid body simulation.
*
* A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
* A dynamic tree arranges data in a binary tree to accelerate
* queries such as AABB queries and ray casts. Leaf nodes are proxies
* with an AABB. These are used to hold a user collision object.
* Nodes are pooled and relocatable, so I use node indices rather than pointers.
* The dynamic tree is made available for advanced users that would like to use it to organize
* spatial game data besides rigid bodies.
* @{
*/
/// Tree node flags. For internal usage.
[AllowDuplicates] public enum b2TreeNodeFlags : c_int
{
Allocated = 0x0001,
Enlarged = 0x0002,
Leaf = 0x0004,
}
/// A node in the dynamic tree. For internal usage.
[CRepr] public struct b2TreeNode
{
/// The node bounding box
public b2AABB aabb; // 16
/// Category bits for collision filtering
public uint64 categoryBits; // 8
[CRepr, Union] public using public struct
{
/// Children (internal node)
public [CRepr] public struct
{
public int32 child1; public int32 child2;
} children;
/// User data (leaf node)
public uint64 userData;
}; // 8
[CRepr, Union] public using public struct
{
/// The node parent index (allocated node)
public int32 parent;
/// The node freelist next index (free node)
public int32 next;
}; // 4
public uint16 height; // 2
public uint16 flags; // 2
}
/// The dynamic tree structure. This should be considered private data.
/// It is placed here for performance reasons.
[CRepr] public struct b2DynamicTree
{
/// The tree nodes
public b2TreeNode* nodes;
/// The root index
public int32 root;
/// The number of nodes
public int32 nodeCount;
/// The allocated node space
public int32 nodeCapacity;
/// Node free list
public int32 freeList;
/// Number of proxies created
public int32 proxyCount;
/// Leaf indices for rebuild
public int32* leafIndices;
/// Leaf bounding boxes for rebuild
public b2AABB* leafBoxes;
/// Leaf bounding box centers for rebuild
public b2Vec2* leafCenters;
/// Bins for sorting during rebuild
public int32* binIndices;
/// Allocated space for rebuilding
public int32 rebuildCapacity;
}
/// These are performance results returned by dynamic tree queries.
[CRepr] public struct b2TreeStats
{
/// Number of internal nodes visited during the query
public c_int nodeVisits;
/// Number of leaf nodes visited during the query
public c_int leafVisits;
}
extension Box2D
{
/// Constructing the tree initializes the node pool.
[LinkName("b2DynamicTree_Create")] public static extern b2DynamicTree DynamicTree_Create(c_int proxyCapacity);
/// Destroy the tree, freeing the node pool.
[LinkName("b2DynamicTree_Destroy")] public static extern void DynamicTree_Destroy(b2DynamicTree* tree);
/// Create a proxy. Provide an AABB and a userData value.
[LinkName("b2DynamicTree_CreateProxy")] public static extern c_int DynamicTree_CreateProxy(b2DynamicTree* tree, b2AABB aabb, uint64 categoryBits, uint64 userData);
/// Destroy a proxy. This asserts if the id is invalid.
[LinkName("b2DynamicTree_DestroyProxy")] public static extern void DynamicTree_DestroyProxy(b2DynamicTree* tree, c_int proxyId);
/// Move a proxy to a new AABB by removing and reinserting into the tree.
[LinkName("b2DynamicTree_MoveProxy")] public static extern void DynamicTree_MoveProxy(b2DynamicTree* tree, c_int proxyId, b2AABB aabb);
/// Enlarge a proxy and enlarge ancestors as necessary.
[LinkName("b2DynamicTree_EnlargeProxy")] public static extern void DynamicTree_EnlargeProxy(b2DynamicTree* tree, c_int proxyId, b2AABB aabb);
/// Modify the category bits on a proxy. This is an expensive operation.
[LinkName("b2DynamicTree_SetCategoryBits")] public static extern void DynamicTree_SetCategoryBits(b2DynamicTree* tree, c_int proxyId, uint64 categoryBits);
/// Get the category bits on a proxy.
[LinkName("b2DynamicTree_GetCategoryBits")] public static extern uint64 DynamicTree_GetCategoryBits(b2DynamicTree* tree, c_int proxyId);
}
/// This function receives proxies found in the AABB query.
/// @return true if the query should continue
public function bool b2TreeQueryCallbackFcn(c_int, uint64, void*);
extension Box2D
{
/// Query an AABB for overlapping proxies. The callback class is called for each proxy that overlaps the supplied AABB.
/// @return performance data
[LinkName("b2DynamicTree_Query")] public static extern b2TreeStats DynamicTree_Query(b2DynamicTree* tree, b2AABB aabb, uint64 maskBits, b2TreeQueryCallbackFcn callback, void* context);
/// Query an AABB for overlapping proxies. The callback class is called for each proxy that overlaps the supplied AABB.
/// No filtering is performed.
/// @return performance data
[LinkName("b2DynamicTree_QueryAll")] public static extern b2TreeStats DynamicTree_QueryAll(b2DynamicTree* tree, b2AABB aabb, b2TreeQueryCallbackFcn callback, void* context);
}
/// 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
public function float b2TreeRayCastCallbackFcn(b2RayCastInput*, c_int, uint64, void*);
extension Box2D
{
/// 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.
/// However, this filtering may be approximate, so the user should still apply filtering to results.
/// @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 mask bit hint: `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
/// @return performance data
[LinkName("b2DynamicTree_RayCast")] public static extern b2TreeStats DynamicTree_RayCast(b2DynamicTree* tree, b2RayCastInput* input, uint64 maskBits, b2TreeRayCastCallbackFcn callback, void* context);
}
/// 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
public function float b2TreeShapeCastCallbackFcn(b2ShapeCastInput*, c_int, uint64, void*);
extension Box2D
{
/// 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
/// @return performance data
[LinkName("b2DynamicTree_ShapeCast")] public static extern b2TreeStats DynamicTree_ShapeCast(b2DynamicTree* tree, b2ShapeCastInput* input, uint64 maskBits, b2TreeShapeCastCallbackFcn callback, void* context);
/// Get the height of the binary tree.
[LinkName("b2DynamicTree_GetHeight")] public static extern c_int DynamicTree_GetHeight(b2DynamicTree* tree);
/// Get the ratio of the sum of the node areas to the root area.
[LinkName("b2DynamicTree_GetAreaRatio")] public static extern float DynamicTree_GetAreaRatio(b2DynamicTree* tree);
/// Get the bounding box that contains the entire tree
[LinkName("b2DynamicTree_GetRootBounds")] public static extern b2AABB DynamicTree_GetRootBounds(b2DynamicTree* tree);
/// Get the number of proxies created
[LinkName("b2DynamicTree_GetProxyCount")] public static extern c_int DynamicTree_GetProxyCount(b2DynamicTree* tree);
/// Rebuild the tree while retaining subtrees that haven't changed. Returns the number of boxes sorted.
[LinkName("b2DynamicTree_Rebuild")] public static extern c_int DynamicTree_Rebuild(b2DynamicTree* tree, bool fullBuild);
/// Get the number of bytes used by this tree
[LinkName("b2DynamicTree_GetByteCount")] public static extern c_int DynamicTree_GetByteCount(b2DynamicTree* tree);
/// Get proxy user data
[LinkName("b2DynamicTree_GetUserData")] public static extern uint64 DynamicTree_GetUserData(b2DynamicTree* tree, c_int proxyId);
/// Get the AABB of a proxy
[LinkName("b2DynamicTree_GetAABB")] public static extern b2AABB DynamicTree_GetAABB(b2DynamicTree* tree, c_int proxyId);
/// Validate this tree. For testing.
[LinkName("b2DynamicTree_Validate")] public static extern void DynamicTree_Validate(b2DynamicTree* tree);
/// Validate this tree has no enlarged AABBs. For testing.
[LinkName("b2DynamicTree_ValidateNoEnlarged")] public static extern void DynamicTree_ValidateNoEnlarged(b2DynamicTree* tree);
}
/**@}*/
/**
* @defgroup character Character mover
* Character movement solver
* @{
*/
/// These are the collision planes returned from b2World_CollideMover
[CRepr] public struct b2PlaneResult
{
/// The collision plane between the mover and a convex shape
public b2Plane plane;
// The collision point on the shape.
public b2Vec2 point;
/// Did the collision register a hit? If not this plane should be ignored.
public bool hit;
}
/// These are collision planes that can be fed to b2SolvePlanes. Normally
/// this is assembled by the user from plane results in b2PlaneResult
[CRepr] public struct b2CollisionPlane
{
/// The collision plane between the mover and some shape
public b2Plane plane;
/// Setting this to FLT_MAX makes the plane as rigid as possible. Lower values can
/// make the plane collision soft. Usually in meters.
public float pushLimit;
/// The push on the mover determined by b2SolvePlanes. Usually in meters.
public float push;
/// Indicates if b2ClipVector should clip against this plane. Should be false for soft collision.
public bool clipVelocity;
}
/// Result returned by b2SolvePlanes
[CRepr] public struct b2PlaneSolverResult
{
/// The translation of the mover
public b2Vec2 translation;
/// The number of iterations used by the plane solver. For diagnostics.
public c_int iterationCount;
}
extension Box2D
{
/// Solves the position of a mover that satisfies the given collision planes.
/// @param targetDelta the desired movement from the position used to generate the collision planes
/// @param planes the collision planes
/// @param count the number of collision planes
[LinkName("b2SolvePlanes")] public static extern b2PlaneSolverResult SolvePlanes(b2Vec2 targetDelta, b2CollisionPlane* planes, c_int count);
/// Clips the velocity against the given collision planes. Planes with zero push or clipVelocity
/// set to false are skipped.
[LinkName("b2ClipVector")] public static extern b2Vec2 ClipVector(b2Vec2 vector, b2CollisionPlane* planes, c_int count);
}
/**@}*/
+84
View File
@@ -0,0 +1,84 @@
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace Box2D;
static
{
// SPDX-FileCopyrightText: 2026 Erin Catto
// SPDX-License-Identifier: MIT
/// Used to detect bad values. Positions greater than about 16km will have precision
/// problems, so 100km as a limit should be fine in all cases.
public static var B2_HUGE = ( 100000.0f * Box2D.GetLengthUnitsPerMeter() );
/// Maximum parallel workers. Used for some fixed size arrays.
public const let B2_MAX_WORKERS = 32;
/// Maximum number of tasks queued per world step. b2EnqueueTaskCallback will never be called
/// more than this per world step. This is related to B2_MAX_WORKERS. With 32 workers,
/// the maximum observed task count is 130. This allows an external task system to use a fixed
/// size array for Box2D task, which may help with creating stable user task pointers.
public const let B2_MAX_TASKS = 256;
/// Maximum number of colors in the constraint graph. Constraints that cannot
/// find a color are added to the overflow set which are solved single-threaded.
/// The compound barrel benchmark has minor overflow with 24 colors
public const let B2_GRAPH_COLOR_COUNT = 24;
/// A small length used as a collision and constraint tolerance. Usually it is
/// chosen to be numerically significant, but visually insignificant. In meters.
/// Normally this is 0.5cm.
/// @warning modifying this can have a significant impact on stability
public static var B2_LINEAR_SLOP = ( 0.005f * Box2D.GetLengthUnitsPerMeter() );
/// Maximum number of simultaneous worlds that can be allocated
public const let B2_MAX_WORLDS = 128;
/// Maximum length of the body name. Can be 0 if you don't need names.
public const let B2_NAME_LENGTH = 10;
/// The maximum rotation of a body per time step. This limit is very large and is used
/// to prevent numerical problems. You shouldn't need to adjust this.
/// @warning increasing this to 0.5f * b2_pi or greater will break continuous collision.
public const let B2_MAX_ROTATION = ( 0.25f * B2_PI );
/// Box2D uses limited speculative collision. This reduces jitter.
/// Normally this is 2cm.
/// @warning modifying this can have a significant impact on performance and stability
public static var B2_SPECULATIVE_DISTANCE = ( 4.0f * B2_LINEAR_SLOP );
/// The default contact recycling distance.
public static var B2_CONTACT_RECYCLE_DISTANCE = ( 10.0f * B2_LINEAR_SLOP );
/// The default contact recycling world angle threshold. 0.98 ~= 11.5 degrees
public const let B2_CONTACT_RECYCLE_COS_ANGLE = ( 0.98f );
/// This is used to fatten AABBs in the dynamic tree. This allows proxies
/// to move by a small amount without triggering a tree adjustment. This is in meters.
/// Normally this is 5cm.
/// @warning modifying this can have a significant impact on performance
public static var B2_MAX_AABB_MARGIN = ( 0.05f * Box2D.GetLengthUnitsPerMeter() );
/// For small objects the margin is limited to this fraction times the maximum extent
public const let B2_AABB_MARGIN_FRACTION = 0.125f;
}
/// The time that a body must be still before it will go to sleep. In seconds.
static
{
public const let B2_TIME_TO_SLEEP = 0.5f;
}
+203
View File
@@ -0,0 +1,203 @@
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace Box2D;
// SPDX-FileCopyrightText: 2023 Erin Catto
// SPDX-License-Identifier: MIT
// Note: this file should be stand-alone
/**
* @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.
[CRepr] public struct b2WorldId
{
public uint16 index1;
public uint16 generation;
}
/// Body id references a body instance. This should be treated as an opaque handle.
[CRepr] public struct b2BodyId
{
public int32 index1;
public uint16 world0;
public uint16 generation;
}
/// Shape id references a shape instance. This should be treated as an opaque handle.
[CRepr] public struct b2ShapeId
{
public int32 index1;
public uint16 world0;
public uint16 generation;
}
/// Chain id references a chain instances. This should be treated as an opaque handle.
[CRepr] public struct b2ChainId
{
public int32 index1;
public uint16 world0;
public uint16 generation;
}
/// Joint id references a joint instance. This should be treated as an opaque handle.
[CRepr] public struct b2JointId
{
public int32 index1;
public uint16 world0;
public uint16 generation;
}
/// Contact id references a contact instance. This should be treated as an opaque handled.
[CRepr] public struct b2ContactId
{
public int32 index1;
public uint16 world0;
public int16 padding;
public uint32 generation;
}
static
{
/// A null id. Works for any id type.
/// A null id. Works for any id type.
/// Use these to make your identifiers null.
/// You may also use zero initialization to get null.
public const b2WorldId b2_nullWorldId = default;
public const b2BodyId b2_nullBodyId = default;
public const b2ShapeId b2_nullShapeId = default;
public const b2ChainId b2_nullChainId = default;
public const b2JointId b2_nullJointId = default;
public const b2ContactId b2_nullContactId = default;
/// Macro to determine if any id is null.
/// Macro to determine if any id is non-null.
/// Compare two ids for equality. Doesn't work for b2WorldId. Don't mix types.
}
extension Box2D
{
/// Store a world id into a uint32_t.
[LinkName("b2StoreWorldId")] public static extern uint32 StoreWorldId(b2WorldId id);
/// Load a uint32_t into a world id.
[LinkName("b2LoadWorldId")] public static extern b2WorldId LoadWorldId(uint32 x);
/// Store a body id into a uint64_t.
[LinkName("b2StoreBodyId")] public static extern uint64 StoreBodyId(b2BodyId id);
/// Load a uint64_t into a body id.
[LinkName("b2LoadBodyId")] public static extern b2BodyId LoadBodyId(uint64 x);
/// Store a shape id into a uint64_t.
[LinkName("b2StoreShapeId")] public static extern uint64 StoreShapeId(b2ShapeId id);
/// Load a uint64_t into a shape id.
[LinkName("b2LoadShapeId")] public static extern b2ShapeId LoadShapeId(uint64 x);
/// Store a chain id into a uint64_t.
[LinkName("b2StoreChainId")] public static extern uint64 StoreChainId(b2ChainId id);
/// Load a uint64_t into a chain id.
[LinkName("b2LoadChainId")] public static extern b2ChainId LoadChainId(uint64 x);
/// Store a joint id into a uint64_t.
[LinkName("b2StoreJointId")] public static extern uint64 StoreJointId(b2JointId id);
/// Load a uint64_t into a joint id.
[LinkName("b2LoadJointId")] public static extern b2JointId LoadJointId(uint64 x);
/// Store a contact id into 16 bytes
[LinkName("b2StoreContactId")] public static extern void StoreContactId(b2ContactId id, uint32[3] values);
/// Load a two uint64_t into a contact id.
[LinkName("b2LoadContactId")] public static extern b2ContactId LoadContactId(uint32[3] values);
}
/**@}*/
+14
View File
@@ -0,0 +1,14 @@
using System;
using CxxBuildTool;
namespace Box2D;
class Box2D
{
[OnCompile(.TypeDone)]
private static void Build()
{
if (!Compiler.IsBuilding) return;
CxxBuildTool.CMake(Compiler.ProjectDir + "/box2d", Compiler.BuildDir + "/" + Compiler.ProjectName, "-DBOX2D_SAMPLES=OFF -DBOX2D_UNIT_TESTS=OFF");
}
}
+800
View File
@@ -0,0 +1,800 @@
// This file was generated by Cpp2Beef
using System;
using System.Interop;
namespace Box2D;
// SPDX-FileCopyrightText: 2023 Erin Catto
// SPDX-License-Identifier: MIT
/**
* @defgroup math Math
* @brief Vector math types and functions
* @{
*/
/// 2D vector
/// This can be used to represent a point or free vector
[CRepr] public struct b2Vec2
{
/// coordinates
public float x; public float y;
public this(float x, float y) { this.x = x; this.y = y; }
}
/// Cosine and sine pair
/// This uses a custom implementation designed for cross-platform determinism
[CRepr] public struct b2CosSin
{
/// cosine and sine
public float cosine;
public float sine;
public this(float cosine, float sine) { this.cosine = cosine; this.sine = sine; }
}
/// 2D rotation
/// This is similar to using a complex number for rotation
[CRepr] public struct b2Rot
{
/// cosine and sine
public float c; public float s;
public this(float c, float s) { this.c = c; this.s = s; }
}
/// A 2D rigid transform
[CRepr] public struct b2Transform
{
public b2Vec2 p;
public b2Rot q;
public this(b2Vec2 p, b2Rot q) { this.p = p; this.q = q; }
}
/// A 2-by-2 Matrix
[CRepr] public struct b2Mat22
{
/// columns
public b2Vec2 cx; public b2Vec2 cy;
public this(b2Vec2 cx, b2Vec2 cy) { this.cx = cx; this.cy = cy; }
}
/// Axis-aligned bounding box
[CRepr] public struct b2AABB
{
public b2Vec2 lowerBound;
public b2Vec2 upperBound;
public this(b2Vec2 lowerBound, b2Vec2 upperBound) { this.lowerBound = lowerBound; this.upperBound = upperBound; }
}
/// separation = dot(normal, point) - offset
[CRepr] public struct b2Plane
{
public b2Vec2 normal;
public float offset;
public this(b2Vec2 normal, float offset) { this.normal = normal; this.offset = offset; }
}
static
{
/**@}*/
/**
* @addtogroup math
* @{
*/
/// https://en.wikipedia.org/wiki/Pi
public const let B2_PI = 3.14159265359f;
public const b2Vec2 b2Vec2_zero = .( 0.0f, 0.0f );
public const b2Rot b2Rot_identity = .( 1.0f, 0.0f );
public const b2Transform b2Transform_identity = .( .( 0.0f, 0.0f ), .( 1.0f, 0.0f ) );
public const b2Mat22 b2Mat22_zero = .( .( 0.0f, 0.0f ), .( 0.0f, 0.0f ) );
}
extension Box2D
{
/// Is this a valid number? Not NaN or infinity.
[LinkName("b2IsValidFloat")] public static extern bool IsValidFloat(float a);
/// Is this a valid vector? Not NaN or infinity.
[LinkName("b2IsValidVec2")] public static extern bool IsValidVec2(b2Vec2 v);
/// Is this a valid rotation? Not NaN or infinity. Is normalized.
[LinkName("b2IsValidRotation")] public static extern bool IsValidRotation(b2Rot q);
/// Is this a valid transform? Not NaN or infinity. Rotation is normalized.
[LinkName("b2IsValidTransform")] public static extern bool IsValidTransform(b2Transform t);
/// Is this a valid bounding box? Not Nan or infinity. Upper bound greater than or equal to lower bound.
[LinkName("b2IsValidAABB")] public static extern bool IsValidAABB(b2AABB aabb);
/// Is this a valid plane? Normal is a unit vector. Not Nan or infinity.
[LinkName("b2IsValidPlane")] public static extern bool IsValidPlane(b2Plane a);
/// @return the minimum of two integers
[LinkName("b2MinInt")] public static extern c_int MinInt(c_int a, c_int b);
/// @return the maximum of two integers
[LinkName("b2MaxInt")] public static extern c_int MaxInt(c_int a, c_int b);
/// @return the absolute value of an integer
[LinkName("b2AbsInt")] public static extern c_int AbsInt(c_int a);
/// @return an integer clamped between a lower and upper bound
[LinkName("b2ClampInt")] public static extern c_int ClampInt(c_int a, c_int lower, c_int upper);
// https://en.wikipedia.org/wiki/Floor_and_ceiling_functions
[LinkName("b2CeilingInt")] public static extern c_int CeilingInt(c_int numerator, c_int denominator);
/// @return the minimum of two floats
[LinkName("b2MinFloat")] public static extern float MinFloat(float a, float b);
/// @return the maximum of two floats
[LinkName("b2MaxFloat")] public static extern float MaxFloat(float a, float b);
/// @return the absolute value of a float
[LinkName("b2AbsFloat")] public static extern float AbsFloat(float a);
/// @return a float clamped between a lower and upper bound
[LinkName("b2ClampFloat")] public static extern float ClampFloat(float a, float lower, float upper);
/// Compute an approximate arctangent in the range [-pi, pi]
/// This is hand coded for cross-platform determinism. The atan2f
/// function in the standard library is not cross-platform deterministic.
/// Accurate to around 0.0023 degrees
[LinkName("b2Atan2")] public static extern float Atan2(float y, float x);
/// Compute the cosine and sine of an angle in radians. Implemented
/// for cross-platform determinism.
[LinkName("b2ComputeCosSin")] public static extern b2CosSin ComputeCosSin(float radians);
/// Vector dot product
[LinkName("b2Dot")] public static extern float Dot(b2Vec2 a, b2Vec2 b);
/// Vector cross product. In 2D this yields a scalar.
[LinkName("b2Cross")] public static extern float Cross(b2Vec2 a, b2Vec2 b);
/// Perform the cross product on a vector and a scalar. In 2D this produces a vector.
[LinkName("b2CrossVS")] public static extern b2Vec2 CrossVS(b2Vec2 v, float s);
/// Perform the cross product on a scalar and a vector. In 2D this produces a vector.
[LinkName("b2CrossSV")] public static extern b2Vec2 CrossSV(float s, b2Vec2 v);
/// Get a left pointing perpendicular vector. Equivalent to b2CrossSV(1.0f, v)
[LinkName("b2LeftPerp")] public static extern b2Vec2 LeftPerp(b2Vec2 v);
/// Get a right pointing perpendicular vector. Equivalent to b2CrossVS(v, 1.0f)
[LinkName("b2RightPerp")] public static extern b2Vec2 RightPerp(b2Vec2 v);
/// Vector addition
[LinkName("b2Add")] public static extern b2Vec2 Add(b2Vec2 a, b2Vec2 b);
/// Vector subtraction
[LinkName("b2Sub")] public static extern b2Vec2 Sub(b2Vec2 a, b2Vec2 b);
/// Vector negation
[LinkName("b2Neg")] public static extern b2Vec2 Neg(b2Vec2 a);
/// Vector linear interpolation
/// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
[LinkName("b2Lerp")] public static extern b2Vec2 Lerp(b2Vec2 a, b2Vec2 b, float t);
/// Component-wise multiplication
[LinkName("b2Mul")] public static extern b2Vec2 Mul(b2Vec2 a, b2Vec2 b);
/// Multiply a scalar and vector
[LinkName("b2MulSV")] public static extern b2Vec2 MulSV(float s, b2Vec2 v);
/// a + s * b
[LinkName("b2MulAdd")] public static extern b2Vec2 MulAdd(b2Vec2 a, float s, b2Vec2 b);
/// a - s * b
[LinkName("b2MulSub")] public static extern b2Vec2 MulSub(b2Vec2 a, float s, b2Vec2 b);
/// Component-wise absolute vector
[LinkName("b2Abs")] public static extern b2Vec2 Abs(b2Vec2 a);
/// Component-wise minimum vector
[LinkName("b2Min")] public static extern b2Vec2 Min(b2Vec2 a, b2Vec2 b);
/// Component-wise maximum vector
[LinkName("b2Max")] public static extern b2Vec2 Max(b2Vec2 a, b2Vec2 b);
/// Component-wise clamp vector v into the range [a, b]
[LinkName("b2Clamp")] public static extern b2Vec2 Clamp(b2Vec2 v, b2Vec2 a, b2Vec2 b);
/// Get the length of this vector (the norm)
[LinkName("b2Length")] public static extern float Length(b2Vec2 v);
/// Get the distance between two points
[LinkName("b2Distance")] public static extern float Distance(b2Vec2 a, b2Vec2 b);
/// Convert a vector into a unit vector if possible, otherwise returns the zero vector.
/// todo MSVC is not inlining this function in several places per warning 4710
[LinkName("b2Normalize")] public static extern b2Vec2 Normalize(b2Vec2 v);
/// Determines if the provided vector is normalized (norm(a) == 1).
[LinkName("b2IsNormalized")] public static extern bool IsNormalized(b2Vec2 a);
/// Convert a vector into a unit vector if possible, otherwise returns the zero vector. Also
/// outputs the length.
[LinkName("b2GetLengthAndNormalize")] public static extern b2Vec2 GetLengthAndNormalize(float* length, b2Vec2 v);
/// Normalize rotation
[LinkName("b2NormalizeRot")] public static extern b2Rot NormalizeRot(b2Rot q);
/// Integrate rotation from angular velocity
/// @param q1 initial rotation
/// @param deltaAngle the angular displacement in radians
[LinkName("b2IntegrateRotation")] public static extern b2Rot IntegrateRotation(b2Rot q1, float deltaAngle);
// dc/dt = -omega * sin(t)
// ds/dt = omega * cos(t)
// c2 = c1 - omega * h * s1
// s2 = s1 + omega * h * c1
/// Get the length squared of this vector
[LinkName("b2LengthSquared")] public static extern float LengthSquared(b2Vec2 v);
/// Get the distance squared between points
[LinkName("b2DistanceSquared")] public static extern float DistanceSquared(b2Vec2 a, b2Vec2 b);
/// Make a rotation using an angle in radians
[LinkName("b2MakeRot")] public static extern b2Rot MakeRot(float radians);
/// Make a rotation using a unit vector
[LinkName("b2MakeRotFromUnitVector")] public static extern b2Rot MakeRotFromUnitVector(b2Vec2 unitVector);
/// Compute the rotation between two unit vectors
[LinkName("b2ComputeRotationBetweenUnitVectors")] public static extern b2Rot ComputeRotationBetweenUnitVectors(b2Vec2 v1, b2Vec2 v2);
/// Is this rotation normalized?
[LinkName("b2IsNormalizedRot")] public static extern bool IsNormalizedRot(b2Rot q);
// larger tolerance due to failure on mingw 32-bit
/// Get the inverse of a rotation
[LinkName("b2InvertRot")] public static extern b2Rot InvertRot(b2Rot a);
/// 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/
[LinkName("b2NLerp")] public static extern b2Rot NLerp(b2Rot q1, b2Rot q2, float t);
/// 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
[LinkName("b2ComputeAngularVelocity")] public static extern float ComputeAngularVelocity(b2Rot q1, b2Rot q2, float inv_h);
// 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
/// Get the angle in radians in the range [-pi, pi]
[LinkName("b2Rot_GetAngle")] public static extern float Rot_GetAngle(b2Rot q);
/// Get the x-axis
[LinkName("b2Rot_GetXAxis")] public static extern b2Vec2 Rot_GetXAxis(b2Rot q);
/// Get the y-axis
[LinkName("b2Rot_GetYAxis")] public static extern b2Vec2 Rot_GetYAxis(b2Rot q);
/// Multiply two rotations: q * r
[LinkName("b2MulRot")] public static extern b2Rot MulRot(b2Rot q, b2Rot r);
// [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
/// Transpose multiply two rotations: inv(a) * b
/// This rotates a vector local in frame b into a vector local in frame a
[LinkName("b2InvMulRot")] public static extern b2Rot InvMulRot(b2Rot a, b2Rot b);
// [ ac as] * [bc -bs] = [ac*bc+qs*bs -ac*bs+as*bc]
// [-as ac] [bs bc] [-as*bc+ac*bs as*bs+ac*bc]
// s(a - b) = ac * bs - as * bc
// c(a - b) = ac * bc + as * bs
/// Relative angle between a and b
[LinkName("b2RelativeAngle")] public static extern float RelativeAngle(b2Rot a, b2Rot b);
// sin(b - a) = bs * ac - bc * as
// cos(b - a) = bc * ac + bs * as
/// Convert any angle into the range [-pi, pi]
[LinkName("b2UnwindAngle")] public static extern float UnwindAngle(float radians);
// Assuming this is deterministic
/// Rotate a vector
[LinkName("b2RotateVector")] public static extern b2Vec2 RotateVector(b2Rot q, b2Vec2 v);
/// Inverse rotate a vector
[LinkName("b2InvRotateVector")] public static extern b2Vec2 InvRotateVector(b2Rot q, b2Vec2 v);
/// Transform a point (e.g. local space to world space)
[LinkName("b2TransformPoint")] public static extern b2Vec2 TransformPoint(b2Transform t, b2Vec2 p);
/// Inverse transform a point (e.g. world space to local space)
[LinkName("b2InvTransformPoint")] public static extern b2Vec2 InvTransformPoint(b2Transform t, b2Vec2 p);
/// Multiply two transforms. If the result is applied to a point p local to frame B,
/// the transform would first convert p to a point local to frame A, then into a point
/// in the world frame.
/// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
/// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
[LinkName("b2MulTransforms")] public static extern b2Transform MulTransforms(b2Transform A, b2Transform B);
/// Creates a transform that converts a local point in frame B to a local point in frame A.
/// v2 = A.q' * (B.q * v1 + B.p - A.p)
/// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
[LinkName("b2InvMulTransforms")] public static extern b2Transform InvMulTransforms(b2Transform A, b2Transform B);
/// Multiply a 2-by-2 matrix times a 2D vector
[LinkName("b2MulMV")] public static extern b2Vec2 MulMV(b2Mat22 A, b2Vec2 v);
/// Get the inverse of a 2-by-2 matrix
[LinkName("b2GetInverse22")] public static extern b2Mat22 GetInverse22(b2Mat22 A);
/// Solve A * x = b, where b is a column vector. This is more efficient
/// than computing the inverse in one-shot cases.
[LinkName("b2Solve22")] public static extern b2Vec2 Solve22(b2Mat22 A, b2Vec2 b);
/// Does a fully contain b
[LinkName("b2AABB_Contains")] public static extern bool AABB_Contains(b2AABB a, b2AABB b);
/// Get the center of the AABB.
[LinkName("b2AABB_Center")] public static extern b2Vec2 AABB_Center(b2AABB a);
/// Get the extents of the AABB (half-widths).
[LinkName("b2AABB_Extents")] public static extern b2Vec2 AABB_Extents(b2AABB a);
/// Union of two AABBs
[LinkName("b2AABB_Union")] public static extern b2AABB AABB_Union(b2AABB a, b2AABB b);
/// Do a and b overlap
[LinkName("b2AABB_Overlaps")] public static extern bool AABB_Overlaps(b2AABB a, b2AABB b);
/// Compute the bounding box of an array of circles
[LinkName("b2MakeAABB")] public static extern b2AABB MakeAABB(b2Vec2* points, c_int count, float radius);
/// Signed separation of a point from a plane
[LinkName("b2PlaneSeparation")] public static extern float PlaneSeparation(b2Plane plane, b2Vec2 point);
/// One-dimensional mass-spring-damper simulation. Returns the new velocity given the position and time step.
/// You can then compute the new position using:
/// position += timeStep * newVelocity
/// This drives towards a zero position. By using implicit integration we get a stable solution
/// that doesn't require transcendental functions.
[LinkName("b2SpringDamper")] public static extern float SpringDamper(float hertz, float dampingRatio, float position, float velocity, float timeStep);
/// Box2D bases all length units on meters, but you may need different units for your game.
/// You can set this value to use different units. This should be done at application startup
/// and only modified once. Default value is 1.
/// For example, if your game uses pixels for units you can use pixels for all length values
/// sent to Box2D. There should be no extra cost. However, Box2D has some internal tolerances
/// and thresholds that have been tuned for meters. By calling this function, Box2D is able
/// to adjust those tolerances and thresholds to improve accuracy.
/// A good rule of thumb is to pass the height of your player character to this function. So
/// if your player character is 32 pixels high, then pass 32 to this function. Then you may
/// confidently use pixels for all the length values sent to Box2D. All length values returned
/// from Box2D will also be pixels because Box2D does not do any scaling internally.
/// However, you are now on the hook for coming up with good values for gravity, density, and
/// forces.
/// @warning This must be modified before any calls to Box2D
[LinkName("b2SetLengthUnitsPerMeter")] public static extern void SetLengthUnitsPerMeter(float lengthUnits);
/// Get the current length units per meter.
[LinkName("b2GetLengthUnitsPerMeter")] public static extern float GetLengthUnitsPerMeter();
}
/**@}*/
/**
* @defgroup math_cpp C++ Math
* @brief Math operator overloads for C++
*
* See math_functions.h for details.
* @{
*/
/// Unary add one vector to another
/// Unary subtract one vector from another
/// Unary multiply a vector by a scalar
/// Unary negate a vector
/// Binary vector addition
/// Binary vector subtraction
/// Binary scalar and vector multiplication
/// Binary scalar and vector multiplication
/// Binary vector equality
/// Binary vector inequality
/**@}*/
+1519
View File
File diff suppressed because it is too large Load Diff