Laid Out Headers

This commit is contained in:
2024-04-04 20:00:23 -04:00
parent de108630b6
commit fb7aba71b1
12 changed files with 470 additions and 26 deletions

View File

@@ -10,17 +10,17 @@
namespace J3ML::Geometry
{
using J3ML::LinearAlgebra::CoordinateFrame;
/// A frustum can be set to one of the two common different forms.
enum class FrustumType
{
Invalid,
Invalid = 0,
/// Set the Frustum type to this value to define the orthographic projection formula. In orthographic projection,
/// 3D images are projected onto a 2D plane essentially by flattening the object along one direction (the plane normal).
/// The size of the projected images appear the same independent of their distance to the camera, and distant objects will
/// not appear smaller. The shape of the Frustum is identical to an oriented bounding box (OBB).
Orthographic,
/// Set the Frustum type to this value to use the perspective projection formula. With perspective projection, the 2D
/// image is formed by projecting 3D points towards a single point (the eye point/tip) of the Frustum, and computing the
/// point of intersection of the line of the projection and the near plane of the Frustum.
@@ -29,17 +29,183 @@ namespace J3ML::Geometry
Perspective
};
class Frustum : public Shape {
public:
Plane TopFace;
Plane BottomFace;
Plane RightFace;
Plane LeftFace;
Plane FarFace;
Plane NearFace;
static Frustum CreateFrustumFromCamera(const CoordinateFrame& cam, float aspect, float fovY, float zNear, float zFar);
AABB MinimalEnclosingAABB() const;
/// The Frustum class offers choosing between the two common conventions for the value ranges in
/// post-projective space. If you are using either the OpenGL or Direct3D API, you must feed the API data that matches
/// the correct convention.
enum class FrustumProjectiveSpace
{
Invalid = 0,
/// If this option is chosen, the post-projective unit cube of the Frustum
/// is modelled after the OpenGL API convention, meaning that in projected space,
/// points inside the Frustum have the X and Y range in [-1, 1] and Z ranges in [-1, 1],
/// where the near plane maps to Z=-1 and the far plane maps to Z=1.
/// @note If you are submitting projection matrices to GPU hardware using the OpenGL API,
/// you **must** use this convention. (or otherwise more than half of the precision of the GL depth buffer is wasted)
GL,
/// If this option is chosen, the post-projective unit cube is modelled after the
/// Direct3D API convention, which differs from the GL convention that Z ranges in [0, 1] instead.
/// Near plane maps to Z=0, and far plane maps to Z=1. The X and Y ranges in [-1, 1] as is with GL.
/// @note If you are submitting projection matrices to GPU hardware using the Direct3D API,
/// you **must** use this convention.
D3D,
};
/// The handedness rule in J3ML bundles together two different conventions related to the camera:
/// * the chirality of the world and view spaces,
/// * the fixed local front direction of the Frustum.
/// @note The world and view spaces are always assumed to the same chirality, meaning that Frustum::ViewMatrix()
/// (and hence Frustum::WorldMatrix()) always returns a matrix with a positive determinant, i.e. it does not mirror.
/// If FrustumRightHanded is chosen, then Frustum::ProjectionMatrix() is a mirroring matrix, since the post-projective space
/// is always left-handed.
/// @note Even though in the local space of the camera +Y is always up, in the world space one can use any 'world up' direction
/// as one pleases, by orienting the camera via the Frustum::up vector.
enum class FrustumHandedness
{
Invalid = 0,
/// If a Frustum is left-handed, then in the local space of the Frustum (the view space), the camera looks towards +Z,
/// while +Y goes towards up, and +X goes towards right.
/// @note The fixed-pipeline D3D9 API traditionally used the FrustumLeftHanded convention.
Left,
/// If a Frustum is right-handed, then the camera looks towards -Z, +Y is up, and +X is right.
/// @note The fixed-pipeline OpenGL API traditionally used the FrustumRightHanded convention.
Right
};
/// Represents either an orthographic or a perspective viewing frustum.
class Frustum : public Shape {
public: /// Members
/// Specifies whether this frustum is a perspective or an orthographic frustum.
FrustumType type;
/// Specifies whether the [-1, 1] or [0, 1] range is used for the post-projective depth range.
FrustumProjectiveSpace projectiveSpace;
/// Specifies the chirality of world and view spaces
FrustumHandedness handedness;
/// The eye point of this frustum
Vector3 pos;
/// The normalized direction this frustum is watching towards.
Vector3 front;
/// The normalized up direction for this frustum.
/// This vector is specified in world (global) space. This vector is always normalized.
/// @note The vectors front and up must always be perpendicular to each other. This means that this up vector is not
/// a static/constant up vector, e.g. (0, 1, 0), but changes according to when the camera pitches up and down to
/// preserve the condition that front and up are always perpendicular
/// @note In the _local_ space of the Frustum, the direction +y is _always_ the up direction and cannot be changed. This
/// coincides to how Direct3D and OpenGL view and projection matrices are constructed
Vector3 up;
/// Distance from the eye point to the front plane
/// This parameter must be positive. If perspective projection is used, this parameter must be strictly positive
/// (0 is not allowed). If orthographic projection is used, 0 is possible (but uncommon, and not recommended).
/// When using the Frustum class to derive perspective projection matrices for a GPU, it should be noted that too
/// small values cause poor resolution of Z values near the back plane in post-perspective space, if non-linear
/// depth is used (which is common). The larger this value is, the more resolution there is for the Z values across the
/// depth range. Too large values cause clipping of geometry when they come very near the camera. */
float nearPlaneDistance;
/// Distance from the eye point to the back plane of the projection matrix.
/// This parameter must be strictly greater than nearPlaneDistance. The range [nearPlaneDistance, farPlaneDistance]
// specifies the visible range of objects inside the Frustum. When using the Frustum class for deriving perspective
// projection matrix for GPU rendering, it should be remembered that any geometry farther from the camera (in Z value)
// than this distance will be clipped from the view, and not rendered.
float farPlaneDistance;
union {
/// Horizontal field-of-view, in radians. This field is only valid if type == PerspectiveFrustum.
/** @see type. */
float horizontalFov;
/// The width of the orthographic frustum. This field is only valid if type == OrthographicFrustum.
/** @see type. */
float orthographicWidth;
};
union {
/// Vertical field-of-view, in radians. This field is only valid if type == PerspectiveFrustum.
/** @see type. */
float verticalFov;
/// The height of the orthographic frustum. This field is only valid if type == OrthographicFrustum.
/** @see type. */
float orthographicHeight;
};
void WorldMatrixChanged();
void ProjectionMatrixChanged();
/// Frustums are typically used in batch culling operations.
/// Therefore the matrices associated with a frustum are cached for immediate access.
Matrix4x4 worldMatrix;
Matrix4x4 projectionMatrix;
Matrix4x4 viewProjectionMatrix;
public: /// Methods
Frustum();
static Frustum CreateFrustumFromCamera(const CoordinateFrame& cam, float aspect, float fovY, float zNear, float zFar);
AABB MinimalEnclosingAABB() const;
OBB MinimalEnclosingOBB() const;
void SetKind(FrustumProjectiveSpace projectiveSpace, FrustumHandedness handedness);
void SetViewPlaneDistances(float nearPlaneDistance, float farPlaneDistance);
void SetFrame(const Vector3& pos, const Vector3& front, const Vector3& up);
void SetPos(const Vector3& pos);
void SetFront(const Vector3& front);
void SetUp(const Vector3& up);
void SetPerspective(float horizontalFov, float verticalFov);
void SetOrthographic(float orthographicWidth, float orthographicHeight);
FrustumHandedness Handedness() const { return handedness; }
FrustumType Type() const { return type; }
FrustumProjectiveSpace ProjectiveSpace() const { return projectiveSpace;}
const Vector3 &Pos() const {return pos;}
const Vector3 &Front() const { return front; }
const Vector3 &Up() const { return up; }
float NearPlaneDistance() const { return nearPlaneDistance; }
float FarPlaneDistance() const { return farPlaneDistance;}
float HorizontalFov() const { return horizontalFov;}
float VerticalFov() const { return verticalFov;}
float OrthographicWidth() const { return orthographicWidth; }
float OrthograhpicHeight() const { return orthographicHeight; }
int NumEdges() const { return 12; }
float AspectRatio() const;
void SetHorizontalFovAndAspectRatio(float horizontalFov, float aspectRatio);
Vector3 CornerPoint(int cornerIndex) const;
Vector3 NearPlanePos(float x, float y) const;
Vector3 FarPlanePos(float x, float y) const;
Vector3 WorldRight() const;
Plane TopPlane() const;
Plane BottomPlane() const;
Plane RightPlane() const;
Plane LeftPlane() const;
Plane FarPlane() const;
Plane NearPlane() const;
float NearPlaneWidth() const;
float NearPlaneHeight() const;
void Translate(const Vector3& offset);
void Transform(const Matrix3x3& transform);
void Transform(const Matrix4x4& transform);
void Transform(const Quaternion& transform);
Polyhedron ToPolyhedron() const;
bool Intersects(const Ray& ray) const;
//bool Intersects(const Line& line) const;
bool Intersects(const LineSegment& lineSegment) const;
bool Intersects(const AABB& aabb) const;
bool Intersects(const OBB& obb) const;
bool Intersects(const Plane& plane) const;
bool Intersects(const Triangle& triangle) const;
bool Intersects(const Polygon& lineSegment) const;
bool Intersects(const Sphere& aabb) const;
bool Intersects(const Capsule& obb) const;
bool Intersects(const Frustum& plane) const;
bool Intersects(const Polyhedron& triangle) const;
};
}

View File

@@ -12,5 +12,6 @@ namespace J3ML::Geometry
LineSegment(const Vector3& a, const Vector3& b);
Vector3 A;
Vector3 B;
bool Contains(const Vector3&) const;
};
}

