bEPU Games Home

BEPUphysics Home

Forums

Overview

Media

Documentation

Downloads

Versions

 

 

      Documentation

 

BEPUphysics uses an overall design scheme as follows:

Entities, such as convex polyhedra, are contained in a SpaceEntities compose all dynamic and nondynamic objects within the world. Interaction Handlers such as Controllers and Constraints manage behavior between Entities. 

Helper Classes, specifically the Toolbox and PrimitiveToolbox, provide shortcuts and easy methods to accomplish complex tasks and computations.

 

General Tips:
   -
Avoid using very large or very small objects.  These can cause sometimes noticeable artifacts.
   -Avoid large mass ratios.  Very heavy objects sitting on top of light objects can be unstable.
   -While entity margins are adjustable, avoid extremely small values.
   -If something isn't clear, be sure to ask on the forums or let
Norbo know!

 

Have questions that aren't addressed here?  Head to the forums or contact Norbo directly.  Forums are the preferred method of communication as others may learn from what is posted there.  The library comes with full XML documentation for in-code viewing.

       

    Entities

All simulated objects fall under the category of Entity.  Entities are stored within and updated by their associated Space object.

There are currently nine base types of Entity:
Box
  
Specialized primitive with a mathematical definition, well suited for crate duty.
Capsule
  
Spherically expanded line segment; a pill.
Cylinder
  
Mathematically defined object with a height and radius with two circular ends.
Cone
  
Mathematically defined object with a height and radius with one circular and one single-point end.
Sphere
  
Simple mathematically defined object with a radius.
Triangle
  
Three vertices connected by three edges.
MinkowskiSum
   Sweeps the two component entities through each other to form a new shape.
ConvexHull
   A triangulated exterior shell of a point set.
WrappedBody
  
An implicit convex hull around a set of shapes.

  -Note that while the display graphics of the Cylinder, Capsule, Cone, and Sphere are triangulated, they are considered to have 'perfect' curves during simulation as they are defined through equations instead of a series of triangles.

Each basic type of Entity can be either physically simulated or not.  Switching between these states is as simple as calling Entity.makePhysical(float mass) or Entity.makeNonDynamic(). Physical objects respond to collisions and operate based on forces.  Nondynamic objects, on the other hand, operate purely on the velocity level.  In collisions, they are considered to have infinite inertia.

A special type is CompoundBody; other entities can be added to its listing by using the function addBody(Entity body), or removed by using the removeBody(Entity body) method.  When added to a CompoundBody, an Entity's relative position to the CompoundBody and its existing elements becomes fixed and the object will act as a part of the CompoundBody physically.  CompoundBodies can be added to other CompoundBodies, allowing for hierarchies of objects.

 

     World and Environment: Space

Obviously, there needs to be somewhere to put all of the objects to be simulated.  This is handled through the Space class.

A Space object can be created with no parameters or with a list of entities.  To add additional objects after creating the Space, call add(Entity entity).  This will place the entity in the list of entities to be updated each frame.  Conversely, objects can be removed from the update loop by calling remove(Entity entity).  Constraints can be added and removed by using the add(Constraint constraint) and remove(Constraint constraint) functions, respectively.

To move the simulation forward, simply call the update(GameTime gameTime) method of the Space object.  Also available are the update(float dt, GameTime gameTime) method and other auxiliary methods.  If the simulation should slow down into 'moon gravity' during intense interaction, the Game's isFixedTimeStep should be set to false and the second method (update(float dt, GameTime gameTime)) should be used, with dt being a value less than or equal to 1/60f.

Simulations can be set to run with adaptive quality based on the current performance using the activateDynamicIterationCount(float desiredFPS, int minIterations, int maxIterations) function.  If the time since the last drawn frame is less than 1/desiredFPS, the iteration count will increase by 1 up to a maximum of maxIterations.  Conversely, if the time since the last drawn frame is greater than 1/desiredFPS, the number of iterations will decrease by one per frame until the minimum is reached.  If the current FPS is extremely low, the decrease rate is faster.

If desired, a list of all contact points between objects in the simulation during the current frame can be obtained by calling getContacts(); however, as this compiles the list from individual Controllers at the time of the request, it is not recommended for frequent calls.

A raycast against the entire world can be performed by using Space.rayCast; this searches through the broad phase listing and any ray castable containers (such as static triangle groups) within the world.

Additionally, there are a set of important fields contained in a Space's SimulationSettings which can be used to tune the simulation.  These range from varying position correction and integration methods to the lower bound on velocity before being clamped to zero.  Other collision detection options are also available here, allowing continuous collision detection to be enabled and disabled.

