Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Geometry/RaySphere.h
9913 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
#include <Jolt/Math/FindRoot.h>
8
9
JPH_NAMESPACE_BEGIN
10
11
/// Tests a ray starting at inRayOrigin and extending infinitely in inRayDirection against a sphere,
12
/// @return FLT_MAX if there is no intersection, otherwise the fraction along the ray.
13
/// @param inRayOrigin Ray origin. If the ray starts inside the sphere, the returned fraction will be 0.
14
/// @param inRayDirection Ray direction. Does not need to be normalized.
15
/// @param inSphereCenter Position of the center of the sphere
16
/// @param inSphereRadius Radius of the sphere
17
JPH_INLINE float RaySphere(Vec3Arg inRayOrigin, Vec3Arg inRayDirection, Vec3Arg inSphereCenter, float inSphereRadius)
18
{
19
// Solve: |RayOrigin + fraction * RayDirection - SphereCenter|^2 = SphereRadius^2 for fraction
20
Vec3 center_origin = inRayOrigin - inSphereCenter;
21
float a = inRayDirection.LengthSq();
22
float b = 2.0f * inRayDirection.Dot(center_origin);
23
float c = center_origin.LengthSq() - inSphereRadius * inSphereRadius;
24
float fraction1, fraction2;
25
if (FindRoot(a, b, c, fraction1, fraction2) == 0)
26
return c <= 0.0f? 0.0f : FLT_MAX; // Return if origin is inside the sphere
27
28
// Sort so that the smallest is first
29
if (fraction1 > fraction2)
30
std::swap(fraction1, fraction2);
31
32
// Test solution with lowest fraction, this will be the ray entering the sphere
33
if (fraction1 >= 0.0f)
34
return fraction1; // Sphere is before the ray start
35
36
// Test solution with highest fraction, this will be the ray leaving the sphere
37
if (fraction2 >= 0.0f)
38
return 0.0f; // We start inside the sphere
39
40
// No solution
41
return FLT_MAX;
42
}
43
44
/// Tests a ray starting at inRayOrigin and extending infinitely in inRayDirection against a sphere.
45
/// Outputs entry and exit points (outMinFraction and outMaxFraction) along the ray (which could be negative if the hit point is before the start of the ray).
46
/// @param inRayOrigin Ray origin. If the ray starts inside the sphere, the returned fraction will be 0.
47
/// @param inRayDirection Ray direction. Does not need to be normalized.
48
/// @param inSphereCenter Position of the center of the sphere.
49
/// @param inSphereRadius Radius of the sphere.
50
/// @param outMinFraction Returned lowest intersection fraction
51
/// @param outMaxFraction Returned highest intersection fraction
52
/// @return The amount of intersections with the sphere.
53
/// If 1 intersection is returned outMinFraction will be equal to outMaxFraction
54
JPH_INLINE int RaySphere(Vec3Arg inRayOrigin, Vec3Arg inRayDirection, Vec3Arg inSphereCenter, float inSphereRadius, float &outMinFraction, float &outMaxFraction)
55
{
56
// Solve: |RayOrigin + fraction * RayDirection - SphereCenter|^2 = SphereRadius^2 for fraction
57
Vec3 center_origin = inRayOrigin - inSphereCenter;
58
float a = inRayDirection.LengthSq();
59
float b = 2.0f * inRayDirection.Dot(center_origin);
60
float c = center_origin.LengthSq() - inSphereRadius * inSphereRadius;
61
float fraction1, fraction2;
62
switch (FindRoot(a, b, c, fraction1, fraction2))
63
{
64
case 0:
65
if (c <= 0.0f)
66
{
67
// Origin inside sphere
68
outMinFraction = outMaxFraction = 0.0f;
69
return 1;
70
}
71
else
72
{
73
// Origin outside of the sphere
74
return 0;
75
}
76
break;
77
78
case 1:
79
// Ray is touching the sphere
80
outMinFraction = outMaxFraction = fraction1;
81
return 1;
82
83
default:
84
// Ray enters and exits the sphere
85
86
// Sort so that the smallest is first
87
if (fraction1 > fraction2)
88
std::swap(fraction1, fraction2);
89
90
outMinFraction = fraction1;
91
outMaxFraction = fraction2;
92
return 2;
93
}
94
}
95
96
JPH_NAMESPACE_END
97
98