View File

@@ -11,10 +11,19 @@ namespace J3ML::Geometry
{
public:
Plane() : Shape() {}
Plane(const Vector3& v1, const Vector3 &v2, const Vector3& v3)
{
Set(v1, v2, v3);
}
Plane(const Vector3& pos, const Vector3& norm)
: Shape(), Position(pos), Normal(norm) {}
Vector3 Position;
Vector3 Normal;
float distance = 0.f;
void Set(const Vector3& v1, const Vector3& v2, const Vector3& v3)
{
}
};
}

View File

@@ -40,6 +40,33 @@ namespace J3ML::Geometry
Vector3 Vertex(int vertexIndex) const;
bool Intersects(const LineSegment&) const;
bool Contains(const Vector3&) const;
bool Contains(const LineSegment&) const;
bool Contains(const Triangle&) const;
bool Contains(const Polygon&) const;
bool Contains(const AABB&) const;
bool Contains(const OBB&) const;
bool Contains(const Frustum&) const;
bool Contains(const Polyhedron&) const;
bool ContainsConvex(const Vector3&, float epsilon = 1e-4f) const;
bool ContainsConvex(const LineSegment&) const;
bool ContainsConvex(const Triangle&) const;
bool Intersects(const Ray&) const;
bool Intersects(const Plane&) const;
bool Intersects(const Polyhedron&) const;
bool Intersects(const AABB&) const;
bool Intersects(const OBB&) const;
bool Intersects(const Triangle&) const;
bool Intersects(const Polygon&) const;
bool Intersects(const Frustum&) const;
bool Intersects(const Sphere&) const;
bool Intersects(const Capsule&) const;
protected:
private:
};