Broad Phases

Broad phases provide a method for determining collision pairs.  They can also be queried with bounding shapes for determining objects in an area.  Beyond the following, custom broad phases can be derived from the BroadPhase class and used in the space.
 
UniformGrid
   
Separates the space into an infinite number of cubes.  Objects within these cells are checked only against other entities within the applicable cells.  This type of grid is rebuilt every frame, lowering the bookkeeping costs but providing suboptimal performance for simulations with many nonmoving objects.  Recommended for simulations in which most or all entities are moving.

PersistentUniformGrid
    Similar to the above, but keeps track of objects through frames and does not rebuild the representation every frame.  A generally good fit for most simulations; used by default.

BruteForce
   
Simple pairwise check between entities with no spatial partitioning.  Provides acceptable performance only for small (low hundreds or less) numbers of objects.

Broad phases also support methods for getting entities within bounding volumes and raycasting against their contents.

Updateables and Other Frameworks

The engine supports a framework for new types of objects to be maintained by the space.  These include Updateables, SolverUpdateables, CombinedUpdateables, and ForceFields.  Default subclasses of these are listed below; others can be added externally.

Static Triangle Groups : Updateable
    An efficient container for complex static triangulated geometry.  Can be loaded in based on a mesh.  Capable of handling thousands of triangles quickly.

Static Groups : Updateable
    Nonmoving elements of the simulation, such as level geometry, can be represented within StaticGroups.  The entities added to a StaticGroup will be added into the associated space dynamically as needed (such as when physically simulated bodies approach).  With large amounts of geometry, the computational savings can be great.  Note that entities added to a StaticGroup need not be added directly to the space; the StaticGroup will handle all of the adding and removing.

Terrain : Updateable
    A conceptual subset of static groups, Terrain converts a list of heights into appropriately placed triangles dynamically.  As with static groups, the triangles will persist only when necessary.  Heights can be modified on the fly, allowing deformability.

Vehicle : CombinedUpdateable
    Vehicles are wheeled mechanisms that can be driven around while saying "vroom vrooooom rrrrrrrroooom."  They support numerous friction coefficients, braking, acceleration, and tuning variables.  In order to get a solid feel for the friction forces of the tires, vehicle force calculation needed to be integrated directly into the solver.  Additionally, to update the graphical portion of the vehicle (wheel positions relative to interpolated positions), the end of frame update component of CombinedUpdateable is used.  Using the same basis or directly using the SolverUpdateable, other types can be directly tied into the solver.  This has the benefit of letting forces and impulses applied during the updates to be 'felt' across the simulation, causing the propagation of momentum rather than stopping nonphysically.

PushField : ForceField
    The pushfield is the simplest available forcefield; it is simply a uniform application of the same force with a maximum speed.

Tornado : ForceField
    Showing off a little of what can be done with the framework, a tornado incorporates three position-dependent forces to form a whirling mass of air.

GravitationalField : ForceField
    Applies position dependent forces based on a center origin and a constant value.  The constant value can be thought of as the product of the gravitational constant and the mass of the object.  In the default demos example, considering the real world gravitational constant, the 'planet' has an effective mass of 10,000,000,000,000 kilograms.

_______

     Helper Classes

There are two main helper classes; the Toolbox and PrimitiveToolbox.

Toolbox:
  
Contains numerous math and geometry tests. Includes methods for:
-Segment/Ray - Triangle Tests
-Point - Triangle Tests
-Line - Line Tests
-Triangle - Triangle Tests
-Point - Plane Tests
-General Entity/Entity Tests
-Ray-Entity tests
-Miscellaneous vector, float, list, and quaternion operations

   Additionally, the Toolbox contains computational constants epsilon and bigEpsilon, corresponding to floating point tolerances.  Default values are epsilon = 1E-7f and bigEpsilon = 1E-5f.

PrimitiveToolbox:
   Contains methods for easily creating common shapes.  Includes methods for:
-Tetrahedra of arbitrary vertex positions and right tetrahedra
-Hexahedra of arbitrary positions or rectangular prisms and cubes.
 

_______

     Interaction Handlers

Force
   Forces
can be created and applied to physically simulated objects.  Based on the origin and direction of force, the target is pushed. The magnitude of the push is determined by the length of the direction vector.

   Additionally, Forces can be set to track the target in either or both linear and angular motion.  This can be used to simulate 'thruster' behaviors.  By default, tracking is disabled.  If tracking is enabled, the default behavior is for both linear and angular motion to be tracked.  These settings can be adjusted through the Force's isTrackingTarget and isChangingDirectionWhileTracking fields.

   To apply a Force, use an entity's applyForce(Force force) method.  To remove it from the object entirely, use the removeForce(Force force) method.  A Force can be temporarily turned off without removing it from an object by setting its isActive field to false.

