All interactions with the physics engine start with creating a physical world object using the
CreatePhysicalWorld() function. It returns a pointer to the
The world is later filled with physical entities and geometries. Geometries are first created as independent objects so that they can be used alone via the
IGeometry interface which they expose and then they can be physicalized and added to physical entities. Geometry physicalization means computing physical properties (volume, inertia tensor) and storing them in a special internal structure. Pointers to these structures can then be passed to physical entities.
Each physicalized geometry has a reference counter which is set to 1 during creation, incremented every time the geometry is added to an entity and decremented every time the geometry is removed or the entity is deleted. When the counter reaches 0, the physical geometry structure is deleted and the corresponding IGeometry object is released (it is however refcounted as well). In the following the geometry management functions are listed. They are accessible via the geometry manage, which is a part of physical world. The pointer to it is returned by the
CreateMesh: Creates a triangular mesh object from a set of vertices and indices (3 indices per triangle) and returns the corresponding IGeometry pointer.
- The engine uses triangle connectivity information in many places, so it is strongly recommended to have meshes closed and manifold. The function is able to recognize different vertices that represent the same point in space for connectivity calculations (there is no tolerance though, it checks only for exact duplicates). Open edges are ok only for geometries that will not be used as parts of dynamic physical entities and only if there will be little or no interaction with them.
- For collision detection the function can create either an OBB or a memory-optimized AABB or a single box tree. Selection is made by specifying the corresponding flag. If both AABB and OBB flags are specified, the function selects the tree that fits the geometry most tightly. Since an OBB tree is tighter in most cases, priority of AABBs can be boosted to save memory (also, AABB checks are slightly faster if the trees are equally tight). The engine can either copy the vertex/index data or use it directly from the pointers provided.
- The mesh_multycontact flags give some hints on whether multiple contacts are possible. Specifying that multiple contacts are unlikely (mesh_multycontact0) can improve performance a bit at the expense of missing multiple contacts if they do occur (note that it does not necessarily mean they will be missed, it is a hint for the algorithm to use some optimizations more aggressively). mesh_multycontact2 disables this optimization and ..1 is a recommended default setting. Convex geometries are detected and some additional optimizations are used for them, although internally there is no separate class for convex objects (this may change in the future).
- Meshes can have per-face materials. Materials are used to look up friction, bounciness, and pierceability coefficients and can be queried by the game as a part of collision detection output.
CreateMeshfunction is able to detect meshes that represent primitives (with the specified tolerance) and returns primitive objects instead. In order to activate this detection, the corresponding flags should be specified. Note that primitives can't store materials. They can only have one in the physical geometry structure, so this detection is not used when the material array has more than one material index in it.
CreatePrimitive: Creates a primitive geometry explicitly. The corresponding primitive (cylinder, sphere, box, heightfield, or ray) structure should be filled and passed as a parameter, along with its ::type.
RegisterGeometry: Physicalizes an IGeometry object by computing its physical properties and storing them in an auxiliary structure. Material index (surfaceidx) can be stored in it; it will be used if the geometry itself does not have any materials specified (such as if it is a primitive).
UnregisterGeometry comprise a reference "sandwich" for it. Note that the latter does not delete the object until its reference count becomes 0.
Geometries and physicalized geometries can be serialized. This allows to save time when computing OBB trees. That computation is not particularly slow but serialization is still faster.
Physical entities can be created via calls to the
CreatePhysicalEntity method of the physical world. It can create entities of the following types:
- PE_STATIC: Immovable entity. It can still be moved manually by setting positions from outside but in order to ensure proper interactions with simulated objects, it is better to use PE_RIGID entity with infinite mass.
- PE_RIGID: A single rigid body. Can have infinite mass (specified by setting mass to 0) in which case it will not be simulated but will interact properly with other simulated objects;
- PE_ARTICULATED: An articulated structure, consisting of several rigid bodies connected with joints (a ragdoll, for instance). It is also possible to manually connect several PE_RIGID entities with joints but in this case they will not know that they comprise a single object, and thus some useful optimizations will not be used.
- PE_WHEELEDVEHICLE: A wheeled vehicle. Internally it is built on top of a rigid body, with added vehicle functionality (wheels, suspensions, engine, brakes). PE_RIGID, PE_ARTICULATED and PE_WHEELEDVEHICLE are purely physical entities that comprise the core of the simulation engine. The other entities are processed independently;
- PE_LIVING: A special entity type to represent player characters that can move through the physical world and interact with it.
- PE_PARTICLE: A simple entity that represents a small lightweight rigid body. It is simulated as a point with some thickness and supports flying, sliding and rolling modes. Recommended usage: rockets, grenades and small debris.
- PE_ROPE: A rope object. It can either hang freely or connect two purely physical entities.
- PE_SOFT: A system of non-rigidly connected vertices that can interact with the environment. A typical usage is cloth objects.
Entities use a two-dimensional regular grid to speed up broad phase collision detection. This grid should be set up with a call to the
SetupEntityGrid function before any physical entities are created.
Entities can be created in either permanent or on-demand mode which is specified by the parameter lifeTime, which is 0 for permanent entities. In on-demand mode the placeholders of entities should be created first via
CreatePhysicalPlaceholder and then the physics will call the outer system back to create the full entity whenever some interaction is required in the bounding box of this placeholder (more on callbacks later).
If an entity is not involved in any interactions (which also includes interactions with rays shot from outside) for the specified lifetime, it will be destroyed, with the placeholder remaining. The advantage is that placeholders require much less memory than full entities (ca. 70 vs. ca. 260 bytes). It is even possible for an outer system to support hierarchical placeholders, i.e. meta-placeholders that create other placeholders upon request.
Additionally, there is a sector-based on-demand physicalization (currently used for vegetation). It is activated after
RegisterBBoxInPODGrid is called. Entities are created and destroyed on a sector basis. The sector size is specified in
In order to maintain associations with outside engine objects, physical entities store an additional void pointer and two 16-bit integers (pForeingData, iForeignData, and iForeignFlags). The entities themselves never modify these parameters, they are only set from outside. The intended usage is to store a pointer to the outside engine reference entity in pForeignData and to store the entity type, if applicable, in iForeignData. However, there are no restrictions that enforce this.
All physical entities have unique ids. It is possible to not specify an id during creation and let the physics engine generate one automatically, however, during serialization entities use these ids to save dependency information, so there should be a guarantee that entities will have the same ids when reading the saved state. It is also possible to set a new id later. Currently the physics engine uses a simple array to map ids to entity pointers, so using large id numbers will result in allocation of an equally large array.
DestroyPhysicalEntity destroys a physical entity or suspends/restores it (if mode parameter is equal to 0, 1, and 2 correspondingly). Suspending an entity causes it to clear all its connections with other entities (this includes constraints) but without the actual deletion. Restoring this entity afterwards will not automatically restore all lost connections. Deleted entities are not destroyed immediately, they are put into a "recycle bin" instead (some entities that they had one-way connections with might need to remove references to them). The recycle bin is emptied at the end of each TimeStep (this can also be forced by calling
The physical world can have one special static terrain object (set up with
SetHeightfieldData) but it is also possible to create terrain geometry manually and add it to an entity in which case the number of terrains is unlimited.
For each material index, the physical world stores the friction coefficient, a bounciness (restitution) coefficient and some flags. Whenever two surfaces contact, the contact's friction and bounciness are computed as an average of these values of both surfaces. The flags only affect raytracing (see below).
Internally, physical entities are grouped by their simulation mode. It is important to know this because some interface functions, such as ray tracing and querying entities in an area, allow filtering entities by this type. The types are:
- 0 (bitmask ent_static): Static entities
- 1 (bitmask ent_sleeping_rigid): Deactivated, purely physical objects (currently rigid bodies, articulated bodies and wheeled vehicles).
- 2 (bitmask ent_rigid): Active, purely physical objects.
- 3 (bitmask ent_living): Living entities.
- 4 (bitmask ent_inpependent): Physical entities that are simulated independently from the others (e.g. particles, ropes and soft objects). As a rule, entities that have a lower simulation type are not aware of entities with higher simulation types (types 1 and 2 are considered as one for this purpose), so players (type 3) and particles (type 4) check collisions against purely physical entities (types 1 and 2) but purely physical entities do not know anything about them. Similarly, ropes (type 4) can check collisions against players but not vice versa. However, entities of higher types can still affect entities with lower types using impulses and sometimes constraints.
- 6 (bitmask ent_triggers): Entities (or placeholders) that are not simulated and solely issue callbacks when other entities enter their bounding box.
- 7 (bitmask ent_deleted, should not be used directly): Objects in the recycle bin.
Terrain does not have a special simulation mode (it is considered as static) but can be filtered independently with the ent_terrain bitmask. Most entities expect a particular simulation mode (and will automatically be set to the proper value). However, there are exceptions, such as articulated entities which can be simulated in modes 1 and 2 as fully physicalized dead bodies or in mode 4 as skeletons that play impact animations without affecting the environment and being affected by it.
Most of the interactions with physical entities will go through the functions
Action. Entities can have multiple geometries ('physicalized geometries') which can be added with a call to
AddGeometry (there is a corresponding
RemoveGeometry function as well).
SetParams sets various parameters. These can always be queried later with
GetStatus requests the state of simulation parameters. The difference from
GetParams is that
GetStatus requests values that an entity is supposed to change during simulation, i.e. a simulation output, while
GetParams queries the simulation input parameters.
Action makes an entity execute some action like having an impulse added. All these functions take structure pointers as parameters. When you want to issue a particular command, create a corresponding structure somewhere (as a local variable, for example) and fill only the fields you need (most structures have more fields than you usually need to use in one call). The constructor of each structure fills all fields with a special value that tells the physics engine that this field was unused (the MARK_UNUSED macro can be used to do that explicitly and
is_unused to check if the field is unused).
AddGeometry adds a physicalized geometry to an entity. Each geometry has the following properties:
- id: A unique part identifier within the bounds of the entity the geometry belongs to. Can be either specified explicitly or generated automatically (
AddGeometryreturns this value). id never changes when the parts array changes (if some parts from the middle are removed, for instance) but the internal parts index might.
- position, orientation and uniform scaling relative to the entity
- mass: Makes sense only for non-static objects; static objects assume infinite mass in all interactions). It is possible to specify either mass or density where the complementary value will be computed automatically (using formula mass = density*volume; volume is stored in the physicalized geometry structure and is scaled if the geometry is scaled).
- surface_idx: Used if neither IGeometry nor physicalized geometry have surface (material) identifiers.
- flags and flagsCollider: Whenever an entity checks collisions against other objects, it checks only parts that have a flag mask which intersects its current part's flagsCollider (i.e.
[CRYENGINE:current entity part].flagsCollider & [CRYENGINE:potential collider part].flags != 0). There are 16 type bits that can be used (named geom_colltype) to represent some entity groups. Although it is not enforced, it is a good practice to keep these relationships symmetrical like this:
[CRYENGINE:entity A part i].flags & entity B part j].flagsCollider -> [CRYENGINE:entity B part j].flags & [CRYENGINE:entity A part i].flagsCollider
In situations when it is known that collision checks are one-sided (i.e. entity A can check collisions against entity B but never vice versa), it is ok to not maintain this rule. Some flags are reserved for special collision groups, such as geom_colltype1 is equal to geom_colltype_players and geom_colltype2 is equal to geom_colltype_explosion (i.e. whenever explosion pressure is calculated, only parts with this flag are considered). There are also special flags for ray-tracing and buoyancy calculations, geom_colltype_ray and geom_floats respectively (it is possible however to specify different flags to be used for raytraycing).
- minContactDist: Minimum distance between contacts which this part of the entity might have with another part of another entity (note that contacts belonging to different parts are not checked for this). Can be left unused so that it will be initialized with a default value based on geometry size.
Each part can have both geometry and proxy geometry. Geometry is used exclusively for raytracing and proxy geometry in all other cases. If no proxy geometry is specified, both geometries are set to be equal. The idea is to allow the raytracing to test against high-poly meshes without having to introduce changes to the part array layout.
Common Argument Structures
Sets position and orientation of the entity. One can use either offset/quaternion/scaling values directly or let the physics extract them from a 3x3 (orientation+scaling) or a 4x4 (orientation_scaling+offset) matrix. Physics use a right-to-left transformation order convention, with vectors being columns, i.e. vector_in_world = Matrix_Entity * Matrix_Entity_Parts * vector_in_geometry. All interface structures that support matrices can use either row-major or column-major matrix layout in memory (the latter is considered to be transposed, thus the corresponding member has T at the end of its name). Note that there is no per-entity scaling. Scaling is present only for parts so whenever a new scaling is set via pe_params_pos, it gets copied into each part and will override any previous individual scalings that the parts might have had. This structure also allows to set the simulation type manually. Normally, after the changes are made, entity bounds are recalculated and the entity gets re-registered in the collision hash grid although this can be postponed if bRecalcBounds is set to 0.
Allows to force an entity's bounding box to a particular value, or query it (when used with
GetParams). Normally, the bounding box is recalculated automatically basing on the geometries the entity has but setting it manually can be useful for entities without geometries (e.g. triggers) or placeholders. Note that if the entity has some geometries, it might recalculate its bounding box later, overriding these values. Bounding boxes are axis-aligned and in the world coordinate system.
Allows to specify an outer entity for an entity. Whenever a box of interest (namely its center) is inside the entity with an outer entity, this outer entity is excluded from the set of potential colliders. This way it is possible to have a building exterior quickly culled away when the region of interest is inside the building's interior. Outer entities can be nested and an optional geometry to test for containment is supported.
Sets or queries the entity part's properties. Part can be specified either using an internal part index or by its id.
Sets simulation parameters for entities that can accept these parameters (currently these are all purely physical entities, ropes, and soft entities). minEnergy is equal to sleep speed squared. Note that damping and gravity can be specified independently for colliding and falling (i.e. when there are no contacts) states.
Sets the buoyancy properties of the object and the water plane. The physics engine does not have a list of water volumes, so it is a responsibility of an outer system to update water plane parameters whenever they change. The water surface is assumed to be a perfect plane, so in order to simulate some bobbing on the waves one can perturb the normal of this surface. waterFlow specifies the water movement velocity (it will affect the object based on its waterResistance property). Note that a separate sleeping condition is used in the water (waterEmin).
Entities can have 'sensors' attached to them. Sensors are rays that the entity can shoot to sample the environment around it. It is more efficient to do it from inside the entity step than calling the world's raytracing function for every ray from outside. Currently only living entities support sensors and then only vertical down ones.
Allows to add a one-time impulse to an entity. impulse is the impulse property (in N*sec; impulse P will change object's velocity by P/[CRYENGINE:object mass]). point is a point in world space where the impulse is applied. It is used to calculate the rotational effects of the impulse. Instead of point, momentum can be used to specify the rotational impulse explicitly. If neither point nor momentum are specified, the impulse is assumed to be applied to the center of mass of the object. iApplyTime specifies the time when the impulse is applied. It is 2 ("after the next step") by default because if the object is lying on something, it is better to first give the solver an opportunity to reflect the impulse (it might even absorb it entirely) instead of trying to make a step with a potentially very high velocity first.
Adds a constraint between two objects (currently only purely physical entities support this action). Points specify the constraint positions in world space (if the second point is not unused and is different from the first one, the solver will attempt to bring them together). Relative positions are always fully constrained to be 0 (i.e. the points on the bodies will always have to be in one spot) and relative rotations can be constrained in twist and bend directions. These directions correspond to rotation around x-axis and remaining rotation around a line on the yz-plane (it describes the tilt of the x axis) of a relative transformation between the two constraint coordinate frames attached to the affected bodies. Original position of the constraint frames are specified with qframe parameters and can be specified either in world or entity coordinate space (as indicated by the corresponding flag in flags). If one or both qframes are unused, they are considered to be an identity transformation in either the world or entity frame. Rotation limits are specified with the xlimits and yzlimits parameters, with the element 0 being the minimum and element 1 the maximum (if the minimum is more than or equal to the maximum, the corresponding relative rotation is entirely prohibited). pConstraintEntity specifies an entity that represents the constraint (currently the only example is a rope which automatically creates a constraint between the entities it is tied to). When passed a pe_action_add_constraint pointer,
Action returns a constraint identifier (which can later be used to remove the constraint). It will never be 0, so 0 indicates a failure.
Sets velocity of an object directly. This is a very useful action for rigid bodies with infinite mass (represented as mass). It informs the physics system about the velocity that this body is moving with which will help the solver to ensure zero relative velocity with the objects it contacts (if velocity is not set and only position is changed, the engine will rely solely on penetrations to enforce the contacts). Note that velocity will not be automatically computed if position is set manually each frame. The body will continue moving with the specified velocity once it has been set.
Requests the current transformation (position, orientation, and scale) of an entity or its part. An alternative way is to use pe_params_pos with
GetParams. If some matrix pointers are set, the engine will fill them with data in the corresponding format. Note that the BBox member in this structure is relative to entity's position, unlike pe_params_bbox.
Serves as a common way for retrieving an entity's movement parameters. Acceleration and angular acceleration are computed based on gravity and interactions with other objects. Note that any external impulses that might have been added to the entity are not taken into account since they are deemed to be instantaneous. submergedFraction is a fraction of the entity's volume that was under water during the last frame (naturally, only parts with geom_float flag are considered). waterResistance contains the maximum water resistance the entity encountered during one frame since the last time this status was requested (this means the accumulated value is cleared when the status is returned). This value can be useful for generating splash effects.
Living Entity-Specific Argument Structures
Living entities use cylinders or capsules as their bounding geometry. Normally the cylinders are hovering above the ground and the entity shoots a single ray down to detect if it is standing on something. This cylinder geometry always occupies the first part slot (it is created automatically). It is possible to add more geometries manually but they will not be tested against the environment when the entity moves. Other entities however will process them when testing collisions against this entity. Living entities never change their orientation themselves - they are always set from outside. Normally, living entities are expected to rotate only around the z-axis but other orientations are supported with exception that collisions against livings entities always assume vertically oriented cylinders.
Sets the dimensions of the living entity's bounding geometry. heightPivot specifies the z-coordinate of a point in the entity frame that is considered to be at the feet level (usually 0). heightEye is the z-coordinate of the camera attached to the entity. This camera does not affect entity movement, its sole purpose is to smooth out height changes that the entity undergoes (during walking on a highly bumpy surface, such as stairs, after dimensions change and during landing after a period of flying). The camera position can be requested via the pe_status_living structure. sizeCollider specifies the size of the cylinder (x is radius, z is half-height, y is unused). heightColliders is the cylinder's center z-coordinate. The head is an auxiliary sphere that is checked for collisions with objects above the cylinder. Head collisions don't affect movement but they make the camera position go down. headRadius is the radius of this sphere and headHeight is the z-coordinate of its center in the topmost state (i.e. when it doesn't touch anything).
Sets a living entity's movement parameters. Living entities have their 'desired' (also called 'requested') movement velocity (set with pe_action_move) and they attempt to reach it. How fast that happens depends on the kInertia setting. The more this value is, the faster this velocity is reached. The default is 8 and 0 is a special case which means that the desired velocity will be reached instantly. kAirControl (0..1) specifies how strongly the requested velocity affects movement when the entity is flying (1 means that whenever a new requested velocity is set, it is copied to the actual movement velocity). kAirResistance describes how fast velocity is damped during flying. nodSpeed (default 60) sets the strength of camera reaction to landings. bSwimming is a flag that tells that the entity is allowed to attempt to move in all directions (gravity might still pull it down though). If not set, the requested velocity will always be projected on the ground if the entity is not flying. Living entities have several threshold angles that specify maximum or minimum ground slopes for certain activities (minSlideAngle, maxClimbAngle, maxJumpAngle and minFallAngle). Note that if an entity's bounding cylinder collides with a sloped ground, the behavior is not governed by these slopes only. Setting bNetwork makes the entity allocate a much longer movement history array which might be required for synchronization (if not set, this array will be allocated the first time network-related actions are requested, such as performing a step back). Setting bActive to 0 puts the living entity to a special 'inactive' state where it does not check collisions with the environment and only moves with the requested velocity (other entities can still collide with it, though; note that this applies only to the entities of the same or higher simulation classes).
Requests a movement from a living entity. dir is the requested velocity the entity will try to reach. If iJump is not 0, this velocity will not be projected on the ground and snapping to the ground will be turned off for a short period of time. If iJump is 1, the movement velocity is set to be equal to dir instantly. In case of 2, dir is added to it). dt is reserved for internal use.
Returns the status of a living entity. vel is the velocity that is averaged from the entity's position change over several frames. velUnconstrained is the current movement velocity. It can be different from vel because in many cases when the entity bumps into an obstacle, it will restrict the actual movement but keep the movement velocity the same, so that if on the next frame the obstacle ends, no speed will be lost. If the entity is standing on something, groundHeight and groundSlope will contain the point's z coordinate and normal, otherwise bFlying will be 1. Note that pGroundCollider is set only if the entity is standing on a non-static object. camOffset contains the current camera offset as a 3d vector in the entity frame (although only z coordinates actually changes in it). bOnStairs is a heuristic flag that indicates that the entity assumes that it is currently walking on stairs because of often and abrupt height changes.
Particle Entity-Specific Structures
Sets particle entity parameters. During movement, particles trace rays along their paths with the length size*0.5 (since size stands for 'diameter' rather than 'radius') to check if they hit something. When they already lie or slide, they positions themselves at a distance of thickness*0.5 from the surface (thus thin objects like shards of glass can be simulated). Particles can be set to have additional acceleration due to thrust of a lifting force (assuming that they have wings) with the parameters accThrust and accLift but these should never be used without specifying kAirResistance, otherwise particles will gain infinite velocity. Particles can optionally spin when in the air (toggled with flag particle_no_spin). Spinning is independent from linear motion of particles and is changed only after impacts or falling from surfaces. Particles can also align themselves with the direction of the movement (toggled with particle_no_path_alignment flag) which is very useful for objects like rockets. That way the y-axis of the entity is aligned with the heading and the z-axis is set to be orthogonal to y and to point upward ('up' direction is considered to be opposite to particle's gravity). When moving along a surface, particles can either slide or roll. Rolling can be disabled with the flag particle_no_roll (it is automatically disabled on steep slopes). Note that rolling uses the particle material's friction as damping while rolling treats friction in a conventional way. When touching ground, particles align themselves so that their normal (defined in entity frame) is parallel to the surface normal. Particles can always keep the initial orientation as well (particle_constant_orientation) and stop completely after the first contact (particle_single_contact). minBounceVel specifies the lower velocity threshold after which the particle will not bounce even if the bounciness of the contact is more than 0.
Articulated Entity-Specific Structures
Articulated entities consist of linked rigid bodies. Loops in linking are not allowed and the connection structure should be a tree with a single root. A structural unit of an articulated entity is a rigid body with a joint that connects it to its parent (there can be only one such joint). When an articulated entity is used to simulate some body effects without interactions with environment, it uses the Featherstone method which is tweaked to tolerate strong impacts and stiff springs in complex body structures. In interactive mode it uses a common solver.
Creates a joint between two bodies in an articulated entity or changes (or queries when used with
GetParams) parameters of an existing one. A joint is created between the two bodies specified in the op parameter at the pivot point (in the entity frame). Whenever a geometry is added to an articulated entity, it should use pe_articgeomparams to specify which body this geometry belongs to (in idbody). idbody can be any unique number and each body can have several geometries. There are no restrictions on the order in which joints are created but it is required that all bodies in the entity are connected before the simulation starts. Joints use Euler angles to define rotational limits. Flags that start with angle0_ can be specified for each angle individually by shifting them left by the 0-based angle index (for instance, to lock the z-axis one should OR the flags with
angle0_locked<<2). The coordinate frame of the child body is inherited from the first entity part (geometry) that was assigned to it. Joint angular limits are defined in a relative frame between the bodies that the joint connects. The frame of the child body can optionally be offset by specifying a child's orientation that corresponds to rotation angles (0,0,0) (using q0, pMtx0, or pMtx0T). This can help to get limits that can be robustly represented using Euler angles. A general rule regarding limits is to make upper and lower bounds at least 15-20 degrees apart (this depends on simulation settings though and on how high the velocity of this joint might be) and keep the y-axis limit in -90..90 degrees range (preferably within some safe margin from its ends). Note that in the parameter structure all angles are defined in radians. pe_params_joint uses 3d vectors to represent groups of 3 values that define some property for each angle. In addition to limits, each angle can have a spring that will pull the angle to 0 and a dashpot which will dampen the movement as the angle approaches its limit. For convenience, springs are specified in acceleration terms, i.e. the stiffness and damping can stay the same for joints that connect bodies with different masses (also, damping can be computed automatically to yield a critically damped spring by specifying auto_kd for the corresponding angle). joint_no_gravity makes the joint to be not affected by gravity (this can be useful if we assume that forces that hold the joint in its default position are just enough to counter the gravity) and joint_isolated_accelerations makes the joint use a special mode where it treats springs not like physical springs but rather like some guidelines on what the acceleration should be like (this mode is recommended for simulating effects on a skeleton). These two flags, as well as springs and dashpots, are currently only supported in Featherstone mode. Effective joint angles are always the sum of q and qext. If springs are activated, they attempt to drive q (but not qext) to 0. The idea behind this is to allow to set some pose from animation and then apply physical effects relative to it. In articulated entities collisions between parts are checked only for pairs that are explicitly specified in pSelfCollidingParts (thus this setting is per body or per joint rather than per part).
Allows to set and query articulated entity simulation mode parameters. Articulated entities can either be attached to something or be free, as set by the bGrounded flag (the latter is not supported in Featherstone mode). When grounded, the entity can either fetch dynamic parameters from the entity it is attached to (if bInreritVel is set; the entity is specified in pHost) or have them set in a, wa, w and v parameters. bCollisionResp effectively switches between Featherstone mode (0) and constraint mode (1). bCheckCollisions turns collision detection on and off. Currently it is supported only for constraint mode. iSimType specifies a simulation type which defines the way in which bodies that comprise the entity evolve. 0 means that joint pivots are always enforced exactly by projecting the movement of child bodies to a set of constrained directions and 1 means that bodies evolve independently and rely on the solver to enforce the joints. The second mode is not supported in Featherstone mode and in constraint mode it is turned on automatically if some bodies are moving fast enough (thus it makes sense to keep this value at 1 since it makes slow motion smoother). Articulated entities support a so called "lying mode" that is turned on when the number of contacts becomes more than a specified threshold (nCollLyingMode). Lying mode has a separate set of simulation parameters, such as gravity and damping. This feature was designed for ragdolls in order to help them look less sloppy when they hit the ground and to simulate the high damping of a human body in a simple way (this is achieved by setting gravity to a lower value and damping to higher than usual). Note that standard simulation parameters can still be different from freefall ones. When using constraint mode, articulated entities can try to represent hinge joints (i.e. rotational joints with only axis enabled) as two point-to-point constrains which can give better results in some cases. In order for this to happen, the entity should have the bExpandHinges parameter set (it internally propagates this value to joint_expand_hinge flags for all joints, so don't try to set it for joints manually).
Rope Entity-Specific Structures
Ropes are simulated as chains of connected equal-length sticks ("segments") with point masses. Each segment can individually collide with the environment. Ropes can tie two entities together in which case they will add a constraint to those when fully strained and won't affect their movement. In oder to collide with other objects (pushing them if necessary) in a strained state, the rope must use dynamic subdivision mode (set by rope_subdivide_segs flag). pe_params_rope specifies all the parameters a rope needs to start working (rope entities don't need any geometry). If initial point positions are not specified, the rope is assumed to be hanging down from its entity position and if they are, segments should have equal length, within some error margin. Note that ropes don't use materials to specify friction but rather an explicit friction value. If pe_params_rope is passed to
GetParams, pPoints will be a pointer to the first vertex in an internal rope vertex structure and iStride will contain the size of it.
Soft Entity-Specific Structures
There are two types of soft entities - mesh-based (they use a soft constraint-like solver; typically cloth objects) and tetrahedral lattice-based (they use a spring solver; typically jelly-like objects). The longest edges of all triangles can optionally be discarded with the sef_skip_longest_edges flag. Currently collisions are handled at vertex level only (vertices have a customizable thickness though) and work best against primitive geometries rather than meshes.
This is the main structure to set up a working soft entity (another one is pe_simulation_params). Here thickness is the collision size of vertices (they are therefore treated as spheres). If some edge differs from the original length by more than maxSafeStep, positional length enforcement kicks in. Spring damping is defined with kdRatio as a ratio to a critically damped value (overall damping from pe_simulation_params is also supported). Soft entities will react to wind if airResistance is not 0 (if wind is 0, having non-zero airResistance would mean that the entity will look like it is additionally damped - air resistance will attempt to even surface velocity with air velocity). Same will happen under water, only the parameters specified in pe_params_buoyancy will be used instead. Note that the Archimedean force that acts on vertices submerged in the water will depend on the entity's density which should be defined explicitly in pe_simulation_params (dependence will be same as for rigid bodies - the force will be 0 if waterDensity is equal to density). collTypes enables collisions with entities of a particular simulation type using ent_ masks.
Can be used to attach some of a soft entity's vertices to another physical entity. piVtx specifies vertex indices and points specify attachment positions in world space (if unused, current vertex positions will become attachment points).
World: Advancing the Physical World State
TimeStep functions make the entities advance their state by the specified time interval. If timeGranularity in the physical variables is set, the time interval will be snapped to an integer value with this granularity (i.e. if timeGranularity is 0.001, the time interval will be snapped to a milliseconds). Entities that perform the step can be filtered with ent_ flags in the flags parameter. flags can contain usual ent_ masks for simulation types and ent_flagged_only which will update entities only if they have the pef_update flag set. Specifying the ent_deleted flag will allow the world to flush its recycle bin and delete timeouted entities if physics-on-demand is used. Most entities have the maximum time step capped and in case of larger timesteps, they will have to perform several substeps. The number of substeps can be limited with the physics variable nMaxSubsteps.
GetEntitiesInBox uses the internal entity hash grid to return entities that have their bounding boxes overlapped with the specified box. The function supports typical filtering by simulation type and optional sorting of the output list by entity mass (in ascending order). If ent_alloctate_list is specified, the function allocates memory for the list (the memory can later be freed by a call to
pWorld->GetPhysUtils()->DeletePointer). Otherwise, an internal pointer will be returned. One should keep in mind that the physics system uses this pointer in almost all operations that require forming an entity list, thus no such calls should be made when the list is in use (or the list will be invalidated). If calls like this are required and memory allocation is undesired, one can copy the list to a local pre-allocated array before iterating over it.
The physical world has a dedicated function to cast rays into the environment (
RayWorldIntersection). Depending on the material the ray hits and the ray properties, a hit might be pierceable or solid. More precisely, a pierceable hit is a hit that has its material pierceability strictly higher than the ray's pierceability (material pierceability and ray pirceability occupy the lowest 4 bits of material flags and RayWorldIntersection flags correspondingly). Pierceable hits don't stop the ray and are accumulated as a sorted (by hit distance) list. The caller provides the function with an array for the hits. A solid hit (if any) always takes the slot with index 0 and pierceable hits slots from 1 to the end. Optionally, the function can separate between 'important' and 'unimportant' pierceable hits (importance is indicated by sf_important in material flags) and can make all important hits have higher priority (regardless of hit distance) than unimportant ones when competing for space in the array. By default RayWorldIntersection checks only entity parts with the geom_colltype_ray flag, but it is possible to specify another flag or combination of flags (in this case all flags should be set in part for it to be tested) by setting
flags |= geom_colltype_mask<<rwi_colltype_bit.
RayTraceEntity is a more low-level function and checks ray hits for one entity only. Tt returns only the closest hit. Alternatively,
CollideEntityWithBeam can perform a sweep-check with a sphere of the specified radius. Note that in order to reliably detect collisions, initially the sphere should be outside of the object. The org parameter corresponds to the sphere center.
World: Creating Explosions
SimulateExplosion is used to simulate explosions in a physical world. The only effect of explosions inside the physics system are impulses that are added to the nearby objects. A single impulse is calculated by integrating impulsive pressure at an area fragment multiplied by this area and scaled by its orientation towards the epicenter. Impulsive pressure has a falloff proportional to 1/distance2. If distance is smaller than rmin, it is clamped to rmin. impulsive_pressure_at_r is the impulsive pressure at distance r.
SimulateExplosion can optionally build an occlusion cubemap to find entities occluded from the explosion (nOccRe_s should be set to a non-zero cubemap resolution in one dimension in this case). First static entities are drawn into the cubemap and then dynamic entities (of the types specified in iTypes) are tested vs. this map (thus, dynamic entities never occlude each other). nOccRes can have the special value -1 that tells the function to reuse the cubemap from the last call and process only dynamic entities that were not processed during that call. This is useful when the code that creates the explosion decides to spawn new entities afterwards, such as debris or dead bodies, and wants to add explosion impulses to them without recomputing the occlusion map. Due to the projective nature of the cubemap, small objects very close to the epicenter can occlude more than they normally would. To counter this, rmin_occ can specify linear dimensions of a small cube that is subtracted from the environment when building the occlusion map (thus these small objects will be cropped). The downside is that it can make explosions go through thin walls, so some compromise value should be used. nGrow specifies the number of occlusion cubemap cells (in one dimension) that dynamic entities are inflated with. This can help explosions to reach around corners in a controllable way. After a call to
SimulateExplosion, the physics system can return how much a particular entity was affected by it (based on cubemap information) via a call to
IsAffectedByExplosion (returns fraction that was affected, 0..1). This function just performs a lookup into a stored entity list; the cubemap is not recomputed. The explosion epicenter for used for generating impulses can be made different from the one used to build a cubemap. One example of using this is creating explosions slightly below the ground to make things go up instead of just sidewards. Note that only parts with geom_colltype_explosion are processed in this function.