Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
1.0.0:physics [2023/03/16 08:41] – [Types of Body] admin1.0.0:physics [2023/03/16 14:18] (current) – [Override Collider-Registration] admin
Line 95: Line 95:
  
 ^Type ^Description ^ ^Type ^Description ^
-|TQ3BodyType.eStaticBody | Static bodies have no rigid body component attached to them, so the physics engine does not consider them to be moving. (Avoid moving these frequently or you'll violate that expectation). Use static colliders for level geometry like the ground and immovable walls, or stationary trigger volumes. Static colliders on their own won't set off trigger/collision messages, unless there's a Rigidbody on the other participant.| +|TQ3BodyType.eStaticBody | Static bodies have no rigid body component attached to them, so the physics engine does not consider them to be moving. (Avoid moving these frequently or you'll violate that expectation). Use static colliders for level geometry like the ground and immovable walls, or stationary trigger volumes. Static colliders on their own won't set off trigger/collision messages, unless there's a rigid body on the other participant.| 
-|TQ3BodyType.eDynamicBody|Dynamic bodies have a Rigidbody component attached to them and their eKinematic flag is not set. These objects move at the whims of physics according to their linear/angular velocities and the forces/torques and collision impacts exerted on them. The physics engine takes responsibility for resolving their collisions with static, kinematic, and other dynamic objects and rebounding them as needed. Use these for basic physics objects you want to be able to stack & topple and have them behave plausibly with minimal intervention, or for objects that you want to steer in a physics-focused way, like a rocketship.| +|TQ3BodyType.eDynamicBody|Dynamic bodies have a rigid body component attached to them and their eKinematic flag is not set. These objects move at the whims of physics according to their linear/angular velocities and the forces/torques and collision impacts exerted on them. The physics engine takes responsibility for resolving their collisions with static, kinematic, and other dynamic objects and rebounding them as needed. Use these for basic physics objects you want to be able to stack & topple and have them behave plausibly with minimal intervention, or for objects that you want to steer in a physics-focused way, like a rocketship.| 
-|TQ3BodyType.eKinematicBody|Kinematic bodies have a Rigidbody component with a set eKinematic flag. This tells the physics engine "this object moves, but I'll handle that part" — the kinematic object will process collisions with other rigidbodies, but only dynamic objects will automatically react by bouncing away, and cause messages to be sent. The kinematic object itself won't move except how you tell it to with MovePosition or MoveRotation — its velocity won't automatically integrate each timestep. Use this for objects that you want to control in ways that don't behave like simple physics bodies — like a bipedal character controller or highly custom vehicle controls. Use physics queries like overlap checks and shape casts to scan for collisions preemptively, since they won't stop your object automatically. |+|TQ3BodyType.eKinematicBody|Kinematic bodies have a rigid body component with a set eKinematic flag. This tells the physics engine "this object moves, but I'll handle that part" — the kinematic object will process collisions with other rigid bodies, but only dynamic objects will automatically react by bouncing away, and cause messages to be sent. The kinematic object itself won't move except how you tell it to with MovePosition or MoveRotation — its velocity won't automatically integrate each timestep. Use this for objects that you want to control in ways that don't behave like simple physics bodies — like a bipedal character controller or highly custom vehicle controls. Use physics queries like overlap checks and shape casts to scan for collisions preemptively, since they won't stop your object automatically. |
 ===== Colliders ===== ===== Colliders =====
  
Line 116: Line 116:
  
 On collider registration you push starting transformation information and shape data to the physics world: On collider registration you push starting transformation information and shape data to the physics world:
-  * AddBoxCollider() +^Method^ 
-  AddSphereCollider() +|procedure AddBoxCollider(const AControl : TControl3D; const APrefab : TGorillaColliderSettings);|Add a box collider for a specific TControl3D instance to the physics system. At first you will need to create a TGorillaColliderSettings structure, where to define the body type (static, dynamic, kinematic)| 
-  AddCapsuleCollider() +|procedure AddSphereCollider(const AControl : TControl3D; const APrefab : TGorillaColliderSettings);|Add a spherical collider for a specific TControl3D instance to the physics system. At first you will need to create a TGorillaColliderSettings structure, where to define the body type (static, dynamic, kinematic)| 
-  AddParticleCollider() +|procedure AddCapsuleCollider(const AControl : TControl3D; const APrefab : TGorillaColliderSettings; const ARadius, AHeight : Single);|Add a capsule collider for a specific TControl3D instance to the physics system. At first you will need to create a TGorillaColliderSettings structure, where to define the body type (static, dynamic, kinematic)| 
-  AddTerrainCollider() +|procedure AddParticleCollider(const AData : Pointer; const AType : PTypeInfo; const APrefab : TGorillaColliderSettings; const ATransformation : TMatrix3D; const ARadius : Single; out ABody : TQ3Body);|Add a particle collider for a specific pointer value to the physics system. At first you will need to create a TGorillaColliderSettings structure, where to define the body type (static, dynamic, kinematic). Also provide a starting transformation matrix and a radius of the particle. The procedure will return a TQ3Body instance as pointer which should be linked with your particle structure (AParticle). This method is automatically used by the physics particle influencer class.| 
-  AddMeshCollider()+|procedure AddTerrainCollider(const AMesh : TCustomMesh; const APrefab : TGorillaColliderSettings);|Add a terrain collider for a specific TCustomMesh (terrain) instance to the physics system. At first you will need to create a TGorillaColliderSettings structure, where to define the body type (static, dynamic, kinematic). Of course the body type is flexible, but for terrains you should use the static body type.| 
 +|procedure AddTerrainCollider(const ATerrain : TGorillaMesh; const APrefab : TGorillaColliderSettings);|Add a terrain collider for a specific TGorillaMesh instance to the physics system. At first you will need to create a TGorillaColliderSettings structure where to define the body type (static, dynamic, kinematic). Of course the body type is flexible, but for terrains you should use the static body type.| 
 +|procedure AddMeshCollider(const AMesh : TCustomMesh; const APrefab : TGorillaColliderSettings);|Add a capsule collider for a specific TCustomMesh instance to the physics system. At first you will need to create a TGorillaColliderSettings structure where to define the body type (static, dynamic, kinematic)| 
 +|procedure AddMeshCollider(const AMesh : TGorillaMesh; const APrefab : TGorillaColliderSettings);|Add a capsule collider for a specific TGorillaMesh instance to the physics system. At first you will need to create a TGorillaColliderSettings structure where to define the body type (static, dynamic, kinematic)|
  
 From there on the physics controller will compute transformation based on its own universe. From there on the physics controller will compute transformation based on its own universe.
