Skip to content

Commit

Permalink
Fix for issue doctest#422 (doctest#609)
Browse files Browse the repository at this point in the history
  • Loading branch information
erincatto authored Jul 12, 2020
1 parent 8118426 commit 07ad495
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 28 deletions.
8 changes: 8 additions & 0 deletions build_docs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash

# Builds Box2D along with documentation
rm -rf build
mkdir build
cd build
cmake -DBOX2D_BUILD_DOCS=ON ..
cmake --build .
4 changes: 4 additions & 0 deletions deploy_docs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash

# Copies documentation to blog
cp -R docs/html/. ../../blog/public/documentation/
14 changes: 14 additions & 0 deletions docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,20 @@ but you can convert that to pixel coordinates with a simple scaling
factor. You can then use those pixel coordinates to place your sprites,
etc. You can also account for flipped coordinate axes.

Another limitation to consider is overall world size. If your world units
become larger than 2 kilometers or so, then the lost precision can affect
stability.

> **Caution**:
> Box2D works best with world sizes less than 2 kilometers. Use
> b2World::ShiftOrigin to support larger worlds.
If you need to have a larger game world, consider using
b2World::ShiftOrigin to keep the world origin close to your player. I recommend
to use grid lines along with some hysteresis for triggering calls to ShiftOrigin.
This call should be made infrequently because it is has CPU cost. You may
need to store a physics offset when translating between game units and Box2D units.

Box2D uses radians for angles. The body rotation is stored in radians
and may grow unbounded. Consider normalizing the angle of your bodies if
the magnitude of the angle becomes too large (use b2Body::SetAngle).
Expand Down
39 changes: 12 additions & 27 deletions src/collision/b2_polygon_shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,29 +81,21 @@ static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count)
{
b2Assert(count >= 3);

b2Vec2 c; c.Set(0.0f, 0.0f);
b2Vec2 c(0.0f, 0.0f);
float area = 0.0f;

// pRef is the reference point for forming triangles.
// It's location doesn't change the result (except for rounding error).
b2Vec2 pRef(0.0f, 0.0f);
#if 0
// This code would put the reference point inside the polygon.
for (int32 i = 0; i < count; ++i)
{
pRef += vs[i];
}
pRef *= 1.0f / count;
#endif
// Get a reference point for forming triangles.
// Use the first vertex to reduce round-off errors.
b2Vec2 s = vs[0];

const float inv3 = 1.0f / 3.0f;

for (int32 i = 0; i < count; ++i)
{
// Triangle vertices.
b2Vec2 p1 = pRef;
b2Vec2 p2 = vs[i];
b2Vec2 p3 = i + 1 < count ? vs[i+1] : vs[0];
b2Vec2 p1 = vs[0] - s;
b2Vec2 p2 = vs[i] - s;
b2Vec2 p3 = i + 1 < count ? vs[i+1] - s : vs[0] - s;

b2Vec2 e1 = p2 - p1;
b2Vec2 e2 = p3 - p1;
Expand All @@ -119,7 +111,7 @@ static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count)

// Centroid
b2Assert(area > b2_epsilon);
c *= 1.0f / area;
c = (1.0f / area) * c + s;
return c;
}

Expand Down Expand Up @@ -390,20 +382,13 @@ void b2PolygonShape::ComputeMass(b2MassData* massData, float density) const

b2Assert(m_count >= 3);

b2Vec2 center; center.Set(0.0f, 0.0f);
b2Vec2 center(0.0f, 0.0f);
float area = 0.0f;
float I = 0.0f;

// s is the reference point for forming triangles.
// It's location doesn't change the result (except for rounding error).
b2Vec2 s(0.0f, 0.0f);

// This code would put the reference point inside the polygon.
for (int32 i = 0; i < m_count; ++i)
{
s += m_vertices[i];
}
s *= 1.0f / m_count;
// Get a reference point for forming triangles.
// Use the first vertex to reduce round-off errors.
b2Vec2 s = m_vertices[0];

const float k_inv3 = 1.0f / 3.0f;

Expand Down
3 changes: 2 additions & 1 deletion unit-test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_executable(unit_test
doctest.h
hello_world.cpp
collision_test.cpp
)

set_target_properties(unit_test PROPERTIES
Expand All @@ -13,4 +14,4 @@ target_link_libraries(unit_test PUBLIC box2d)
# Place the test executable at the project binary directory instead of in the nested subfolder
set_target_properties(unit_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})

source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES doctest.h hello_world.cpp)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES doctest.h hello_world.cpp collision_test.cpp)
82 changes: 82 additions & 0 deletions unit-test/collision_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// MIT License

// Copyright (c) 2020 Erin Catto

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include "box2d/box2d.h"
#include <stdio.h>

#include "doctest.h"

// Unit tests for collision algorithms
DOCTEST_TEST_CASE("collision test")
{
SUBCASE("polygon mass data")
{
const b2Vec2 center(100.0f, -50.0f);
const float hx = 0.5f, hy = 1.5f;
const float angle1 = 0.25f;

// Data from issue #422. Not used because the data exceeds accuracy limits.
//const b2Vec2 center(-15000.0f, -15000.0f);
//const float hx = 0.72f, hy = 0.72f;
//const float angle1 = 0.0f;

b2PolygonShape polygon1;
polygon1.SetAsBox(hx, hy, center, angle1);

const float absTol = 2.0f * b2_epsilon;
const float relTol = 2.0f * b2_epsilon;

CHECK(b2Abs(polygon1.m_centroid.x - center.x) < absTol + relTol * b2Abs(center.x));
CHECK(b2Abs(polygon1.m_centroid.y - center.y) < absTol + relTol * b2Abs(center.y));

b2Vec2 vertices[4];
vertices[0].Set(center.x - hx, center.y - hy);
vertices[1].Set(center.x + hx, center.y - hy);
vertices[2].Set(center.x - hx, center.y + hy);
vertices[3].Set(center.x + hx, center.y + hy);

b2PolygonShape polygon2;
polygon2.Set(vertices, 4);

CHECK(b2Abs(polygon2.m_centroid.x - center.x) < absTol + relTol * b2Abs(center.x));
CHECK(b2Abs(polygon2.m_centroid.y - center.y) < absTol + relTol * b2Abs(center.y));

const float mass = 4.0f * hx * hy;
const float inertia = (mass / 3.0f) * (hx * hx + hy * hy) + mass * b2Dot(center, center);

b2MassData massData1;
polygon1.ComputeMass(&massData1, 1.0f);

CHECK(b2Abs(massData1.center.x - center.x) < absTol + relTol * b2Abs(center.x));
CHECK(b2Abs(massData1.center.y - center.y) < absTol + relTol * b2Abs(center.y));
CHECK(b2Abs(massData1.mass - mass) < 20.0f * (absTol + relTol * mass));
CHECK(b2Abs(massData1.I - inertia) < 40.0f * (absTol + relTol * inertia));

b2MassData massData2;
polygon2.ComputeMass(&massData2, 1.0f);

CHECK(b2Abs(massData2.center.x - center.x) < absTol + relTol * b2Abs(center.x));
CHECK(b2Abs(massData2.center.y - center.y) < absTol + relTol * b2Abs(center.y));
CHECK(b2Abs(massData2.mass - mass) < 20.0f * (absTol + relTol * mass));
CHECK(b2Abs(massData2.I - inertia) < 40.0f * (absTol + relTol * inertia));
}
}

0 comments on commit 07ad495

Please sign in to comment.