From 2e9a4b57905868274bef5c749c8117c130ded453 Mon Sep 17 00:00:00 2001 From: Kenton Hamaluik Date: Sat, 15 Feb 2020 15:51:08 -0700 Subject: [PATCH] added intersect result --- CHANGELOG.md | 16 +++++- README.md | 21 ++++--- bench/Main.hx | 17 +++--- docs/404.html | 2 +- docs/headbutt/threed/Headbutt.html | 5 +- docs/headbutt/threed/Shape.html | 2 +- docs/headbutt/threed/TestResult.html | 13 +++++ docs/headbutt/threed/index.html | 4 +- docs/headbutt/threed/shapes/Box.html | 2 +- docs/headbutt/threed/shapes/Line.html | 2 +- docs/headbutt/threed/shapes/Polyhedron.html | 2 +- docs/headbutt/threed/shapes/Sphere.html | 2 +- docs/headbutt/threed/shapes/index.html | 2 +- docs/headbutt/twod/Headbutt.html | 11 ++-- docs/headbutt/twod/IntersectResult.html | 10 ++++ docs/headbutt/twod/Shape.html | 2 +- docs/headbutt/twod/TestResult.html | 13 +++++ docs/headbutt/twod/index.html | 4 +- docs/headbutt/twod/shapes/Circle.html | 2 +- docs/headbutt/twod/shapes/Line.html | 2 +- docs/headbutt/twod/shapes/Polygon.html | 2 +- docs/headbutt/twod/shapes/Rectangle.html | 2 +- docs/headbutt/twod/shapes/index.html | 2 +- docs/index.html | 2 +- docs/nav.js | 2 +- dox.hxml | 8 ++- haxelib.json | 4 +- src/headbutt/twod/Headbutt.hx | 19 +++++-- src/headbutt/twod/IntersectResult.hx | 63 +++++++++++++++++++++ test/TestHeadbutt2D.hx | 21 +++---- 30 files changed, 199 insertions(+), 60 deletions(-) create mode 100644 docs/headbutt/threed/TestResult.html create mode 100644 docs/headbutt/twod/IntersectResult.html create mode 100644 docs/headbutt/twod/TestResult.html create mode 100644 src/headbutt/twod/IntersectResult.hx diff --git a/CHANGELOG.md b/CHANGELOG.md index d4b6711..caf4456 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.6.0] - 2020-02-15 +### Added +- Added `TestResult` type which is returned from `test()` and can be checked directly + for collisions or passed to `intersect()` to further calculate an intersection +- Added `IntersectResult` type which is returned from `intersect()` and can be used + to calculate collision normals, separation distances, etc +- Added `Headbutt.testAndIntersect()` function which is a shortcut for testing and + then calculating the intersection if a collision is found + +### Changed +- Changed `Headbutt` interface from interacting with an object with internal state + to static pure functions (i.e. call `Headbutt.test()` instead of `new Headbutt().test()`) + ## [0.5.0] - 2020-02-15 ### Added - Added transformation support to all provided shape classes @@ -28,7 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.3.0] - 2017-07-01 - Initial release -[Unreleased]: https://github.com/hamaluik/headbutt/compare/v0.5.0...HEAD +[Unreleased]: https://github.com/hamaluik/headbutt/compare/v0.6.0...HEAD +[0.6.0]: https://github.com/hamaluik/headbutt/compare/v0.4.0...v0.6.0 [0.5.0]: https://github.com/hamaluik/headbutt/compare/v0.4.0...v0.5.0 [0.4.0]: https://github.com/hamaluik/headbutt/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/hamaluik/headbutt/releases/tag/v0.3.0 diff --git a/README.md b/README.md index b85a9e7..e4dbbef 100644 --- a/README.md +++ b/README.md @@ -20,24 +20,31 @@ Create either 2D shapes or 3D shapes by implementing the appropriate interface: * `Box` * `Polyhedron` -Then, instantiate an instance of the appropriate `Headbutt`: +Apply generic transformations to shapes: ```haxe -var hb2 = new headbutt.twod.Headbutt(); -var hb3 = new headbutt.threed.Headbutt(); +var box = new Box(new Vec3(0.5, 0.5, 0.5)); +box.transform = GLM.transform( + new Vec3(5, -1, 3), // translation + Quat.fromEuler(Math.PI / 4, 0, Math.PI / 3, new Quat()), // rotation + new Vec3(2, 1, 4) // scale +); ``` -Next, check shapes for intersections: +Then, check shapes for intersections: ```haxe -if(hb2.test(shapeA, shapeB)) { /*...*/ } -if(hb3.test(objectA, objectB)) { /*...*/ } +if(headbutt.twod.Headbutt.test(shapeA, shapeB)) { /*...*/ } +if(headbutt.threed.Headbutt.test(objectA, objectB)) { /*...*/ } ``` Alternatively, calculate intersections (**note:** intersection calculations haven't been implemented in 3D yet!): ```haxe -var penetration: Null = hb2.intersect(shapeA, shapeB); +var testResult = headbutt.twod.Headbutt.test(shapeA, shapeB); +var intersection = headbutt.twod.Headbutt.intersect(testResult); +// or: +var intersection = headbutt.twod.Headbutt.testAndIntersect(shapeA, shapeB); ``` ## API diff --git a/bench/Main.hx b/bench/Main.hx index 75455c6..d9c782c 100644 --- a/bench/Main.hx +++ b/bench/Main.hx @@ -67,7 +67,6 @@ class Main { } public static function main(): Void { - var hb = new Headbutt(); println('| Test | Intersect | Headbutt (μs/iter) |'); println('|:-----|:---------:|---------:|-------:|'); @@ -77,13 +76,13 @@ class Main { var line_line_int_hb = new Benchmark(); line_line_int_hb.run(function() { - hb.test(lineA, lineB); + Headbutt.test(lineA, lineB); }); println('| line/line | ✔ | ${line_line_int_hb.toString()} |'); var line_line_noint_hb = new Benchmark(); line_line_noint_hb.run(function() { - hb.test(lineA, lineC); + Headbutt.test(lineA, lineC); }); println('| line/line | ✗ | ${line_line_noint_hb.toString()} |'); @@ -93,31 +92,31 @@ class Main { var circ_circ_int_hb = new Benchmark(); circ_circ_int_hb.run(function() { - hb.test(circleA, circleB); + Headbutt.test(circleA, circleB); }); println('| circ/circ | ✔ | ${circ_circ_int_hb.toString()} |'); var circ_circ_noint_hb = new Benchmark(); circ_circ_noint_hb.run(function() { - hb.test(circleA, circleC); + Headbutt.test(circleA, circleC); }); println('| circ/circ | ✗ | ${circ_circ_noint_hb.toString()} |'); var pentA = new headbutt.twod.shapes.Polygon([new Vec2(0, 1), new Vec2(1, 0.5), new Vec2(1, -1), new Vec2(-1, -1), new Vec2(-1, 0.5)]); var pentB = new headbutt.twod.shapes.Polygon([new Vec2(0, 1), new Vec2(1, 0.5), new Vec2(1, -1), new Vec2(-1, -1), new Vec2(-1, 0.5)]); - pentB.set_trs(new Vec2(0.5, 0), 0, new Vec2(1, 1)); + pentB.setTransform(new Vec2(0.5, 0), 0, new Vec2(1, 1)); var pentC = new headbutt.twod.shapes.Polygon([new Vec2(0, 1), new Vec2(1, 0.5), new Vec2(1, -1), new Vec2(-1, -1), new Vec2(-1, 0.5)]); - pentC.set_trs(new Vec2(5, 0), 0, new Vec2(1, 1)); + pentC.setTransform(new Vec2(5, 0), 0, new Vec2(1, 1)); var pent_pent_int_hb = new Benchmark(); pent_pent_int_hb.run(function() { - hb.test(pentA, pentB); + Headbutt.test(pentA, pentB); }); println('| pent/pent | ✔ | ${pent_pent_int_hb.toString()} |'); var pent_pent_noint_hb = new Benchmark(); pent_pent_noint_hb.run(function() { - hb.test(pentA, pentC); + Headbutt.test(pentA, pentC); }); println('| pent/pent | ✗ | ${pent_pent_noint_hb.toString()} |'); } diff --git a/docs/404.html b/docs/404.html index 36bbe51..b21ede5 100644 --- a/docs/404.html +++ b/docs/404.html @@ -1 +1 @@ -File not found - Headbutt