Constraint
   Constraints
can be formed between two Entities.  They restrict motion and provide an extra degree of interaction.  As of v0.6.0, there are four two-body velocity solver constraints: BallSocketJoints, PointOnLineJoint, DistanceConstraint, and DistangeRangeConstraint.  All of these and those below can be found in the "More Constraints" demo.

Examples of Combination Constraints:
   Fixed Point:  A 'weld' joint can be created by using three BallSocketJoints.  The most stable configuration is having each BallSocketJoint's anchor offset along a different orthogonal axis from a midpoint between two objects (in other words, each BallSocketJoint has a slightly different anchor point).
   Revolute:  'Hinges' can be made by two BallSocketJoints.  The axis of rotation allowed by the hinge is the vector from the first BallSocketJoint anchor point to the second BallSocketJoint anchor point.
  
Prismatic:  'Sliders' can be formed by three PointOnLineJoints, with each anchor location offset in a similar fashion to the fixed point and each PointOnLineJoint's axis parallel to the others.

Each Constraint has two primary tuning variables; softness and bias factor.  Higher softness values allow the constraint to 'give' somewhat.  Generally, softness values are low, ranging from 0 to 1.  The bias factor is a modifier of the speed at which the constraint corrects position drift, and is within a similar order of magnitude, though a value of .2f works well in almost all situations.  Values close to 0 will cause noticeable position drift, while values closer to 1 can cause the constraint to explode.

If instability is observed in a simulation involving constraints, tuning these variables can often alleviate the problem.  In many problematic cases, increasing the softness can help stop overzealous adherence to the constraint.

Constraints can also have a maximum force limit specified.  When violated, the constraint will be removed from simulation.  In the future, motors, friction, and motion limits will be added.

SingleBodyConstraints
are solver-based types which affect only a single entity.  Examples include the MaximumSpeedConstraint and RotationalAxisConstraint.  Other single body affecting types which aren't a part of the solver include GrabConstraint and UprightConstraint.  A special two-body constraint that is not part of the solver, the Spring, is also available.

Controller
   Controllers
manage the collision of two objects.  They persist over multiple frames, as long as the possible collision exists (as determined by the broad phase collision detection). During their lifespan, Controllers will keep track of the state of the collision.  If the objects intersect, the Controller will move them apart to a safe collision margin and create Contact points to maintain noninterpenetration.

Contact
   Contacts
are generated by Controllers to keep objects out of intersection.  At each Contact location, an impulse is iteratively calculated using the number of iterations defined in the Space class.
 
Collision Filters
  
Entities' collisionFilter field acts as a bitmask which checks if a given collision is valid.  If one or more of the 'enabled' bits in the filter match the collided entity's field, the controller is created.  The setCollisionFilter method of Entity provides an easy way of setting up the individual bits without having to convert binary to decimal.

Adding entities to an entity's nonCollidableEntities list will also prevent interaction.  Setting an entity's isTangible flag to false will result in them not interacting with other objects, but it still generates Controllers.  This makes it a valuable as a 'detector,' which finds nearby candidate entities.

      

    Events

As of v0.6.0, individual events can be hooked for collision events by using the Entity.addEventHook method.


Most events are deferred to the end of the frame, allowing for most operations to be called safely.  However, there are three special 'immediate' methods: contact created immediate, controller created immediate, and entity updated immediate.  The first two events allow the modification of the contact and controller's data at the exact time of creation, before they are used in any calculations.  The third acts as a callback for any additional logic that should be performed with that entity.  The demos (#30) have an example of how to use the event system in game logic.

      

    Thread Safety

As of v0.7.0, running BEPUphysics in a separate thread has become significantly easier.  Entity states such as position and velocity are buffered so that reads get the last valid result and writes wait until the engine is ready before changing values.  Along with the buffered states, unbuffered properties are available; any property with a prefix of "internal," such as Entity.internalLinearVelocity, read and write values directly.  This can be handy for immediate changes when it is known that thread safety isn't an issue.


Most of the space's operations, such as raycasting or adding entities, are internally locked to ensure thread safety.  Space also contains synchronization objects for use by external operations.  The engine takes out locks on these synchronization objects as necessary, so locking the lockerUpdate object will ensure that your code will not run while the engine updates.  The finer grained locks on entities, controllers, constraints, and updateables provide additional control.

 

 

 

 

 

© 2008 Bepu Entertainment LLC.  All rights reserved.
Contact Us.

RSS Feed