View File

@@ -14,6 +14,8 @@ namespace J3ML::Geometry
bool Intersects(const AABB& aabb) const;
AABB BoundingAABB() const;
bool Contains(const Vector3&) const;
};

View File

@@ -132,7 +132,6 @@ namespace J3ML::LinearAlgebra {
Vector2 operator * (const Vector2& rhs) const;
Vector3 operator * (const Vector3& rhs) const;
Vector4 operator * (const Vector4& rhs) const;
Matrix3x3 operator * (const Matrix3x3& rhs) const;
Matrix4x4 operator * (const Matrix4x4& rhs) const;
Matrix3x3 Mul(const Matrix3x3& rhs) const;

View File

@@ -25,10 +25,10 @@ namespace J3ML::LinearAlgebra {
return {x, y, z};
}
float GetX() const;
float GetY() const;
float GetZ() const;
float GetW() const;
float GetX() const { return x; }
float GetY() const { return y; }
float GetZ() const { return z; }
float GetW() const { return w; }
#if MUTABLE
void SetX(float newX) { x = newX;}
void SetY(float newY) { y = newY;}
@@ -39,12 +39,21 @@ namespace J3ML::LinearAlgebra {
static const Vector4 NaN;
float operator[](std::size_t index) const;
float &operator[](std::size_t index);
bool IsWithinMarginOfError(const Vector4& rhs, float margin=0.0001f) const;
bool IsNormalized(float epsilonSq = 1e-5f) const;
bool IsZero(float epsilonSq = 1e-6f) const;
bool IsFinite() const;
bool IsPerpendicular(const Vector4& other, float epsilonSq=1e-5f) const;
bool IsPerpendicular(const Vector4& other, float epsilonSq=1e-5f) const
{
float dot = Dot(other);
return dot*dot <= epsilonSq * LengthSquared() * other.LengthSquared();
}
bool IsPerpendicular3(const Vector4& other, float epsilonSq = 1e-5f) const
{
}
bool operator==(const Vector4& rhs) const;
bool operator!=(const Vector4& rhs) const;