Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Geometry/Plane.h
21760 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
JPH_NAMESPACE_BEGIN
8
9
/// An infinite plane described by the formula X . Normal + Constant = 0.
10
class [[nodiscard]] Plane
11
{
12
public:
13
JPH_OVERRIDE_NEW_DELETE
14
15
/// Constructor
16
Plane() = default;
17
explicit Plane(Vec4Arg inNormalAndConstant) : mNormalAndConstant(inNormalAndConstant) { }
18
Plane(Vec3Arg inNormal, float inConstant) : mNormalAndConstant(inNormal, inConstant) { }
19
20
/// Create from point and normal
21
static Plane sFromPointAndNormal(Vec3Arg inPoint, Vec3Arg inNormal) { return Plane(Vec4(inNormal, -inNormal.Dot(inPoint))); }
22
23
/// Create from point and normal, double precision version that more accurately calculates the plane constant
24
static Plane sFromPointAndNormal(DVec3Arg inPoint, Vec3Arg inNormal) { return Plane(Vec4(inNormal, -float(DVec3(inNormal).Dot(inPoint)))); }
25
26
/// Create from 3 counter clockwise points
27
static Plane sFromPointsCCW(Vec3Arg inV1, Vec3Arg inV2, Vec3Arg inV3) { return sFromPointAndNormal(inV1, (inV2 - inV1).Cross(inV3 - inV1).Normalized()); }
28
29
// Properties
30
Vec3 GetNormal() const { return Vec3(mNormalAndConstant); }
31
void SetNormal(Vec3Arg inNormal) { mNormalAndConstant = Vec4(inNormal, mNormalAndConstant.GetW()); }
32
float GetConstant() const { return mNormalAndConstant.GetW(); }
33
void SetConstant(float inConstant) { mNormalAndConstant.SetW(inConstant); }
34
35
/// Store as 4 floats
36
void StoreFloat4(Float4 *outV) const { mNormalAndConstant.StoreFloat4(outV); }
37
38
/// Offset the plane (positive value means move it in the direction of the plane normal)
39
Plane Offset(float inDistance) const { return Plane(mNormalAndConstant - Vec4(Vec3::sZero(), inDistance)); }
40
41
/// Transform the plane by a matrix
42
inline Plane GetTransformed(Mat44Arg inTransform) const
43
{
44
Vec3 transformed_normal = inTransform.Multiply3x3(GetNormal());
45
return Plane(transformed_normal, GetConstant() - inTransform.GetTranslation().Dot(transformed_normal));
46
}
47
48
/// Scale the plane, can handle non-uniform and negative scaling
49
inline Plane Scaled(Vec3Arg inScale) const
50
{
51
Vec3 scaled_normal = GetNormal() / inScale;
52
float scaled_normal_length = scaled_normal.Length();
53
return Plane(scaled_normal / scaled_normal_length, GetConstant() / scaled_normal_length);
54
}
55
56
/// Distance point to plane
57
float SignedDistance(Vec3Arg inPoint) const { return inPoint.Dot(GetNormal()) + GetConstant(); }
58
59
/// Project inPoint onto the plane
60
Vec3 ProjectPointOnPlane(Vec3Arg inPoint) const { return inPoint - GetNormal() * SignedDistance(inPoint); }
61
62
/// Returns intersection point between 3 planes
63
static bool sIntersectPlanes(const Plane &inP1, const Plane &inP2, const Plane &inP3, Vec3 &outPoint)
64
{
65
// We solve the equation:
66
// |ax, ay, az, aw| | x | | 0 |
67
// |bx, by, bz, bw| * | y | = | 0 |
68
// |cx, cy, cz, cw| | z | | 0 |
69
// | 0, 0, 0, 1| | 1 | | 1 |
70
// Where normal of plane 1 = (ax, ay, az), plane constant of 1 = aw, normal of plane 2 = (bx, by, bz) etc.
71
// This involves inverting the matrix and multiplying it with [0, 0, 0, 1]
72
73
// Fetch the normals and plane constants for the three planes
74
Vec4 a = inP1.mNormalAndConstant;
75
Vec4 b = inP2.mNormalAndConstant;
76
Vec4 c = inP3.mNormalAndConstant;
77
78
// Result is a vector that we have to divide by:
79
float denominator = Vec3(a).Dot(Vec3(b).Cross(Vec3(c)));
80
if (denominator == 0.0f)
81
return false;
82
83
// The numerator is:
84
// [aw*(bz*cy-by*cz)+ay*(bw*cz-bz*cw)+az*(by*cw-bw*cy)]
85
// [aw*(bx*cz-bz*cx)+ax*(bz*cw-bw*cz)+az*(bw*cx-bx*cw)]
86
// [aw*(by*cx-bx*cy)+ax*(bw*cy-by*cw)+ay*(bx*cw-bw*cx)]
87
Vec4 numerator =
88
a.SplatW() * (b.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, SWIZZLE_UNUSED>() - b.Swizzle<SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_X, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_Z, SWIZZLE_X, SWIZZLE_Y, SWIZZLE_UNUSED>())
89
+ a.Swizzle<SWIZZLE_Y, SWIZZLE_X, SWIZZLE_X, SWIZZLE_UNUSED>() * (b.Swizzle<SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Y, SWIZZLE_UNUSED>() - b.Swizzle<SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Y, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_UNUSED>())
90
+ a.Swizzle<SWIZZLE_Z, SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_UNUSED>() * (b.Swizzle<SWIZZLE_Y, SWIZZLE_W, SWIZZLE_X, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_W, SWIZZLE_X, SWIZZLE_W, SWIZZLE_UNUSED>() - b.Swizzle<SWIZZLE_W, SWIZZLE_X, SWIZZLE_W, SWIZZLE_UNUSED>() * c.Swizzle<SWIZZLE_Y, SWIZZLE_W, SWIZZLE_X, SWIZZLE_UNUSED>());
91
92
outPoint = Vec3(numerator) / denominator;
93
return true;
94
}
95
96
private:
97
#ifdef JPH_OBJECT_STREAM
98
friend void CreateRTTIPlane(class RTTI &); // For JPH_IMPLEMENT_SERIALIZABLE_OUTSIDE_CLASS
99
#endif
100
101
Vec4 mNormalAndConstant; ///< XYZ = normal, W = constant, plane: x . normal + constant = 0
102
};
103
104
JPH_NAMESPACE_END
105
106