Cute c2

From GiderosMobile

Supported platforms: Platform android.pngPlatform ios.pngPlatform mac.pngPlatform pc.pngPlatform html5.pngPlatform winrt.pngPlatform win32.pngPlatform linux.png
Available since: Gideros 2022.6

Description

cute_c2 implements 2D collision detection routines that test for overlap, and optionally can find the collision manifold. The manifold contains all necessary information to prevent shapes from inter-penetrating, which is useful for character controllers, general physics simulation, and user-interface programming.

cute_c2 LUA binding for Gideros by rrraptor ;-)

To add the cute_c2 plugin:

require "CuteC2"

cute_c2 is available under 2 licenses: zlib license and Public Domain (www.unlicense.org) (you may choose the one you like) and is available at https://github.com/RandyGaul/cute_headers

Global functions

Objects

-- x, y (numbers): position 
-- r (number): radius
Circle = CuteC2.circle(x, y, r)

-- minX, minY (numbers): top left corner position 
-- maxX, maxY (numbers): bottom right corner position
-- anchor point is in top left corner
AABB = CuteC2.aabb(minX, minY, maxX, maxY)

-- x, y (numbers): position 
-- h (number): height
-- r (number): radius
Capsule = CuteC2.capsule(x, y, h, r)

-- points (table): table of x/y pairs (example: {0,0, 100,50, 60,30, 40,90})
-- !!!IMPORTANT NOTE!!! maximum amount of points pairs is 8, everything beyond this limit is ignored
Poly = CuteC2.poly(points)

-- x1, y1 (numbers): start position
-- x2, y2 (numbers): destenation position (gets normalized)
-- len (number): ray lenght (default: distance between (x1, y1) and (x2, y2))
Ray = CuteC2.ray(x1, y1, x2, y2 [, len])
-- x, y (numbers): start position
-- rotation (number): facing angle (in radians)
-- len (number): ray lenght (default: 1)
Ray = CuteC2.rayFromRotation(x, y, rotation [, len])

-- x, y (numbers): position (default: (0, 0))
-- r (number): rotation (default: 0)
Transform = CuteC2.transform([x, y, r])

Functions

bool = CuteC2.circleToCircle(circle1, circle2)
bool = CuteC2.circleToAABB(circle, aabb)
bool = CuteC2.circleToCapsule(circle, capsule)
bool = CuteC2.AABBtoAABB(aabb1, aabb2)
bool = CuteC2.AABBtoCapsule(aabb, capsule)
bool = CuteC2.capsuleToCapsule(capsule1, capsule2)
bool = CuteC2.circleToPoly(circle, poly [, transform])
bool = CuteC2.AABBtoPoly(aabb, poly [, transform])
bool = CuteC2.capsuleToPoly(capsule, poly [, transform])
bool = CuteC2.polyToPoly(poly1, poly2 [, transform1, transform2])
bbol = CuteC2.collided(object1, object2 [, transform1, transform2])

bool = CuteC2.AABBtoPoint(aabb, x, y)
bool = CuteC2.circleToPoint(circle, x, y)
bool = CuteC2.capsuleToPoint(capsule, x, y)
bool = CuteC2.polyToPoint(poly, x, y [, transform])

result, normalX, normalY, t = CuteC2.castRay(ray, object [, transform])
result, normalX, normalY, t = CuteC2.castRay(rayX1, rayY1, rayX2, rayY2, rayLen, object [, transform])

-- t (number): value from raycast result
x, y = CuteC2.impact(ray, t)
x, y = CuteC2.impact(rayX1, rayY1, rayX2, rayY2, rayLen, t)

