Geometries are first created as independent objects so that they can be used alone via the IGeometry
interface 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). There are several geometry management functions, listed below. They are accessible via the geometry manager, which is a part of physical world. The pointer to it is returned by the GetGeomManager
function.
CreateMesh: Creates a triangular mesh object from a set of vertices and indices (3 indices per triangle) and returns the corresponding IGeometry pointer.
CreateMesh
function 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.
IGeometry interface can be used to manually check collisions between geometries via Intersect function. It gives back detailed intersection results, which include all intersection regions with their borders and "unprojection" vectors. An unprojection vector tells how far one geometry can be moved along it to fully resolve the contact. It can either be set explicitly via geometry "velocity" or computed automatically based on intersection region. Continuous linear ("sweep") checks along a specified direction are also supported. In many cases, putting the moving geometry into its final position and "unprojecting" it back will give the same results as a sweep check (only faster), but it doesn't guarantee that it'll unproject to the first contact in complex cases (several manual iterations might be required).
When geometries are unprojected to a single contact point, the contact can optionally be extended to an area, by searching, matching, uniting, and intersecting neighboring features (polygon and polyline areas are supported).
For general meshes collisions are detected by finding some intersecting triangles using bounding trees, and then tracing the intersection border through the meshes using neighborhood (topology) information. Since 5.7, if the engine detects that both meshes are convex, and the query is non-continuous and doesn’t request a border, it uses a dedicated convex-vs-convex intersection check with penetration depth (the implementation is inspired by the GJK algorithm, but it had to be extended to handle penetration depth).
Another notable member of IGeometry interface is Subtract, which performs Boolean subtraction of meshes.
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). AddRefGeometry
and 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 by avoiding computing bounding volume trees. Normally that computation is not prohibitively slow, but serialization is still faster.