404 Page not found

Page not found, sorry.

\ No newline at end of file +File not found - Headbutt

404 Page not found

Page not found, sorry.

\ No newline at end of file diff --git a/docs/headbutt/threed/Headbutt.html b/docs/headbutt/threed/Headbutt.html index 8485239..7cc1585 100644 --- a/docs/headbutt/threed/Headbutt.html +++ b/docs/headbutt/threed/Headbutt.html @@ -6,8 +6,7 @@ display: inline-block; float: none; text-shadow: 0 0 0 transparent; -

Constructor

new ()

Create a new Headbutt instance. Headbutt needs to be instantiated because -internally it stores state. This may change in the future.

Variables

@:value(20)maxIterations:Int = 20

The maximum number of simplex evolution iterations before we accept the +

Static variables

@:value(20)staticMAX_ITERATIONS:Int = 20

The maximum number of simplex evolution iterations before we accept the given simplex. For non-curvy shapes, this can be low. Curvy shapes potentially require higher numbers, but this can introduce significant slow-downs at -the gain of not much accuracy.

Methods

test (shapeA:Shape, shapeB:Shape):Bool

Given two convex shapes, test whether they overlap or not

Parameters:

shapeA
shapeB

Returns:

Bool

\ No newline at end of file +the gain of not much accuracy.

