Laid Out Headers
This commit is contained in:
@@ -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;
|
||||
};
|
||||
}
|
@@ -12,5 +12,6 @@ namespace J3ML::Geometry
|
||||
LineSegment(const Vector3& a, const Vector3& b);
|
||||
Vector3 A;
|
||||
Vector3 B;
|
||||
bool Contains(const Vector3&) const;
|
||||
};
|
||||
}
|
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
}
|
@@ -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:
|
||||
};
|
||||
|
@@ -14,6 +14,8 @@ namespace J3ML::Geometry
|
||||
|
||||
bool Intersects(const AABB& aabb) const;
|
||||
AABB BoundingAABB() const;
|
||||
|
||||
bool Contains(const Vector3&) const;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -1,5 +1,8 @@
|
||||
#include <J3ML/Geometry/Common.h>
|
||||
#include <J3ML/Geometry/Frustum.h>
|
||||
#include <cmath>
|
||||
#include "J3ML/Geometry/AABB.h"
|
||||
#include <J3ML/Geometry/Polyhedron.h>
|
||||
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
@@ -10,12 +13,120 @@ namespace J3ML::Geometry
|
||||
|
||||
const Vector3 frontMultFar = cam.Front * zFar;
|
||||
|
||||
frustum.NearFace = Plane{cam.Position + cam.Front * zNear, cam.Front};
|
||||
frustum.FarFace = Plane{cam.Position + frontMultFar, -cam.Front};
|
||||
frustum.RightFace = Plane{cam.Position, Vector3::Cross(frontMultFar - cam.Right * halfHSide, cam.Up)};
|
||||
frustum.LeftFace = Plane{cam.Position, Vector3::Cross(cam.Up, frontMultFar+cam.Right*halfHSide)};
|
||||
frustum.TopFace = Plane{cam.Position, Vector3::Cross(cam.Right, frontMultFar - cam.Up * halfVSide)};
|
||||
frustum.BottomFace = Plane{cam.Position, Vector3::Cross(frontMultFar + cam.Up * halfVSide, cam.Right)};
|
||||
// frustum.NearFace = Plane{cam.Position + cam.Front * zNear, cam.Front};
|
||||
// frustum.FarFace = Plane{cam.Position + frontMultFar, -cam.Front};
|
||||
// frustum.RightFace = Plane{cam.Position, Vector3::Cross(frontMultFar - cam.Right * halfHSide, cam.Up)};
|
||||
// frustum.LeftFace = Plane{cam.Position, Vector3::Cross(cam.Up, frontMultFar+cam.Right*halfHSide)};
|
||||
// frustum.TopFace = Plane{cam.Position, Vector3::Cross(cam.Right, frontMultFar - cam.Up * halfVSide)};
|
||||
// frustum.BottomFace = Plane{cam.Position, Vector3::Cross(frontMultFar + cam.Up * halfVSide, cam.Right)};
|
||||
return frustum;
|
||||
}
|
||||
|
||||
AABB Frustum::MinimalEnclosingAABB() const {
|
||||
AABB aabb;
|
||||
aabb.SetNegativeInfinity();
|
||||
for(int i = 0; i < 8; ++i)
|
||||
aabb.Enclose(CornerPoint(i));
|
||||
return aabb;
|
||||
}
|
||||
|
||||
Vector3 Frustum::CornerPoint(int cornerIndex) const {
|
||||
assert(0 <= cornerIndex && cornerIndex <= 7);
|
||||
switch(cornerIndex)
|
||||
{
|
||||
default: // For release builds where assume() is disabled, return always the first option if out-of-bounds.
|
||||
case 0: return NearPlanePos(-1, -1);
|
||||
case 1: return FarPlanePos(-1, -1);
|
||||
case 2: return NearPlanePos(-1, 1);
|
||||
case 3: return FarPlanePos(-1, 1);
|
||||
case 4: return NearPlanePos(1, -1);
|
||||
case 5: return FarPlanePos(1, -1);
|
||||
case 6: return NearPlanePos(1, 1);
|
||||
case 7: return FarPlanePos(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 Frustum::NearPlanePos(float x, float y) const {
|
||||
assert(type == FrustumType::Perspective || type == FrustumType::Orthographic);
|
||||
|
||||
if (type == FrustumType::Perspective)
|
||||
{
|
||||
float frontPlaneHalfWidth = std::tan(horizontalFov*0.5f)*nearPlaneDistance;
|
||||
float frontPlaneHalfHeight = std::tan(verticalFov*0.5f)*nearPlaneDistance;
|
||||
x = x * frontPlaneHalfWidth; // Map [-1,1] to [-width/2, width/2].
|
||||
y = y * frontPlaneHalfHeight; // Map [-1,1] to [-height/2, height/2].
|
||||
Vector3 right = WorldRight();
|
||||
return pos + front * nearPlaneDistance + x * right + y * up;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 right = WorldRight();
|
||||
return pos + front * nearPlaneDistance
|
||||
+ x * orthographicWidth * 0.5f * right
|
||||
+ y * orthographicHeight * 0.5f * up;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 Frustum::FarPlanePos(float x, float y) const {
|
||||
assert(type == FrustumType::Perspective || type == FrustumType::Orthographic);
|
||||
|
||||
if (type == FrustumType::Perspective)
|
||||
{
|
||||
float farPlaneHalfWidth = std::tan(horizontalFov*0.5f)*farPlaneDistance;
|
||||
float farPlaneHalfHeight = std::tan(verticalFov*0.5f)*farPlaneDistance;
|
||||
|
||||
x = x * farPlaneHalfWidth;
|
||||
y = y * farPlaneHalfHeight;
|
||||
Vector3 right = WorldRight();
|
||||
return pos + front * farPlaneDistance + x * right + y * up;
|
||||
} else {
|
||||
Vector3 right = WorldRight();
|
||||
return pos + front * farPlaneDistance
|
||||
+ x * orthographicWidth * 0.5f * right
|
||||
+ y * orthographicHeight * 0.5f * up;
|
||||
}
|
||||
}
|
||||
|
||||
Polyhedron Frustum::ToPolyhedron() const {
|
||||
// Note to maintainer: this function is an exact copy of AABB::ToPolyhedron() and OBB::ToPolyhedron().
|
||||
|
||||
Polyhedron p;
|
||||
// Populate the corners of this Frustum.
|
||||
// They will be in the order 0: ---, 1: --+, 2: -+-, 3: -++, 4: +--, 5: +-+, 6: ++-, 7: +++.
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
p.v.push_back(CornerPoint(i));
|
||||
}
|
||||
|
||||
// generate the 6 faces of this Frustum. The function Frustum::GetPlane() has a convention of returning
|
||||
// the planes in order near, far, left, right, top, bottom, so follow the same convention here.
|
||||
const int faces[6][4] =
|
||||
{
|
||||
{ 0, 4, 6, 2 }, // Z-: near plane
|
||||
{ 1, 3, 7, 5 }, // Z+: far plane
|
||||
{ 0, 2, 3, 1 }, // X-: left plane
|
||||
{ 4, 5, 7, 6 }, // X+: right plane
|
||||
{ 7, 3, 2, 6 }, // Y+: top plane
|
||||
{ 0, 1, 5, 4 }, // Y-: bottom plane
|
||||
};
|
||||
|
||||
for (int f = 0; f < 6; ++f)
|
||||
{
|
||||
Polyhedron::Face face;
|
||||
if (this->handedness == FrustumHandedness::Left)
|
||||
{
|
||||
for (int v = 0; v < 4; ++v)
|
||||
face.v.push_back(faces[f][3-v]);
|
||||
} else {
|
||||
for (int v = 0; v < 4; ++v)
|
||||
face.v.push_back(faces[f][v]);
|
||||
}
|
||||
p.f.push_back(face);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
bool Frustum::Intersects(const Ray &ray) const {
|
||||
return this->ToPolyhedron().Intersects(ray);
|
||||
}
|
||||
}
|
@@ -1,5 +1,8 @@
|
||||
#include <J3ML/Geometry/Polyhedron.h>
|
||||
#include <J3ML/Geometry/AABB.h>
|
||||
#include <J3ML/Geometry/Triangle.h>
|
||||
#include <J3ML/Geometry/LineSegment.h>
|
||||
#include "J3ML/Geometry/Ray.h"
|
||||
|
||||
namespace J3ML::Geometry
|
||||
{
|
||||
@@ -15,5 +18,62 @@ namespace J3ML::Geometry
|
||||
return v[vertexIndex];
|
||||
}
|
||||
|
||||
bool Polyhedron::Contains(const Vector3 &point) const {
|
||||
|
||||
if (v.size() <= 3) {
|
||||
if (v.size() == 3)
|
||||
return Triangle(Vector3(v[0]), Vector3(v[1]), Vector3(v[2])).Contains(point);
|
||||
else if (v.size() == 2)
|
||||
return LineSegment(Vector3(v[0]), Vector3(v[1])).Contains(point);
|
||||
else if (v.size() == 1)
|
||||
return Vector3(v[0]).Equals(point);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int bestNumIntersections = 0;
|
||||
float bestFaceContainmentDistance = 0.f;
|
||||
|
||||
// For N > 4 Order Polyhedra
|
||||
// General strategy: pick a ray from the query point to a random direction, and count the number of times the ray intersects a face.
|
||||
// If it intersects an odd number of times, the given point must have been inside the polyhedron.
|
||||
// But unfortunately for numerical stability, we must be smart with the choice of the ray direction. If we pick a ray direction
|
||||
// which exits the polyhedron precisely at a vertex, or at an edge of two adjoining faces, we might count those twice. Therefore
|
||||
// Try to pick a ray direction that passes safely through a center of some face. If we detect that there was a tricky face that
|
||||
// the ray passed too close to an edge, we have no choice but to pick another ray direction and hope that it passes through
|
||||
// the polyhedron in a safe manner.
|
||||
|
||||
|
||||
// Loop through each face to choose the ray direction. If our choice was good, we only do this once and the algorithm
|
||||
// after the first iteration at j == 0. If not, we iterate more faces of the polyhedron to try to find one that is safe for
|
||||
// ray-polyhedron examination.
|
||||
for (int j = 0; j < (int)f.size(); ++j)
|
||||
{
|
||||
if (f[j].v.size() < 3)
|
||||
continue;
|
||||
|
||||
// Accumulate how many times the ray intersected a face of the polyhedron.
|
||||
int numIntersections = 0;
|
||||
// Track a pseudo-distance of the closest edge of a face that the ray passed through. If this distance ends up being too small,
|
||||
// we decide not to trust the result we got, and proceed to another iteration of j, hoping to guess a better-behaving direction
|
||||
// for the test ray.
|
||||
float faceContainmentDistance = INFINITY;
|
||||
|
||||
Vector3 Dir = ((Vector3)v[f[j].v[0]] + (Vector3)v[f[j].v[1]] + (Vector3)v[f[j].v[2]]) * 0.333333333333f - point;
|
||||
|
||||
//if (Dir.Normalize() <= 0.f)
|
||||
//continue;
|
||||
Ray r(Vector3(), Dir);
|
||||
|
||||
for (int i = 0; i < (int)f.size(); ++i)
|
||||
{
|
||||
Plane p((Vector3)v[f[i].v[0]] - point, (Vector3)v[f[i].v[1]] - point, (Vector3)v[f[i].v[2]] - point);
|
||||
|
||||
float d;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -426,5 +426,35 @@ namespace J3ML::LinearAlgebra {
|
||||
return GetColumn(index);
|
||||
}
|
||||
|
||||
Matrix4x4 Matrix3x3::operator*(const Matrix4x4 &rhs) const {
|
||||
auto lhs = *this;
|
||||
Matrix4x4 r;
|
||||
|
||||
r[0][0] = lhs.At(0, 0) * rhs.At(0, 0) + lhs.At(0, 1) * rhs.At(1, 0) + lhs.At(0, 2) * rhs.At(2, 0);
|
||||
r[0][1] = lhs.At(0, 0) * rhs.At(0, 1) + lhs.At(0, 1) * rhs.At(1, 1) + lhs.At(0, 2) * rhs.At(2, 1);
|
||||
r[0][2] = lhs.At(0, 0) * rhs.At(0, 2) + lhs.At(0, 1) * rhs.At(1, 2) + lhs.At(0, 2) * rhs.At(2, 2);
|
||||
r[0][3] = lhs.At(0, 0) * rhs.At(0, 3) + lhs.At(0, 1) * rhs.At(1, 3) + lhs.At(0, 2) * rhs.At(2, 3);
|
||||
|
||||
r[1][0] = lhs.At(1, 0) * rhs.At(0, 0) + lhs.At(1, 1) * rhs.At(1, 0) + lhs.At(1, 2) * rhs.At(2, 0);
|
||||
r[1][1] = lhs.At(1, 0) * rhs.At(0, 1) + lhs.At(1, 1) * rhs.At(1, 1) + lhs.At(1, 2) * rhs.At(2, 1);
|
||||
r[1][2] = lhs.At(1, 0) * rhs.At(0, 2) + lhs.At(1, 1) * rhs.At(1, 2) + lhs.At(1, 2) * rhs.At(2, 2);
|
||||
r[1][3] = lhs.At(1, 0) * rhs.At(0, 3) + lhs.At(1, 1) * rhs.At(1, 3) + lhs.At(1, 2) * rhs.At(2, 3);
|
||||
|
||||
r[2][0] = lhs.At(2, 0) * rhs.At(0, 0) + lhs.At(2, 1) * rhs.At(1, 0) + lhs.At(2, 2) * rhs.At(2, 0);
|
||||
r[2][1] = lhs.At(2, 0) * rhs.At(0, 1) + lhs.At(2, 1) * rhs.At(1, 1) + lhs.At(2, 2) * rhs.At(2, 1);
|
||||
r[2][2] = lhs.At(2, 0) * rhs.At(0, 2) + lhs.At(2, 1) * rhs.At(1, 2) + lhs.At(2, 2) * rhs.At(2, 2);
|
||||
r[2][3] = lhs.At(2, 0) * rhs.At(0, 3) + lhs.At(2, 1) * rhs.At(1, 3) + lhs.At(2, 2) * rhs.At(2, 3);
|
||||
|
||||
r[3][0] = rhs.At(3, 0);
|
||||
r[3][1] = rhs.At(3, 1);
|
||||
r[3][2] = rhs.At(3, 2);
|
||||
r[3][3] = rhs.At(3, 3);
|
||||
return r;
|
||||
}
|
||||
|
||||
Vector2 Matrix3x3::operator*(const Vector2 &rhs) const {
|
||||
return Transform(rhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -634,4 +634,16 @@ namespace J3ML::LinearAlgebra {
|
||||
return IsRowOrthogonal3(epsilon);
|
||||
}
|
||||
|
||||
bool Matrix4x4::IsColOrthogonal3(float epsilon) const {
|
||||
return GetColumn(0).IsPerpendicular(GetColumn(1), epsilon)
|
||||
&& GetColumn(0).IsPerpendicular(GetColumn(2), epsilon)
|
||||
&& GetColumn(1).IsPerpendicular(GetColumn(2), epsilon);
|
||||
}
|
||||
|
||||
bool Matrix4x4::IsRowOrthogonal3(float epsilon) const {
|
||||
return GetRow(0).IsPerpendicular(GetRow(1), epsilon)
|
||||
&& GetRow(0).IsPerpendicular(GetRow(2), epsilon)
|
||||
&& GetRow(1).IsPerpendicular(GetRow(2), epsilon);
|
||||
}
|
||||
|
||||
}
|
@@ -164,6 +164,24 @@ Vector4 Vector4::operator-(const Vector4& rhs) const
|
||||
std::abs(w - _w) < epsilon;
|
||||
}
|
||||
|
||||
float Vector4::operator[](std::size_t index) const {
|
||||
assert(index < 4);
|
||||
if (index==0) return x;
|
||||
if (index==1) return y;
|
||||
if (index==2) return z;
|
||||
if (index==3) return w;
|
||||
return 0;
|
||||
}
|
||||
|
||||
float &Vector4::operator[](std::size_t index) {
|
||||
assert(index < 4);
|
||||
if (index == 0) return x;
|
||||
if (index == 1) return y;
|
||||
if (index == 2) return z;
|
||||
if (index == 3) return w;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#pragma endregion
|
Reference in New Issue
Block a user