Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
erincatto committed May 22, 2024
1 parent b67f489 commit 8610a05
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 219 deletions.
114 changes: 31 additions & 83 deletions docs/collision.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ If edge1 did not exist this collision would seem fine. With edge1
present, the internal collision seems like a bug. But normally when
Box2D collides two shapes, it views them in isolation.
Fortunately, the smooth segment shape provides a mechanism for eliminating ghost
b2SmoothSegment provides a mechanism for eliminating ghost
collisions by storing the adjacent *ghost* vertices. Box2D uses these
ghost vertices to prevent internal collisions.
Expand Down Expand Up @@ -238,83 +238,28 @@ if (output.hit == true)
}
```
### Contact Manifolds
Box2D has functions to compute contact points for overlapping shapes. If
we consider circle-circle or circle-polygon, we can only get one contact
point and normal. In the case of polygon-polygon we can get two points.
These points share the same normal vector so Box2D groups them into a
manifold structure. The contact solver takes advantage of this to
improve stacking stability.
![Contact Manifold](images/manifolds.svg)
Normally you don't need to compute contact manifolds directly, however
you will likely use the results produced in the simulation.
The b2Manifold structure holds a normal vector and up to two contact
points. The normal and points are held in local coordinates. As a
convenience for the contact solver, each point stores the normal and
tangential (friction) impulses.
The data stored in `b2Manifold is optimized for internal use. If you need
this data, it is usually best to use the b2WorldManifold structure to
generate the world coordinates of the contact normal and points. You
need to provide a b2Manifold and the shape transforms and radii.
```cpp
b2WorldManifold worldManifold;
worldManifold.Initialize(&manifold, transformA, shapeA.m_radius,
transformB, shapeB.m_radius);
for (int32 i = 0; i < manifold.pointCount; ++i)
{
b2Vec2 point = worldManifold.points[i];
...
}
```

Notice that the world manifold uses the point count from the original
manifold.

During simulation shapes may move and the manifolds may change. Points
may be added or removed. You can detect this using b2GetPointStates.

```cpp
b2PointState state1[2], state2[2];
b2GetPointStates(state1, state2, &manifold1, &manifold2);

if (state1[0] == b2_removeState)
{
// process event
}
```
Even more generic, you can use `b2ShapeCast()` to linearly cast one point cloud at another point cloud. All shape cast functions use this internally.
### Distance
The `b2Distance` function can be used to compute the distance between two
`b2ShapeDistance()` function can be used to compute the distance between two
shapes. The distance function needs both shapes to be converted into a
b2DistanceProxy. There is also some caching used to warm start the
distance function for repeated calls.
`b2DistanceProxy` (which are point clouds with radii). There is also some caching used to warm start the
distance function for repeated calls. This might make your use case faster.
![Distance Function](images/distance.svg){html: width=30%}
![Distance Function](images/distance.svg)
### Time of Impact
If two shapes are moving fast, they may *tunnel* through each other in a
single time step.
![Tunneling](images/tunneling2.svg){html: width=30%}
The `b2TimeOfImpact` function is used to determine the time when two
moving shapes collide. This is called the *time of impact* (TOI). The
main purpose of `b2TimeOfImpact` is for tunnel prevention. In particular,
it is designed to prevent moving objects from tunneling outside of
static level geometry.
This function accounts for rotation and translation of both shapes,
however if the rotations are large enough, then the function may miss a
collision. However the function will still report a non-overlapped time
and will capture all translational collisions.
The `b2TimeOfImpact()` function is used to determine the time when two moving shapes collide.
This is called the *time of impact* (TOI). The main purpose of `b2TimeOfImpact()` is for
tunnel prevention. Box2D uses this internally to prevent moving objects from tunneling through of
static shapes.
The time of impact function identities an initial separating axis and
The `b2TimeOfImpact()` identities an initial separating axis and
ensures the shapes do not cross on that axis. This might miss collisions
that are clear at the final positions. While this approach may miss some
collisions, it is very fast and adequate for tunnel prevention.
Expand All @@ -335,10 +280,27 @@ transforms of the shapes.
You can use fixed rotations to perform a *shape cast*. In this case, the
time of impact function will not miss any collisions.
### Contact Manifolds
Box2D has functions to compute contact points for overlapping shapes. If
we consider circle-circle or circle-polygon, we can only get one contact
point and normal. In the case of polygon-polygon we can get two points.
These points share the same normal vector so Box2D groups them into a
manifold structure. The contact solver takes advantage of this to
improve stacking stability.
![Contact Manifold](images/manifolds.svg)
Normally you don't need to compute contact manifolds directly, however
you will likely use the results produced in the simulation.
The `b2Manifold` structure holds a normal vector and up to two contact
points. The contact points store the normal and tangential (friction) impulses
computed in the rigid body simulation.
## Dynamic Tree
The b2DynamicTree class is used by Box2D to organize large numbers of
`b2DynamicTree` is used by Box2D to organize large numbers of
shapes efficiently. The class does not know about shapes. Instead it
operates on axis-aligned bounding boxes (AABBs) with user data pointers.
operates on axis-aligned bounding boxes (`b2AABB`) with user data integers.
The dynamic tree is a hierarchical AABB tree. Each internal node in the
tree has two children. A leaf node is a single user AABB. The tree uses
Expand All @@ -362,20 +324,6 @@ be skipped.
![Overlap Test](images/overlap_test.svg){html: width=30%}
Normally you will not use the dynamic tree directly. Rather you will go
through the b2World class for ray casts and region queries. If you plan
through the `b2World` functions for ray casts and region queries. If you plan
to instantiate your own dynamic tree, you can learn how to use it by
looking at how Box2D uses it.
## Broad-phase
Collision processing in a physics step can be divided into narrow-phase
and broad-phase. In the narrow-phase we compute contact points between
pairs of shapes. Imagine we have N shapes. Using brute force, we would
need to perform the narrow-phase for N*N/2 pairs.
The b2BroadPhase class reduces this load by using a dynamic tree for
pair management. This greatly reduces the number of narrow-phase calls.
Normally you do not interact with the broad-phase directly. Instead,
Box2D creates and manages a broad-phase internally. Also, b2BroadPhase
is designed with Box2D's simulation loop in mind, so it is likely not
suited for other use cases.
62 changes: 31 additions & 31 deletions docs/dynamics.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
# Dynamics Module (Out Of Date)
The Dynamics module is the most complex part of Box2D and is the part
you likely interact with the most. The Dynamics module sits on top of
the Common and Collision modules, so you should be somewhat familiar
# Simulation
Rigid body simulation is the primary feature of Box2D. It is the most complex part of
Box2D and is the part you likely interact with the most. Simulations sits on top of
the base and collision functions, so you should be somewhat familiar
with those by now.