Static methods

statictest (shapeA:Shape, shapeB:Shape):Bool

Given two convex shapes, test whether they overlap or not

Parameters:

shapeA
shapeB

Returns:

Bool

\ No newline at end of file diff --git a/docs/headbutt/threed/Shape.html b/docs/headbutt/threed/Shape.html index f70a531..4c4727a 100644 --- a/docs/headbutt/threed/Shape.html +++ b/docs/headbutt/threed/Shape.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

Implement a shape to use the object in Headbutt calculations

Variables

read onlycentre:Vec3

The origin / centre of the shape.

Methods

support (direction:Vec3):Vec3

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file diff --git a/docs/headbutt/threed/TestResult.html b/docs/headbutt/threed/TestResult.html new file mode 100644 index 0000000..ebbfaf1 --- /dev/null +++ b/docs/headbutt/threed/TestResult.html @@ -0,0 +1,13 @@ + + + +headbutt.threed.TestResult - Headbutt

The result of a collision test, which can be coerced into a Bool for easy +collision checking, or fed into Headbutt.intersect to calculate penetration +vectors

\ No newline at end of file diff --git a/docs/headbutt/threed/index.html b/docs/headbutt/threed/index.html index 43d62b6..915faaa 100644 --- a/docs/headbutt/threed/index.html +++ b/docs/headbutt/threed/index.html @@ -6,4 +6,6 @@ display: inline-block; float: none; text-shadow: 0 0 0 transparent; -

headbutt.threed

A GJK and EPA collision engine made with pure Haxe.

..
shapes
Headbutt

Shape

Implement a shape to use the object in Headbutt calculations

\ No newline at end of file +

headbutt.threed

A GJK and EPA collision engine made with pure Haxe.

..
shapes
Headbutt

Shape

Implement a shape to use the object in Headbutt calculations

TestResult

The result of a collision test, which can be coerced into a Bool for easy +collision checking, or fed into Headbutt.intersect to calculate penetration +vectors

\ No newline at end of file diff --git a/docs/headbutt/threed/shapes/Box.html b/docs/headbutt/threed/shapes/Box.html index 693f389..c81ee5c 100644 --- a/docs/headbutt/threed/shapes/Box.html +++ b/docs/headbutt/threed/shapes/Box.html @@ -9,4 +9,4 @@ text-shadow: 0 0 0 transparent;

A box is basically the same as a polyhedron, but with specifically 8 vertices which are at right angles from each other

Constructor

new (size:Vec3)

Create a new box with the given size

Parameters:

size

the width, height, and length of the box

Variables

read onlycentre:Vec3

The centre of the box (derived from the transform)

transform:Mat4

A 3-dimensional transform to apply to each vertex when calculating the simplex

Methods

resize (size:Vec3):Void

Resize the box's local coordinates

Parameters:

size

the width, height, and length of the box

setTransform (position:Vec3, rotation:Quat, scale:Vec3):Void

Change the transform by supplying translation, rotation, and scale components

Parameters:

position

the new centre of the shape

rotation

the rotation of the shape

scale

the scale of the shape

