#include "test_macros.h"
#include "box2d/collision.h"
#include "box2d/math_functions.h"
#include <float.h>
static b2Capsule capsule = { { -1.0f, 0.0f }, { 1.0f, 0.0f }, 1.0f };
static b2Circle circle = { { 1.0f, 0.0f }, 1.0f };
static b2Polygon box;
static b2Segment segment = { { 0.0f, 1.0f }, { 0.0f, -1.0f } };
#define N 4
static int ShapeMassTest( void )
{
{
b2MassData md = b2ComputeCircleMass( &circle, 1.0f );
ENSURE_SMALL( md.mass - b2_pi, FLT_EPSILON );
ENSURE( md.center.x == 1.0f && md.center.y == 0.0f );
ENSURE_SMALL( md.rotationalInertia - 1.5f * b2_pi, FLT_EPSILON );
}
{
float radius = capsule.radius;
float length = b2Distance( capsule.center1, capsule.center2 );
b2MassData md = b2ComputeCapsuleMass( &capsule, 1.0f );
b2Polygon r = b2MakeBox( radius, radius + 0.5f * length );
b2MassData mdr = b2ComputePolygonMass( &r, 1.0f );
b2Vec2 points[2 * N];
float d = b2_pi / ( N - 1.0f );
float angle = -0.5f * b2_pi;
for ( int i = 0; i < N; ++i )
{
points[i].x = 1.0f + radius * cosf( angle );
points[i].y = radius * sinf( angle );
angle += d;
}
angle = 0.5f * b2_pi;
for ( int i = N; i < 2 * N; ++i )
{
points[i].x = -1.0f + radius * cosf( angle );
points[i].y = radius * sinf( angle );
angle += d;
}
b2Hull hull = b2ComputeHull( points, 2 * N );
b2Polygon ac = b2MakePolygon( &hull, 0.0f );
b2MassData ma = b2ComputePolygonMass( &ac, 1.0f );
ENSURE( ma.mass < md.mass && md.mass < mdr.mass );
ENSURE( ma.rotationalInertia < md.rotationalInertia && md.rotationalInertia < mdr.rotationalInertia );
}
{
b2MassData md = b2ComputePolygonMass( &box, 1.0f );
ENSURE_SMALL( md.mass - 4.0f, FLT_EPSILON );
ENSURE_SMALL( md.center.x, FLT_EPSILON );
ENSURE_SMALL( md.center.y, FLT_EPSILON );
ENSURE_SMALL( md.rotationalInertia - 8.0f / 3.0f, 2.0f * FLT_EPSILON );
}
return 0;
}
static int ShapeAABBTest( void )
{
{
b2AABB b = b2ComputeCircleAABB( &circle, b2Transform_identity );
ENSURE_SMALL( b.lowerBound.x, FLT_EPSILON );
ENSURE_SMALL( b.lowerBound.y + 1.0f, FLT_EPSILON );
ENSURE_SMALL( b.upperBound.x - 2.0f, FLT_EPSILON );
ENSURE_SMALL( b.upperBound.y - 1.0f, FLT_EPSILON );
}
{
b2AABB b = b2ComputePolygonAABB( &box, b2Transform_identity );
ENSURE_SMALL( b.lowerBound.x + 1.0f, FLT_EPSILON );
ENSURE_SMALL( b.lowerBound.y + 1.0f, FLT_EPSILON );
ENSURE_SMALL( b.upperBound.x - 1.0f, FLT_EPSILON );
ENSURE_SMALL( b.upperBound.y - 1.0f, FLT_EPSILON );
}
{
b2AABB b = b2ComputeSegmentAABB( &segment, b2Transform_identity );
ENSURE_SMALL( b.lowerBound.x, FLT_EPSILON );
ENSURE_SMALL( b.lowerBound.y + 1.0f, FLT_EPSILON );
ENSURE_SMALL( b.upperBound.x, FLT_EPSILON );
ENSURE_SMALL( b.upperBound.y - 1.0f, FLT_EPSILON );
}
return 0;
}
static int PointInShapeTest( void )
{
b2Vec2 p1 = { 0.5f, 0.5f };
b2Vec2 p2 = { 4.0f, -4.0f };
{
bool hit;
hit = b2PointInCircle( p1, &circle );
ENSURE( hit == true );
hit = b2PointInCircle( p2, &circle );
ENSURE( hit == false );
}
{
bool hit;
hit = b2PointInPolygon( p1, &box );
ENSURE( hit == true );
hit = b2PointInPolygon( p2, &box );
ENSURE( hit == false );
}
return 0;
}
static int RayCastShapeTest( void )
{
b2RayCastInput input = { { -4.0f, 0.0f }, { 8.0f, 0.0f }, 1.0f };
{
b2CastOutput output = b2RayCastCircle( &input, &circle );
ENSURE( output.hit );
ENSURE_SMALL( output.normal.x + 1.0f, FLT_EPSILON );
ENSURE_SMALL( output.normal.y, FLT_EPSILON );
ENSURE_SMALL( output.fraction - 0.5f, FLT_EPSILON );
}
{
b2CastOutput output = b2RayCastPolygon( &input, &box );
ENSURE( output.hit );
ENSURE_SMALL( output.normal.x + 1.0f, FLT_EPSILON );
ENSURE_SMALL( output.normal.y, FLT_EPSILON );
ENSURE_SMALL( output.fraction - 3.0f / 8.0f, FLT_EPSILON );
}
{
b2CastOutput output = b2RayCastSegment( &input, &segment, true );
ENSURE( output.hit );
ENSURE_SMALL( output.normal.x + 1.0f, FLT_EPSILON );
ENSURE_SMALL( output.normal.y, FLT_EPSILON );
ENSURE_SMALL( output.fraction - 0.5f, FLT_EPSILON );
}
return 0;
}
int ShapeTest( void )
{
box = b2MakeBox( 1.0f, 1.0f );
RUN_SUBTEST( ShapeMassTest );
RUN_SUBTEST( ShapeAABBTest );
RUN_SUBTEST( PointInShapeTest );
RUN_SUBTEST( RayCastShapeTest );
return 0;
}