Skip to content

Commit ea7510c

Browse files
committed
Update RayCasting.md
1 parent 082f534 commit ea7510c

File tree

2 files changed

+94
-20
lines changed

2 files changed

+94
-20
lines changed

docs/VirtualAnatomy/ExplorerLevel/MeshSelection/RayCasting.md

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
As mentioned, we have chosen ray casting as the primary method for selecting which objects the user clicks on.
77

88
The way it works is that when the user clicks on the screen, we receive coordinates about where the mouse was clicked (in screen space). We then transform this mouse location to world space and calculate the direction from our character to the point where the mouse clicked. This direction is normalized, meaning it has a length of 1.
9+
After that, we specify a ray length parameter to determine where the ray should end and then cast the ray from the character’s position towards the calculated endpoint.
910

10-
Next, we specify a ray length parameter to determine where the ray should end.
11-
12-
After that, we shoot the ray from the position of our character towards the calculated end of the ray.
11+
Previously, the system used basic ray-object collision detection techniques, but we have now implemented the Möller-Trumbore algorithm for more precise intersection testing with triangles in the scene. This algorithm allows efficient ray-triangle intersection detection, making it particularly useful for accurate selection of 3D models and surfaces.
1312

1413
All of these calculations are performed once the user presses the left mouse button.
1514

@@ -25,13 +24,11 @@ The main responsibility of the `RayCaster` class is to trace the actual rays thr
2524

2625
----
2726

28-
### `RayCaster(UWorld* world = nullptr)`
29-
30-
**Parameters:**
27+
### `RayCaster()`
3128

32-
- `UWorld* world ` - world to use for ray casting
29+
Constructor initializing the m_world and m_currentHitComponent to nullptr.
3330

34-
The constructor takes a world as a parameter, which can be `nullptr` by default since the "world" does not exist during construction time.
31+
`m_world` is set initially to `nullptr` since the "world" does not exist during construction time.
3532

3633
However, you can construct this class in other places besides constructors.
3734

@@ -76,17 +73,23 @@ Therefore, before each intersection test, you must ensure that the world is set
7673

7774
----
7875

79-
### `bool TraceLine(FVector start, FVector rayDirection, float rayLength = 1000)`
76+
### `bool TraceLine(FVector start, FVector rayDirection, float rayLength, FVector& outHitPoint, FVector& outHitNormal, int32& outTriangleIndex, float& outU, float& outV)`
77+
78+
Performs a precise ray trace, detecting triangle-level intersections on static meshes.
8079

8180
**Parameters:**
8281

83-
- `FVector start` - The starting point of the ray in world space.
84-
- `FVector rayDirection` - The direction in which the ray will travel.
85-
- `float rayLength` - The length of the ray, default value is 1000.
82+
- `start`- the starting point of the ray
83+
- `rayDirection`- the direction of the ray
84+
- `rayLength`- the length of the ray
85+
- `outHitPoint`- stores the location where the ray hits
86+
- `outHitNormal`- stores the normal of the hit surface
87+
- `outTriangleIndex`- stores the index of the hit triangle (-1 if no triangle was hit)
88+
- `outU, outV`- Barycentric coordinates of the hit point
8689

8790
**Returns:**
8891

89-
- `True` if a hit was detected.
92+
- `True` if an intersection is found.
9093
- `False` otherwise.
9194

9295
This function uses the `LineTraceSingleByChannel` method from the `UWorld` class to trace the provided ray through the world. By default, it uses the **Visible** channel for intersection testing, meaning only objects that are visible within the scene will be tested for intersection.
@@ -95,6 +98,63 @@ If a hit is detected, the actor that caused the intersection will be stored in t
9598

9699
Lastly, all actors that were added via `AddIngoredActor` method will be ignored
97100