support (direction:Vec3):Vec3

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file diff --git a/docs/headbutt/threed/shapes/Line.html b/docs/headbutt/threed/shapes/Line.html index 70c7585..686552c 100644 --- a/docs/headbutt/threed/shapes/Line.html +++ b/docs/headbutt/threed/shapes/Line.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

Two points form a line in 3D

Constructor

new (start:Vec3, end:Vec3)

Create a new line segment from start to end

Parameters:

start

one end of the line

end

the other end of the line

Variables

read onlycentre:Vec3

The centre of the line, really the midpoint

end:Vec3

The second point of the line in global coordinates

start:Vec3

The first point of the line in global coordinates

Methods

support (direction:Vec3):Vec3

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file diff --git a/docs/headbutt/threed/shapes/Polyhedron.html b/docs/headbutt/threed/shapes/Polyhedron.html index fd1433f..30ebe24 100644 --- a/docs/headbutt/threed/shapes/Polyhedron.html +++ b/docs/headbutt/threed/shapes/Polyhedron.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

A collection of points in 3D, which together define a convex solid

Constructor

new (vertices:Array<Vec3>)

Create a new polygon

Parameters:

origin

The location of the polygon in global coordinates

vertices

The locations of the vertices in local coordinates

Variables

read onlycentre:Vec3

The centre of the polyhedron (derived from the transform)

transform:Mat4

A 3-dimensional transform to apply to each vertex when calculating the simplex

vertices:Array<Vec3>

The vertices in the local coordinate space

Methods

setTransform (position:Vec3, rotation:Quat, scale:Vec3):Void

Change the transform by supplying translation, rotation, and scale components

Parameters:

position

the new centre of the shape

rotation

the rotation of the shape

scale

the scale of the shape

support (direction:Vec3):Vec3

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file diff --git a/docs/headbutt/threed/shapes/Sphere.html b/docs/headbutt/threed/shapes/Sphere.html index 47d9c1c..9c7bf57 100644 --- a/docs/headbutt/threed/shapes/Sphere.html +++ b/docs/headbutt/threed/shapes/Sphere.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

A 3D sphere

Constructor

new (position:Vec3, radius:Float)

Create a new sphere

Parameters:

position

The centre of the sphere in global coordinates

radius

The radius of the sphere

Variables

read onlycentre:Vec3

The centre of the sphere

position:Vec3

Where the sphere is located / the centre of it

radius:Float

How large the sphere is, half the diameter

Methods

support (direction:Vec3):Vec3

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec3

\ No newline at end of file diff --git a/docs/headbutt/threed/shapes/index.html b/docs/headbutt/threed/shapes/index.html index 59be6a9..376ed1a 100644 --- a/docs/headbutt/threed/shapes/index.html +++ b/docs/headbutt/threed/shapes/index.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

headbutt.threed.shapes

A GJK and EPA collision engine made with pure Haxe.

..
Box

A box is basically the same as a polyhedron, but with specifically 8 vertices which are at right angles -from each other

Line

Two points form a line in 3D

Polyhedron

A collection of points in 3D, which together define a convex solid

Sphere

A 3D sphere

\ No newline at end of file +from each other

Line

Two points form a line in 3D

Polyhedron

A collection of points in 3D, which together define a convex solid

Sphere

A 3D sphere

\ No newline at end of file diff --git a/docs/headbutt/twod/Headbutt.html b/docs/headbutt/twod/Headbutt.html index 389f726..499c816 100644 --- a/docs/headbutt/twod/Headbutt.html +++ b/docs/headbutt/twod/Headbutt.html @@ -1,14 +1,15 @@ -headbutt.twod.Headbutt - Headbutt

Constructor

new ()

Create a new Headbutt instance. Headbutt needs to be instantiated because -internally it stores state. This may change in the future.

Variables

@:value(20)maxIterations:Int = 20

The maximum number of simplex evolution iterations before we accept the +

Implementations of the GJK and EPA algorithms

Static variables

@:value(0.00001)staticINTERSECTION_EPSILON:Float = 0.00001

How accurate do intersection calculations need to be when using expanding polytopes

@:value(32)staticMAX_INTERSECTION_ITERATIONS:Int = 32

The maximum number of iterations to employ when running the EPA algoritm, usually +required to be large-ish for circles

@:value(20)staticMAX_ITERATIONS:Int = 20

