Eideren 1 yıl önce
ebeveyn
işleme
c71efce697

+ 1 - 1
en/manual/physics/index.md

@@ -19,7 +19,7 @@ This section explains how physics components work, how to add them to your proje
 * [Collider Shapes](collider-shapes.md): Define the geometric shape of yours collidable components
 * [Collider Shapes](collider-shapes.md): Define the geometric shape of yours collidable components
 * [Constraints](constraints.md): Create appealing and realistic physics
 * [Constraints](constraints.md): Create appealing and realistic physics
 * [Triggers](triggers.md): Use triggers to detect passing objects
 * [Triggers](triggers.md): Use triggers to detect passing objects
-* [Raycasting](raycasting.md): Trace intersecting objects
+* [Physics Queries](raycasting.md): Operations to find objects in the scene
 
 
 > [!WARNING]
 > [!WARNING]
 > Pages to redirect or recycle
 > Pages to redirect or recycle

+ 78 - 16
en/manual/physics/raycasting.md

@@ -1,26 +1,86 @@
-# Raycasting
+# Physics Queries
 
 
 <span class="badge text-bg-primary">Intermediate</span>
 <span class="badge text-bg-primary">Intermediate</span>
 <span class="badge text-bg-success">Programmer</span>
 <span class="badge text-bg-success">Programmer</span>
 
 
-> [!WARNING]
-> This page is outdated, the information contained therein are for Bullet, the previous physics engine
+**Physics Queries** are a set of operation to test and retrieve physics object in a given simulation, the most well known form of those queries is the `RayCast` which traces an invisible line through the scene to find intersecting [Collidables](colliders.md). This is useful, for example, to check which objects are in a gun's line of fire, or are under the mouse cursor when the user clicks.
 
 
-**Raycasting** traces an invisible line through the scene to find intersecting [colliders](colliders.md). This is useful, for example, to check which objects are in a gun's line of fire, or are under the mouse cursor when the user clicks.
+> [!Note]
+> Physics queries uses **collider shapes** to find objects. It ignores entities that have no Collidable Component attached or no collider shape set, see [Collidables](colliders.md).
 
 
->[!Note]
->Raycasting uses **colliders** to calculate intersections. It ignores entities that have no collider component. For more information, see [Colliders](colliders.md).
-
-To use a raycast, in the current [Simulation](xref:Stride.Physics.Simulation), use [Simulation.Raycast](xref:Stride.Physics.Simulation.Raycast(Stride.Core.Mathematics.Vector3,Stride.Core.Mathematics.Vector3,Stride.Physics.CollisionFilterGroups,Stride.Physics.CollisionFilterGroupFlags,System.Boolean,Stride.Physics.EFlags)).
+To raycast in the current [Simulation](xref:Stride.BepuPhysics.BepuSimulation), see the [Simulation API](xref:Stride.BepuPhysics.BepuSimulation).
 
 
 For an example of raycasting, see the **Physics Sample** project included with Stride.
 For an example of raycasting, see the **Physics Sample** project included with Stride.
 
 
-## Example code
+## Examples
+On left click, if there is a 'HostileUnit' in front of 'MyGun', deal damage to it
+```cs
+public override void Update()
+{
+    var simulation = Entity.GetSimulation();
+    MyGun.Transform.GetWorldTransformation(out var rayStart, out var worldRot, out _);
+    var rayDir = worldRot * Vector3.UnitZ;
+    float range = 10;
+    // All layers except 0 & 1
+    var layers = CollisionMask.Everything & ~(CollisionMask.Layer0 | CollisionMask.Layer1); 
+
+    if (Input.IsMouseButtonPressed(MouseButton.Left) && simulation.RayCast(rayStart, rayDir, range, out HitInfo hitResult, layers))
+    {
+        var hostile = hitResult.Collidable.Entity.Get<HostileUnit>();
+        if (hostile is not null)
+            hostile.DealDamage(10);
+    }
+}
+```
+Using the non-alloc version of a penetrating query to find multiple objects intersecting with the ray
+```cs
+var simulation = Entity.GetSimulation();
+Entity.Transform.GetWorldTransformation(out var rayStart, out var worldRot, out _);
+var rayDir = worldRot * Vector3.UnitZ; 
+
+// Allocates a working buffer on the stack for the penetrating test,
+// The 16 specified here would be the maximum item this test would keep track of, 
+// if the test finds more than 16 objects, it will yield the 16 closest ones
+System.Span<HitInfoStack> buffer = stackalloc HitInfoStack[16];
+
+// The order in which elements are yielded throughout this foreach is not guaranteed
+// Some hitInfo with a smaller distance may be returned after one with a larger one,
+// and the opposite is also true.
+foreach (var hitInfo in simulation.RayCastPenetrating(rayStart, rayDir, 100f, buffer))
+{
+    Log.Warning($"T: {hitInfo.Distance}\nNormal: {hitInfo.Normal}\nEntity : {hitInfo.Collidable.Entity}");
+}
+```
+Moves a box through the scene and return what it collided with
+```cs
+var simulation = Entity.GetSimulation();
+Entity.Transform.GetWorldTransformation(out var center, out var worldRot, out _);
+var rayDir = worldRot * Vector3.UnitZ;
+var initialPose = new RigidPose(center, worldRot);
+var displacement = new BodyVelocity(rayDir, default);
+var shape = new Box(0.25f, 0.25f, 0.25f);
 
 
-This code sends a raycast from the mouse's screen position:
+if (simulation.SweepCast(shape, initialPose, displacement, 10, out HitInfo hitInfo))
+{
+    Log.Warning($"T: {hitInfo.Distance}\nNormal: {hitInfo.Normal}\nEntity : {hitInfo.Collidable.Entity}");
+}
+```
+Find up to 16 physics object a box placed at that position would overlap with
+```cs
+var simulation = Entity.GetSimulation();
+Entity.Transform.GetWorldTransformation(out var center, out var worldRot, out _);
+var initialPose = new RigidPose(center, worldRot);
+var shape = new Box(0.25f, 0.25f, 0.25f);
 
 
+System.Span<CollidableStack> buffer = stackalloc CollidableStack[16];
+foreach (var hit in simulation.Overlap(shape, initialPose, buffer))
+{
+    Log.Warning($"Entity : {hit.Entity}");
+}
+```
+Send a raycast from the mouse's screen position:
 ```cs
 ```cs