101+
---
102+
103+
### `UMeshComponent* GetCurrentHitComponent() const`
104+
105+
Returns the mesh component that was hit by the last raycast.
106+
107+
108+
## Private methods
109+
110+
---
111+
112+
### `bool RayTriangleIntersect(const FVector& rayOrigin, const FVector& rayDirection, const FVector& v0, const FVector& v1, const FVector& v2, float& outDistance, float& outU, float& outV, FVector& outNormal)`
113+
114+
Uses the Möller-Trumbore algorithm to determine if a ray intersects a specific triangle in a mesh.
115+
116+
**Parameters:**
117+
- `rayOrigin (FVector)`- the starting point of the ray.
118+
- `rayDirection (FVector)`- the normalized direction vector of the ray.
119+
- `v0 (FVector)`- the first vertex of the triangle.
120+
- `v1 (FVector)`- the second vertex of the triangle.
121+
- `v2 (FVector)`- the third vertex of the triangle.
122+
- `outDistance (float)`- the distance from the ray origin to the intersection point (if any).
123+
- `outU (float)`- the barycentric coordinate U of the intersection point.
124+
- `outV (float)`- the barycentric coordinate V of the intersection point.
125+
- `outNormal (FVector)`- the normal of the intersected triangle.
126+
127+
**Returns:**
128+
- `true` if the ray intersects the triangle.
129+
- `false` otherwise.
130+
---
131+
132+
### `bool GetTriangleVertices(UStaticMeshComponent* staticMeshComp, int32 triangleIndex, FVector& outV0, FVector& outV1, FVector& outV2)`
133+
134+
Retrieves the world-space vertices of a given triangle from a static mesh.
135+
136+
**Parameters:**
137+
- `staticMeshComp (UStaticMeshComponent)`- the static mesh component from which to retrieve triangle data.
138+
- `triangleIndex (int32)`- the index of the triangle within the mesh.
139+
- `outV0 (FVector)`- the first vertex of the triangle in world space.
140+
- `outV1 (FVector)`- the second vertex of the triangle in world space.
141+
- `outV2 (FVector)`- the third vertex of the triangle in world space.
142+
143+
**Returns:**
144+
- `true` if the triangle vertices were successfully retrieved.
145+
- `false` otherwise.
146+
147+
---
148+
149+
### `void DrawOBB(UMeshComponent* meshComponent, float duration = 2.0f, float thickness = 2.0f)`
150+
151+
Draws the Oriented Bounding Box (OBB) for debugging purposes.
152+
153+
**Parameters:**
154+
- `meshComponent (UMeshComponent)`- the mesh component to visualize.
155+
- `duration (float, optional)`- the duration (in seconds) for which the debug box remains visible. *(Default: 2.0s)*
156+
- `thickness (float, optional)`- the line thickness of the debug box. *(Default: 2.0)*
157+
98158
## Private members
99159

100160
---
@@ -129,5 +189,21 @@ World in which the ray casting and intersection testing will take place
129189

130190
Actor that was hit by the constructed ray. This is `nullptr` if no actor was hit.
131191

192+
---
193+
194+
### `int32 m_lastHitTriangleIndex`
195+
196+
Index of the last hit triangle in the static mesh.
197+
198+
---
199+
200+
### `FVector m_lastHitPoint`
201+
202+
World-space position of the last successful hit.
203+
204+
---
205+
206+
### `FVector m_lastHitNormal`
132207

208+
Normal of the last successfully hit triangle.
133209

docs/VirtualAnatomy/ExplorerLevel/User.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ The camera and spring arm are created and added to the root component of the cha
6060
6161
```c++
6262
//for spring arm it is named camera boom as most of the Unreal Engine comunty gives this name to it
63-
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("Camera Boom"));
63+
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("Camera Boom"));
6464
6565
//add to the root of the player
6666
CameraBoom->SetupAttachment(RootComponent);
@@ -69,9 +69,8 @@ The camera and spring arm are created and added to the root component of the cha
6969
The camera is created in similuar manner and is added as a **child** of `CameraBoom`
7070

7171
```c++
72-
MainCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Main camera"));
73-
MainCamera->SetupAttachment(CameraBoom,USpringArmComponent::SocketName);
74-
72+
MainCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Main camera"));
73+
MainCamera->SetupAttachment(CameraBoom,USpringArmComponent::SocketName);
7574
```
7675
7776
If you visit the `BP_User` and open the viewport, you can see both the spring arm and camera there.
@@ -81,7 +80,7 @@ If you visit the `BP_User` and open the viewport, you can see both the spring ar
8180
![camera and user in view port](https://jrcz-data-science-lab.github.io/VirtualAnatomy-Documentation/images/camera-and-spring-arm-in-view-port.png)
8281
8382
84-
## Public fiels
83+
## Public fiels
8584
8685
----
8786
@@ -120,7 +119,6 @@ For example, if you want the user to start spinning once the game starts, you wo
120119
121120
Here we set up our default `TargetActor` and `RayCaster`, since both of them require access to the `World`, and the `World` is not accessible during construction time (e.g., in the constructor).
122121
123-
124122
-----
125123
126124
### `void Tick(float DeltaTime);`
@@ -287,7 +285,7 @@ Rotates the character around the `TargetActor` this method is being called insid
287285
----
288286
289287
290-
### `void ZoomToTheActor(const float& LookInput)`
288+
### `void ZoomToTheActor(const float& LookInput)`
291289
292290
**Parameters:**
293291

0 commit comments

Comments
 (0)