The maximum number of simplex evolution iterations before we accept the given simplex. For non-curvy shapes, this can be low. Curvy shapes potentially require higher numbers, but this can introduce significant slow-downs at -the gain of not much accuracy.

Methods

intersect (shapeA:Shape, shapeB:Shape):Null<Vec2>

Given two shapes, test whether they overlap or not. If they don't, returns -null. If they do, calculates the penetration vector and returns it.

Parameters:

shapeA
shapeB

Returns:

Null

test (shapeA:Shape, shapeB:Shape):Bool

Given two convex shapes, test whether they overlap or not

Parameters:

shapeA
shapeB

Returns:

Bool

\ No newline at end of file +the gain of not much accuracy.

Static methods

staticintersect (testResult:TestResult):Null<IntersectResult>

Given two shapes, test whether they overlap or not. If they don't, returns +null. If they do, calculates the penetration vector and returns it.

Parameters:

testResult

The return value from test

Returns:

Null

statictest (shapeA:Shape, shapeB:Shape):TestResult

Given two convex shapes, test whether they overlap or not

Parameters:

shapeA
shapeB

Returns:

Bool

staticinlinetestAndIntersect (shapeA:Shape, shapeB:Shape):Null<IntersectResult>

Shortcut for calling intersect(test(...)), will return null if the shapes +aren't colliding, otherwise will return how the shapes overlap

Parameters:

shapeA
shapeB

Returns:

Null

\ No newline at end of file diff --git a/docs/headbutt/twod/IntersectResult.html b/docs/headbutt/twod/IntersectResult.html new file mode 100644 index 0000000..5be1a72 --- /dev/null +++ b/docs/headbutt/twod/IntersectResult.html @@ -0,0 +1,10 @@ + + + +headbutt.twod.IntersectResult - Headbutt

The result of calculating the intersection between two shapes

Variables

read onlyintersection:Vec2

A vector describing the direction and magnitude of the overlap between the +shapes

read onlynormal:Vec2

The normal of the collision, just a normalized version of intersection

read onlyoverlapDistance:Float

How much the two shapes are overlapping, just the magnitude of intersection

read onlyshapeA:Shape

The same shapeA that was supplied to test()

read onlyshapeB:Shape

The same shapeB that was supplied to test()

\ No newline at end of file diff --git a/docs/headbutt/twod/Shape.html b/docs/headbutt/twod/Shape.html index 11eb0dc..8917f5d 100644 --- a/docs/headbutt/twod/Shape.html +++ b/docs/headbutt/twod/Shape.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

Implement a shape to use the object in Headbutt calculations

Variables

read onlycentre:Vec2

The centre of the shape, in global coordinates

Methods

support (direction:Vec2):Vec2

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to find the support vertex in

Returns:

Vec2

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to find the support vertex in

Returns:

Vec2

\ No newline at end of file diff --git a/docs/headbutt/twod/TestResult.html b/docs/headbutt/twod/TestResult.html new file mode 100644 index 0000000..562bd58 --- /dev/null +++ b/docs/headbutt/twod/TestResult.html @@ -0,0 +1,13 @@ + + + +headbutt.twod.TestResult - Headbutt

The result of a collision test, which can be coerced into a Bool for easy +collision checking, or fed into Headbutt.intersect to calculate penetration +vectors

\ No newline at end of file diff --git a/docs/headbutt/twod/index.html b/docs/headbutt/twod/index.html index 9721f7b..9f8b584 100644 --- a/docs/headbutt/twod/index.html +++ b/docs/headbutt/twod/index.html @@ -6,4 +6,6 @@ display: inline-block; float: none; text-shadow: 0 0 0 transparent; -

headbutt.twod

A GJK and EPA collision engine made with pure Haxe.

..
shapes
Headbutt

Shape

Implement a shape to use the object in Headbutt calculations

\ No newline at end of file +

headbutt.twod

A GJK and EPA collision engine made with pure Haxe.

..
shapes
Headbutt

Implementations of the GJK and EPA algorithms

IntersectResult

The result of calculating the intersection between two shapes

Shape

Implement a shape to use the object in Headbutt calculations

TestResult

The result of a collision test, which can be coerced into a Bool for easy +collision checking, or fed into Headbutt.intersect to calculate penetration +vectors