-public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, CameraComponent camera, Simulation simulation)
+public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, CameraComponent camera)
 {
 {
     Matrix invViewProj = Matrix.Invert(camera.ViewProjectionMatrix);
     Matrix invViewProj = Matrix.Invert(camera.ViewProjectionMatrix);
 
 
@@ -44,17 +104,19 @@ public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, Camer
     var vectorFar = Vector3.Transform(sPos, invViewProj);
     var vectorFar = Vector3.Transform(sPos, invViewProj);
     vectorFar /= vectorFar.W;
     vectorFar /= vectorFar.W;
 
 
+    var delta = (vectorFar - vectorNear).XYZ();
+    var maxDistance = delta.Length();
+    var dir = delta / maxDistance; // normalize delta
+
     // Raycast from the point on the near plane to the point on the far plane and get the collision result
     // Raycast from the point on the near plane to the point on the far plane and get the collision result
-    var result = simulation.Raycast(vectorNear.XYZ(), vectorFar.XYZ());
-    return result.Succeeded;
+    return camera.Entity.GetSimulation().RayCast(vectorNear.XYZ(), dir, maxDistance, out HitInfo hit);
 }
 }
 ```
 ```
 
 
 >[!Note]
 >[!Note]
 >There are multiple ways to retrieve a reference to this `Simulation` from inside one of your `ScriptComponent`:
 >There are multiple ways to retrieve a reference to this `Simulation` from inside one of your `ScriptComponent`:
->- The recommended way is through a reference to a physics component, something like `myRigidBody.Simulation` or `myCollision.Simulation` as it is the fastest.
->- Then through `SceneSystem` by calling `SceneSystem.SceneInstance.GetProcessor<PhysicsProcessor>()?.Simulation`.
->- Or through `this.GetSimulation()`, note that the `this` is required as it is an extension method.
+>- The recommended way is through a reference to a physics component, something like `myBody.Simulation` as it is the fastest.
+>- Or through the `Entity.GetSimulation()` extension method.
 
 
 ## See also
 ## See also
 * [Colliders](colliders.md)
 * [Colliders](colliders.md)

+ 6 - 0
en/manual/physics/simulation.md

@@ -19,6 +19,12 @@ Those rules can be set by modifying the collision matrix at runtime, or through
 
 
 For example, pressing `Change values...`  next to `Layer0` and un-ticking `Layer1` would cause all objects on `Layer0` to pass through objects on `Layer1`.
 For example, pressing `Change values...`  next to `Layer0` and un-ticking `Layer1` would cause all objects on `Layer0` to pass through objects on `Layer1`.
 
 
+## Retrieving the Simulation
+
+There are multiple ways to retrieve a reference to this `BepuSimulation` from inside one of your `ScriptComponent`:
+- The recommended way is through a reference to a physics component, something like `myBody.Simulation` as it is the fastest.
+- Or through the `Entity.GetSimulation()` extension method.
+
 ## See also
 ## See also
 * [Colliders](colliders.md)
 * [Colliders](colliders.md)
 * [Collider shapes](collider-shapes.md)
 * [Collider shapes](collider-shapes.md)