The Dynamics module contains:
- fixture class
- rigid body class
- contact class
- joint classes
- world class
- listener classes

There are many dependencies between these classes so it is difficult to
describe one class without referring to another. In the following, you
may see some references to classes that have not been described yet.
Therefore, you may want to quickly skim this chapter before reading it
Rigid body simulation contains:
- worlds
- bodies
- shapes
- contacts
- joints
- events

There are many dependencies between these objects so it is difficult to
describe one without referring to another. In the following, you
may see some references to objects that have not been described yet.
Therefore, you may want to quickly skim this section before reading it
closely.

The dynamics module is covered in the following chapters.

## Bodies
Bodies have position and velocity. You can apply forces, torques, and
impulses to bodies. Bodies can be static, kinematic, or dynamic. Here
## Rigid Bodies
Rigid bodies, or just *bodies* have position and velocity. You can apply forces, torques,
and impulses to bodies. Bodies can be static, kinematic, or dynamic. Here
are the body type definitions:

### Body types

#### b2_staticBody
A static body does not move under simulation and behaves as if it has
infinite mass. Internally, Box2D stores zero for the mass and the
inverse mass. Static bodies can be moved manually by the user. A static
body has zero velocity. Static bodies do not collide with other static
or kinematic bodies.
#b2_staticBody:
A static body does not move under simulation and behaves as if it has infinite mass.
Internally, Box2D stores zero for the mass and the inverse mass. A static body has zero
velocity. Static bodies do not collide with other static or kinematic bodies. Static
bodies can be moved manually by the user, but this should be avoided because it may
result in missed collisions and other undesirable behavior.

#### b2_kinematicBody
#b2_kinematicBody:
A kinematic body moves under simulation according to its velocity.
Kinematic bodies do not respond to forces. They can be moved manually by
the user, but normally a kinematic body is moved by setting its
velocity. A kinematic body behaves as if it has infinite mass, however,
Box2D stores zero for the mass and the inverse mass. Kinematic bodies do
not collide with other kinematic or static bodies.
not collide with other kinematic or static bodies. Generally you should use
a kinematic body if you want a shape to be animated and not affected by
forces or collisions.

#### b2_dynamicBody
#b2_dynamicBody:
A dynamic body is fully simulated. They can be moved manually by the
user, but normally they move according to forces. A dynamic body can
collide with all body types. A dynamic body always has finite, non-zero
mass. If you try to set the mass of a dynamic body to zero, it will
automatically acquire a mass of one kilogram and it won't rotate.

Bodies are the backbone for fixtures (shapes). Bodies carry fixtures and
Bodies are the backbone for shapes. Bodies carry fixtures and
move them around in the world. Bodies are always rigid bodies in Box2D.
That means that two fixtures attached to the same rigid body never move
relative to each other and fixtures attached to the same body don't
Expand Down
Loading

0 comments on commit 8610a05

Please sign in to comment.