\ No newline at end of file diff --git a/docs/headbutt/twod/shapes/Circle.html b/docs/headbutt/twod/shapes/Circle.html index 0fe60ac..c994395 100644 --- a/docs/headbutt/twod/shapes/Circle.html +++ b/docs/headbutt/twod/shapes/Circle.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

A circle has a centre and a radius

Constructor

new (position:Vec2, radius:Float)

Create a new circle

Parameters:

position

The centre of the circle in global coordinates

radius

The radius of the circle

Variables

read onlycentre:Vec2

The centre of the circle, in global coordinates

position:Vec2

Where the circle is located / the centre of it

radius:Float

How large the circle is, half the diameter

Methods

support (direction:Vec2):Vec2

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to find the support vertex in

Returns:

Vec2

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to find the support vertex in

Returns:

Vec2

\ No newline at end of file diff --git a/docs/headbutt/twod/shapes/Line.html b/docs/headbutt/twod/shapes/Line.html index 01f65cf..fdf4eb5 100644 --- a/docs/headbutt/twod/shapes/Line.html +++ b/docs/headbutt/twod/shapes/Line.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

Two points form a line in 2D

Constructor

new (start:Vec2, end:Vec2)

Create a new line segment from start to end

Parameters:

start

one end of the line

end

the other end of the line

Variables

read onlycentre:Vec2

The centre of the line, really the midpoint

end:Vec2

The second point of the line in global coordinates

start:Vec2

The first point of the line in global coordinates

Methods

support (direction:Vec2):Vec2

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec2

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to check

Returns:

Vec2

\ No newline at end of file diff --git a/docs/headbutt/twod/shapes/Polygon.html b/docs/headbutt/twod/shapes/Polygon.html index 7f0ec6b..57d1afe 100644 --- a/docs/headbutt/twod/shapes/Polygon.html +++ b/docs/headbutt/twod/shapes/Polygon.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

A collection of points in 2D, which together define a convex solid

Constructor

new (vertices:Array<Vec2>)

Create a new polygon

Parameters:

vertices

The locations of the vertices in local coordinates

Variables

read onlycentre:Vec2

The centre of the polygon (derived from the transform)

transform:Mat3

A 2-dimensional transform to apply to each vertex when calculating the simplex

vertices:Array<Vec2>

The vertices in the local coordinate space

Methods

setTransform (position:Vec2, rotation:Float, scale:Vec2):Void

Change the transform by supplying translation, rotation, and scale components

Parameters:

position

the new centre of the shape

rotation

the rotation of the shape

scale

the scale of the shape

support (direction:Vec2):Vec2

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to find the support vertex in

Returns:

Vec2

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to find the support vertex in

Returns:

Vec2

\ No newline at end of file diff --git a/docs/headbutt/twod/shapes/Rectangle.html b/docs/headbutt/twod/shapes/Rectangle.html index a1bf4b3..861e464 100644 --- a/docs/headbutt/twod/shapes/Rectangle.html +++ b/docs/headbutt/twod/shapes/Rectangle.html @@ -9,4 +9,4 @@ text-shadow: 0 0 0 transparent;

A rectangle is basically the same as a polygon, but with specifically 4 vertices which are at right angles from each other

Constructor

new (size:Vec2)

Create a new rectangle with the given size

Parameters:

size

the width and height of the rectangle

Variables

read onlycentre:Vec2

The centre of the polygon (derived from the transform)

transform:Mat3

A 2-dimensional transform to apply to each vertex when calculating the simplex

Methods

resize (size:Vec2):Void

Resize the rectangle's local coordinates

Parameters:

size

the width and height of the rectangle

setTransform (position:Vec2, rotation:Float, scale:Vec2):Void

Change the transform by supplying translation, rotation, and scale components

Parameters:

position

the new centre of the shape

rotation

the rotation of the shape

scale

the scale of the shape

support (direction:Vec2):Vec2

Given a direction in global coordinates, return the vertex (in global coordinates) -that is the furthest in that direction

Parameters:

direction

the direction to find the support vertex in

Returns:

Vec2

\ No newline at end of file +that is the furthest in that direction

Parameters:

direction

the direction to find the support vertex in

Returns:

Vec2

\ No newline at end of file diff --git a/docs/headbutt/twod/shapes/index.html b/docs/headbutt/twod/shapes/index.html index d4e7856..a5954ad 100644 --- a/docs/headbutt/twod/shapes/index.html +++ b/docs/headbutt/twod/shapes/index.html @@ -7,4 +7,4 @@ float: none; text-shadow: 0 0 0 transparent;