-- Mainfold (table):
-- {
--		count = number,
--		depth = {number1, number2},
--		contact_points = {
--			{x = number, y = number}, 
--			{x = number, y = number}
--		}, 
--		normal = {x = number, y = number}
-- }
Mainfold = CuteC2.collide(object1, object2 [, transform1, transform2])
Mainfold = CuteC2.circleToCircleManifold(circle1, circle2)
Mainfold = CuteC2.circleToAABBManifold(circle, aabb)
Mainfold = CuteC2.circleToCapsuleManifold(circle, capsule)
Mainfold = CuteC2.AABBtoAABBManifold(aabb1, aabb2)
Mainfold = CuteC2.AABBtoCapsuleManifold(aabb, capsule)
Mainfold = CuteC2.capsuleToCapsuleManifold(capsule1, capsule2)
Mainfold = CuteC2.circletoPolyManifold(circle, poly)
Mainfold = CuteC2.AABBtoPolyManifold(aabb, poly)
Mainfold = CuteC2.capsuleToPolyManifold(capsule, poly)
Mainfold = CuteC2.polyToPolyManifold(poly1, poly2)

Advanced functions

Check the [source code](https://github.com/RandyGaul/cute_headers/blob/df3b63e072afa275a72ce8aa7fce0428a5966e0c/cute_c2.h#L342) for more information

distance, aX, aY, bX, bY, iterations = CuteC2.GJK(object1, object2 [, transform1, transform2])
-- hit (bool): true if shapes were touching at the TOI, false if they never hit.
-- toi (number): The time of impact between two shapes.
-- nx, ny (numbers): Surface normal from shape A to B at the time of impact.
-- px, py (numbers): Point of contact between shapes A and B at time of impact.
-- iterations (number): Number of iterations the solver underwent.
hit, toi, nx, ny, px, py, iterations = CuteC2.TOI(object1, v1x, v1y, object2, v2x, v2y [, use_radius, transform1, transform2])

Circle

Circle:setPosition(x, y)
x, y = Circle:getPosition()

Circle:setX(x)
x = Circle:getX()

Circle:setY(y)
y = Circle:getY()

Circle:setRadius(radius)
radius = Circle:getRadius()

minX, minY, maxX, maxY = Circle:getBoundingBox()

x, y, radius = Circle:getData()

Circle:move(dx, dy)

Circle:inflate(skin_factor)

bool = Circle:hitTest(x, y)

result, normalX, normalY, t = Circle:rayTest(ray [, transform])
result, normalX, normalY, t = Circle:rayTest(rayX1, rayY1, rayX2, rayY2, rayLen [, transform])

AABB

-- x, y (number): top left corner position
AABB:setMinPosition(x, y)
x, y = AABB:getMinPosition()

-- x, y (number): bottom right corner position
AABB:setMaxPosition(x, y)
x, y = AABB:getMaxPosition()

-- x, y (number): center position
AABB:setPosition(x, y)
x, y = AABB:getPosition()

AABB:setMinX(x)
x = AABB:getMinX()

AABB:setMinY(y)
y = AABB:getMinY()

AABB:setMaxX(x)
x = AABB:getMaxX()

AABB:setMaxY(y)
y = AABB:getMaxY()

AABB:setX(x)
x = AABB:getX()

AABB:setY(y)
y = AABB:getY()

-- w, h (number): full size (relative to shape center)
AABB:setSize(w, h)
w, h = AABB:getSize()

-- w, h (number): half size (relative to shape center)
AABB:setHalfSize(w, h)
w, h = AABB:getHalfSize()

-- w (number): full width (relative to shape center)
AABB:setWidth(w)
w = AABB:getWidth()

-- h (number): full height (relative to shape center)
AABB:setHeight(h)
h = AABB:getHeight()

-- w (number): half width (relative to shape center)
AABB:setHalfWidth(w)
w = AABB:getHalfWidth()

-- h (number): half height (relative to shape center)
AABB:setHalfHeight(h)
h = AABB:getHalfHeight()

minX, minY, maxX, maxY = AABB:getBoundingBox()

minX, minY, maxX, maxY, fullW, fullH = AABB:getData()

AABB:move(dx, dy)

AABB:inflate(skin_factor)

bool = AABB:hitTest(x, y)
result, normalX, normalY, t = AABB:rayTest(ray [, transform])
result, normalX, normalY, t = AABB:rayTest(rayX1, rayY1, rayX2, rayY2, rayLen [, transform])

Capsule

         , - ~ ~ ~ - ,-------------.-
     , '               ' ,         |
   ,                       ,       |  Radius
  ,                         ,      |
 ,- - - - - - -X-<Tip - - - -,-----|-
 ,                           ,     |
 ,                           ,     |
 ,                           ,     |
 ,             X < Center    ,     | Height
 ,                           ,     |
 ,                           ,     |
 ,             |             ,     |
 ,- - - - - - -X-<Base- - - -,-----|-
  ,                         ,      |
   ,                       ,       | Radius
     ,                  , '        |
       ' - , _ _ _ ,  '_ _ _ _ _ _ |_
-- x, y (number): center position
Capsule:setPosition(x, y)
x, y = Capsule:getPosition()

-- x, y (number): position of the top point
Capsule:setTipPosition(x, y)
x, y = Capsule:getTipPosition()

-- x, y (number): position of the bottom point
Capsule:setBasePosition(x, y)
x, y = Capsule:getBasePosition()

Capsule:setX(x)
x = Capsule:getX()

Capsule:setY(y)
y = Capsule:getY()

Capsule:setTipX(x)
x = Capsule:getTipX()

Capsule:setTipY(y)
y = Capsule:getTipY()

Capsule:setBaseX(x)
x = Capsule:getBaseX()

Capsule:setBaseY(y)
y = Capsule:getBaseY()

-- h (number): height
Capsule:setHeight(h)
h = Capsule:getHeight()

-- r (number): radius
Capsule:setRadius(r)
r = Capsule:getRadius()

Capsule:setSize(radius, height)
radius, height = Capsule:getSize()

minX, minY, maxX, maxY = Capsule:getBoundingBox()

tipX, tipY, baseX, baseY, radius = Capsule:getData()

Capsule:move(dx, dy)
Capsule:inflate(skin_factor)
bool = Capsule:hitTest(x, y)
result, normalX, normalY, t = Capsule:rayTest(ray [, transform])
result, normalX, normalY, t = Capsule:rayTest(rayX1, rayY1, rayX2, rayY2, rayLen [, transform])

Poly

-- points (table): table of x/y pairs (example: {0,0, 100,50, 60,30, 40,90})
Poly:setPoints(points)

-- points (table): table of x/y pairs (example: {{x=0,y=0}, {x=100,y=50}, {x=60,y=30}, {x=40,y=90}})
Poly:setPointsXY(points)

-- returns a table of x/ pairs ({{x=0,y=0,}, {x=10,y=0}, ...})
table = Poly:getPoints() 
table = Poly:getNormals()
table = Poly:getRotatedPoints(transform)
table = Poly:getRotatedNormals(transform)

Poly:setVertex(index, x, y)
x, y = Poly:getVertex(index)
x = Poly:getVertexX(index)
y = Poly:getVertexY(index)
x, y = Poly:getRotatedVertex(index, transform)
x = Poly:getRotatedVertexX(index, transform)
y = Poly:getRotatedVertexY(index, transform)

-- return number of vertices
n = Poly:getVertexCount()
-- removes 
Poly:removeVertex(index)
-- add new vertex
-- x, y (number): point coordinats (in local space)
-- index (number): where to insert (default: last index)
-- transform (Transform): Transform object to add point with respect to shape position and rotation
Poly:insertVertex(x, y [, index, transform])

-- if vertices is too far from origin, sets the origin in the middle of its bounding box
Poly:updateCenter()

-- scales object by a factor
Poly:inflate(skin_factor)
bool = Poly:hitTest(x, y [, transform])
minX, minY, maxX, maxY = Poly:getBoundingBox()
-- return a table with points & normals: {points = {...}, normals = {...}}
table = Poly:getData()

result, normalX, normalY, t = Poly:rayTest(ray [, transform])
result, normalX, normalY, t = Poly:rayTest(rayX1, rayY1, rayX2, rayY2, rayLen [, transform])

Ray

Please check (this thread) https://github.com/RandyGaul/cute_headers/issues/30 for more information about ray direction

Example

┌───────────────────────────────────┐
  0  1  2  3  4  5  6  7  8  9     
  ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──►  
                      x  
1 ├──┼──S##┼──┼──┼──┼──┼──┼──┼──   
      ## ##                
2 ├──┼──##┼─##──┼──┼──┼──┼──┼───  
      #  #  ##             
3 ├──┼──#──┼#─┼──##─┼──┼──┼──┼───  
      #   #   ##           
4 ├──┼──#──┼──#──┼──┼##┼──┼──┼───  
      #    #     ##        
5 ├──┼──#──┼──┼─#┼──┼──┼─#N──┼───  
      #      #             
6 ├──┼──P──┼──┼──┼#─┼──┼──┼──┼───  
             #           
7 ├──┼──┼──┼──┼──┼──T──┼──┼──┼───  
                         
                                  
  y                               
└───────────────────────────────────┘
S = (2; 1) - origin position
T = (6; 7) - direction position
N = (8; 5) - new ray direction
P = (2; 6) - new ray direction
ray = CuteC2.ray(2, 1, 5, 7)

print(ray:getPosition()) --> 2, 1 (point "S")
print(ray:getTargetPosition()) --> 5, 7 (point "T")
print(ray:getLength()) --> 6.70

ray:normalize()
print(ray:getPosition()) --> 2, 1 (point "S")
print(ray:getTargetPosition()) --> (0.45, 0.89) direction vector
print(ray:getLength()) --> 1

ray:faceTo(8, 5) -- point "N"

print(ray:getLength()) --> 7.21
print(ray:getTargetPosition()) --> (0.83, 0.55)
print(ray:getFacePosition()) --> (8, 5)

ray:setDirection(math.pi - math.pi / 2) -- 90 deg
ray:setLength(5) -- point "P"

print(ray:getTargetPosition()) --> ~(0, 1)
print(ray:getFacePosition()) --> ~(2, 6)

API

ray:setPosition(x, y)
x, y = Ray:getPosition()

-- x, y (number): destenation point
ray:setTargetPosition(x, y)
x, y = Ray:getTargetPosition()

-- x, y (number): destenation point  (target position gets normalized)
Ray:faceTo(x, y)

-- returns point in global space
x, y = Ray:getFacePosition()
x = Ray:getFaceX()
y = Ray:getFaceY()

Ray:setStartX(x)
x = Ray:getStartX()

Ray:setStartY(y)
y = Ray:getStartY()

Ray:setTargetX(x)
x = Ray:getTargetX()

Ray:setTargetY(y)
y = Ray:getTargetY()

Ray:setLength(len)
len = Ray:getLength()

-- normalzies the target position 
-- set_len_to_one (bool) 
Ray:normalize([set_len_to_one])

-- normalzies the target position 
Ray:setDirection(radians)
radians = Ray:getDirection()

-- move original position (but not target!)
Ray:move(dx, dy)
startX, startY, directionX, directionY, len = Poly:getData()

Transform

Transform:setPosition(x, y)
x, y = Transform:getPosition()
Transform:setX(x)
x = Transform:getX()
Transform:setY(y)
y = Transform:getY()
Transform:move(deltaX, deltaY)
Transform:setRotation(radians)
radians = Transform:getRotation()
Transform:rotate(amount_in_radians)
Transform:move(dx, dy)
-- returns cos & sin of current rotation angle
cos, sin = Transform:getCosSin()

Shape types

CuteC2.TYPE_NONE
CuteC2.TYPE_CIRCLE
CuteC2.TYPE_AABB
CuteC2.TYPE_CAPSULE
CuteC2.TYPE_POLY

Example:

circle = CuteC2.circle(100, 200, 15)
print(circle.__shapeType == CuteC2.TYPE_CIRCLE) -- true

Example

Methods

Events

Constants