Line 130: Line 133:
 [[#Remote-Control|Remote-Control]] [[#Remote-Control|Remote-Control]]
  
-Derived components of **TCustomMesh** and **TGorillaMesh** are supported for colliders.+Derived components of **TControl3D**, **TCustomMesh** and **TGorillaMesh** are supported for colliders. But for mesh or terrain colliders only TCustomMesh and TGorillaMesh/TGorillaModel are allowed. Other components do not have any vertex information. 
 + 
 +==== ColliderSettings / ColliderPrefab ==== 
 + 
 +Registering a collider for a 3D object expects collider settings (TGorillaColliderSettings) or a collider prefab (TGorillaPhysicsColliderPrefab). 
 + 
 +The collider prefab is a collection item for design time usage. It will automatically register a collider settings (TGorillaColliderSettings) for you when the physics system getting started. 
 + 
 +While the collider settings (TGorillaColliderSettings) is the core structure for collider registration. 
 + 
 +It gives you a number of possible settings: 
 + 
 +^Property ^Description^ 
 +|_Type|TGorillaPhysicsBodyType (TQ3BodyType.eStaticBody, TQ3BodyType.eDynamicBody or TQ3BodyType.eKinematicBody)| 
 +|LockRotAxisX|Locked rotation on the x axis.| 
 +|LockRotAxisY|Locked rotation on the y axis.| 
 +|LockRotAxisZ|Locked rotation on the z axis.| 
 +|LockMoveAxisX|Locked translation on the x axis.| 
 +|LockMoveAxisY|Locked translation on the y axis.| 
 +|LockMoveAxisZ|Locked translation on the z axis.| 
 +|LinearDamping|Linear Damping controls how much the physics body or constraint resists translation.| 
 +|AngularDamping|Angular Damping controls how much they resist rotating. | 
 +|Slop|Additional slop value, which will be added to the computed penetration depth on collision.| 
 +|AllowSubColliders|If a object hierarchy is provided as control, it will try to add the same kind of collider for all sub-elements. Caution: This may produce unexpected behaviour especially on dynamic colliders.| 
 +|AllowSleep|Allows a body to go in sleeping mode and save resources. By default TRUE.| 
 +|Active|Is body enabled for physics computation.| 
 +|Data|Setup colliderdata: friction, restitution, density, sensor ...| 
 +|Data.Friction|Friction is a force between two surfaces that are sliding, or trying to slide, across each other. For example, when you try to push a book along the floor, friction makes this difficult. Friction always works in the direction opposite to the direction in which the object is moving, or trying to move.| 
 +|Data.Restitution|The coefficient of restitution is a measure of how much kinetic energy remains after the collision of two bodies. Its value ranges from 0 to 1.| 
 +|Data.Density|It is the mass of a material substance per unit volume.| 
 +|Data.Sensor|A sensor is a device that detects and responds to some type of input from the physical environment.|
 ===== Threading ===== ===== Threading =====
  
Line 213: Line 246:
   * RemoteBodyImpulse   * RemoteBodyImpulse
   * RemoteBodyForce   * RemoteBodyForce
 +  * RemoteBodyVelocity
 +  * RemoteBodyAngularVelocity
  
 <file pascal> <file pascal>
Line 219: Line 254:
 </file> </file>
  
-By the methods above you're able to set a position and/or rotation explicitly, or to apply a force / impulse on a specific element.+By the methods above you're able to set a position and/or rotation explicitly, modify linear/angular velocity or to apply a force / impulse on a specific element.
  
 **__CAUTION:__ By this methods you can influence physical mechanics so heavily, that overstep bounds / limits or may lead to unexpected behaviour.** **__CAUTION:__ By this methods you can influence physical mechanics so heavily, that overstep bounds / limits or may lead to unexpected behaviour.**
  
 +**__WARNING:__ Modifying objects from the visual scene can have unexpected effects on collision detection. You may place or push an object inside another, which disables collision detection or causes unexpected behaviour!**
  
 ===== Example ===== ===== Example =====
 +
 +==== Runtime Integration ====
 +
 For a working physics system you need a TGorillaPhysicsSystem component on your form. For a working physics system you need a TGorillaPhysicsSystem component on your form.
  
Line 294: Line 333:
 </file> </file>
  
 +==== Override Collider-Registration ====
 +
 +Default collider registration methods only support TControl3D objects.
 +But it is sometimes needed to register other types of objects for colliders, like a virtual instance of a mesh.
 +
 +Writing a helper class gives you access to the protected internal registration methods which are unspecified by type:
 +^Method ^
 +|procedure DoAddBoxCollider(const AData : Pointer; const AType : PTypeInfo; const APrefab : TGorillaColliderSettings; const AAbsoluteMatrix : TMatrix3D; const ASize : TPoint3D; out ABody : TQ3Body); virtual;|
 +|procedure DoAddSphereCollider(const AData : Pointer; const AType : PTypeInfo; const APrefab : TGorillaColliderSettings; const AAbsoluteMatrix : TMatrix3D; const ARadius : Single; out ABody : TQ3Body); virtual;|
 +|procedure DoAddCapsuleCollider(const AData : Pointer; const AType : PTypeInfo; const APrefab : TGorillaColliderSettings; const AAbsoluteMatrix : TMatrix3D; const ARadius : Single; const AHeight : Single; out ABody : TQ3Body); virtual;|
 +|procedure DoAddTerrainCollider(const AData : Pointer; const AType : PTypeInfo; const APrefab : TGorillaColliderSettings; const AAbsoluteMatrix : TMatrix3D; const AMeshMatrix : TMatrix3D; const ASize : TPoint3D; const AMeshData : TMeshData; out ABody : TQ3Body); virtual;|
 +|procedure DoAddMeshCollider(const AData : Pointer; const AType : PTypeInfo; const APrefab : TGorillaColliderSettings; const AAbsoluteMatrix : TMatrix3D; const AMeshMatrix : TMatrix3D; const ASize : TPoint3D; const AMeshData : TMeshData; out ABody : TQ3Body); virtual;|
 +
 +<file pascal>
 +type
 +  /// <summary>
 +  /// Create a helper class to access protected methods for adding colliders.
 +  /// Default methods only handle TControl3D instances, but we
 +  /// want to add colliders dynamically for our virtual instances (TGorillaMeshInstance).
 +  /// </summary>
 +  TGorillaPhysicsHelper = class helper for TGorillaPhysicsSystem
 +    public
 +      procedure AddInstanceCollider(const ATemplate : TMeshDef;
 +        const AData: TGorillaMeshInstance; const APrefab: TGorillaColliderSettings;
 +        const AAbsoluteMatrix: TMatrix3D; const ASize: TPoint3D; const AFlipData : Boolean;
 +        out ABody: TQ3Body);
 +  end;
 +
 +{ TGorillaPhysicsHelper }
 +
 +procedure TGorillaPhysicsHelper.AddInstanceCollider(const ATemplate : TMeshDef;
 +  const AData: TGorillaMeshInstance; const APrefab: TGorillaColliderSettings;
 +  const AAbsoluteMatrix: TMatrix3D; const ASize: TPoint3D; const AFlipData : Boolean;
 +  out ABody: TQ3Body);
 +var LTransform : TMatrix3D;
 +begin
 +  // Get the translation from absolute instance matrix
 +  LTransform := TMatrix3D.CreateTranslation(
 +    TTransformationMatrixUtils.GetTranslationFromTransformationMatrix(AAbsoluteMatrix)
 +    );
 +
 +  // Add a sphere collider for each instance with the maximum size of a side as radius
 +  // or use another internal registration method, like DoAddBoxCollider, DoAddCapsuleCollider, ...
 +  DoAddSphereCollider(AData, TypeInfo(TGorillaMeshInstance), APrefab,
 +    LTransform, Max(ASize.X, Max(ASize.Y, ASize.Z)), ABody);
 +end;
 +</file>
 +
 +When you have declared this kind of helper class in your unit, the TGorillaPhysicsSystem component will then show you a new method to be callable "AddInstanceCollider".
 +
 +
 +==== Render Colliders ====
 +
 +You can render physics colliders for debugging purposes.
 +
 +The most easy way is to insert a TDummy component into your TGorillaViewport and leave all transformation (position, rotation and scaling) zero, to not affect collider rendering.
 +The add a "OnRender" event with the following code.
 +
 +<file pascal>
 +uses 
 +  Gorilla.Physics.Q3.Renderer;
 +
 +const
 +{$IFDEF DEBUG}
 +  SHOW_PHYSICS_COLLIDERS = true;
 +{$ELSE}
 +  SHOW_PHYSICS_COLLIDERS = false; 
 +{$ENDIF}
 +
 +procedure TForm1.Dummy1Render(Sender: TObject; Context: TContext3D);
 +var LRender : TQ3Render;
 +begin
 +  // Check if we want to see physics colliders
 +  if not SHOW_PHYSICS_COLLIDERS then
 +    Exit;
 +
 +  // Here we render physics colliders for debugging
 +  LRender.Context := Context;
 +  GorillaPhysicsSystem1.Engine.Render(@LRender);
 +end;
 +</file>
  
 Next step: [[fmodaudio|FMOD Audio]] Next step: [[fmodaudio|FMOD Audio]]