headbutt.twod.shapes

A GJK and EPA collision engine made with pure Haxe.

..
Circle

A circle has a centre and a radius

Line

Two points form a line in 2D

Polygon

A collection of points in 2D, which together define a convex solid

Rectangle

A rectangle is basically the same as a polygon, but with specifically 4 vertices which are at right angles from -each other

\ No newline at end of file +each other

\ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 088e8c0..884c458 100644 --- a/docs/index.html +++ b/docs/index.html @@ -6,4 +6,4 @@ display: inline-block; float: none; text-shadow: 0 0 0 transparent; -

headbutt version 0.5.0

A GJK and EPA collision engine made with pure Haxe.

threed
twod
\ No newline at end of file +

headbutt version 0.6.0

A GJK and EPA collision engine made with pure Haxe.

threed
twod
\ No newline at end of file diff --git a/docs/nav.js b/docs/nav.js index 19dccd3..a634a28 100644 --- a/docs/nav.js +++ b/docs/nav.js @@ -1 +1 @@ -var navContent=''; \ No newline at end of file +var navContent=''; \ No newline at end of file diff --git a/dox.hxml b/dox.hxml index 8a095f7..1950b51 100644 --- a/dox.hxml +++ b/dox.hxml @@ -2,19 +2,23 @@ -lib glm headbutt.twod.Shape +headbutt.twod.TestResult +headbutt.twod.IntersectResult headbutt.twod.shapes.Circle headbutt.twod.shapes.Line headbutt.twod.shapes.Rectangle headbutt.twod.shapes.Polygon headbutt.twod.Headbutt headbutt.threed.Shape +headbutt.threed.TestResult headbutt.threed.shapes.Sphere headbutt.threed.shapes.Line headbutt.threed.shapes.Box headbutt.threed.shapes.Polyhedron headbutt.threed.Headbutt --xml dox.xml +-D doc-gen +-xml docs/dox.xml --next --cmd haxelib run dox -i . -o docs --title "Headbutt" --toplevel-package "headbutt" -D version "0.5.0" -D source-path "https://github.com/hamaluik/headbutt/tree/master/src" -D description "A GJK and EPA collision engine made with pure Haxe." \ No newline at end of file +-cmd haxelib run dox -i docs -o docs --title "Headbutt" --toplevel-package "headbutt" -D version "0.6.0" -D source-path "https://github.com/hamaluik/headbutt/tree/master/src" -D description "A GJK and EPA collision engine made with pure Haxe." \ No newline at end of file diff --git a/haxelib.json b/haxelib.json index feaf6f0..97afcd5 100644 --- a/haxelib.json +++ b/haxelib.json @@ -5,8 +5,8 @@ "classPath": "src", "tags": ["cross", "utility"], "description": "GJK and EPA based collision detection and intersection calculation", - "version": "0.5.0", - "releasenote": "Added transforms to shapes", + "version": "0.6.0", + "releasenote": "Changed Headbutt interface to use static pure public functions", "contributors": ["hamaluik"], "dependencies": { "glm": "" diff --git a/src/headbutt/twod/Headbutt.hx b/src/headbutt/twod/Headbutt.hx index 4eaeb2f..5b04e28 100644 --- a/src/headbutt/twod/Headbutt.hx +++ b/src/headbutt/twod/Headbutt.hx @@ -206,9 +206,9 @@ class Headbutt { Given two shapes, test whether they overlap or not. If they don't, returns `null`. If they do, calculates the penetration vector and returns it. @param testResult The return value from `test` - @return Null + @return Null */ - public static function intersect(testResult: TestResult): Null { + public static function intersect(testResult: TestResult): Null { if(!testResult.colliding) { // if we're not intersecting, return null return null; @@ -232,13 +232,24 @@ class Headbutt { Vec2.multiplyScalar(intersection, distance, intersection); if(Math.abs(distance - edge.distance) <= INTERSECTION_EPSILON) { - return intersection; + return new IntersectResult(intersection, testResult.shapeA, testResult.shapeB); } else { testResult.simplex.insert(edge.index, support); } } - return intersection; + return new IntersectResult(intersection, testResult.shapeA, testResult.shapeB); + } + + /** + Shortcut for calling `intersect(test(...))`, will return `null` if the shapes + **aren't** colliding, otherwise will return how the shapes overlap + @param shapeA + @param shapeB + @return Null + **/ + inline public static function testAndIntersect(shapeA: Shape, shapeB: Shape): Null { + return intersect(test(shapeA, shapeB)); } } \ No newline at end of file diff --git a/src/headbutt/twod/IntersectResult.hx b/src/headbutt/twod/IntersectResult.hx new file mode 100644 index 0000000..83e0522 --- /dev/null +++ b/src/headbutt/twod/IntersectResult.hx @@ -0,0 +1,63 @@ +/* + * Apache License, Version 2.0 + * + * Copyright (c) 2020 Kenton Hamaluik + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package headbutt.twod; + +import glm.Vec2; + +/** + The result of calculating the intersection between two shapes +**/ +@:allow(headbutt.twod.Headbutt) +class IntersectResult { + /** + A vector describing the direction and magnitude of the overlap between the + shapes + **/ + public var intersection(default, null): Vec2; + + /** + The same `shapeA` that was supplied to `test()` + **/ + public var shapeA(default, null): Shape; + + /** + The same `shapeB` that was supplied to `test()` + **/ + public var shapeB(default, null): Shape; + + /** + The normal of the collision, just a normalized version of `intersection` + **/ + public var normal(default, null): Vec2; + + /** + How much the two shapes are overlapping, just the magnitude of `intersection` + **/ + public var overlapDistance(default, null): Float; + + // TODO: contact points + + function new(intersection: Vec2, shapeA: Shape, shapeB: Shape) { + this.intersection = intersection; + this.shapeA = shapeA; + this.shapeB = shapeB; + + this.normal = Vec2.normalize(intersection, new Vec2()); + this.overlapDistance = intersection.length(); + + } +} \ No newline at end of file diff --git a/test/TestHeadbutt2D.hx b/test/TestHeadbutt2D.hx index c800fd0..d7b1eef 100644 --- a/test/TestHeadbutt2D.hx +++ b/test/TestHeadbutt2D.hx @@ -1,3 +1,4 @@ +import headbutt.twod.IntersectResult; import glm.Vec3; import glm.Mat3; import headbutt.twod.Headbutt; @@ -147,32 +148,32 @@ class TestHeadbutt2D extends BuddySuite { var squareB: Rectangle = new Rectangle(new Vec2(2, 2)); squareB.setTransform(new Vec2(1.5, 0), 0, new Vec2(1, 1)); - var intersection: Null = Headbutt.intersect(Headbutt.test(squareA, squareB)); - intersection.should.not.be(null); - intersection.x.should.beCloseTo(0.5); - intersection.y.should.beCloseTo(0); + var result: Null = Headbutt.intersect(Headbutt.test(squareA, squareB)); + result.should.not.be(null); + result.intersection.x.should.beCloseTo(0.5); + result.intersection.y.should.beCloseTo(0); }); it('should calculate the intersection of two circles', { var circA: Circle = new Circle(new Vec2(0, 0), 1); var circB: Circle = new Circle(new Vec2(1, 1), 0.5); - var intersection: Null = Headbutt.intersect(Headbutt.test(circA, circB)); + var result: Null = Headbutt.intersect(Headbutt.test(circA, circB)); // calculate the intersection manually var ix: Float = circA.radius * Math.cos(Math.PI / 4) - (circB.radius * Math.cos(5 * Math.PI / 4) + circB.centre.x); var iy: Float = circA.radius * Math.sin(Math.PI / 4) - (circB.radius * Math.sin(5 * Math.PI / 4) + circB.centre.y); - intersection.x.should.beCloseTo(ix); - intersection.y.should.beCloseTo(iy); + result.intersection.x.should.beCloseTo(ix); + result.intersection.y.should.beCloseTo(iy); }); it('should calculate the intersection of a line and square', { var square: Rectangle = new Rectangle(new Vec2(2, 2)); var line: Line = new Line(new Vec2(0.5, 0), new Vec2(3.5, 3)); - var intersection: Null = Headbutt.intersect(Headbutt.test(square, line)); - intersection.x.should.be(0.5); - intersection.y.should.be(0); + var result: Null = Headbutt.intersect(Headbutt.test(square, line)); + result.intersection.x.should.be(0.5); + result.intersection.y.should.be(0); }); it('should collide between a rotated square and a not', {