Simple clipping approach
This commit is contained in:
parent
184b9aa245
commit
c0a00e4e4a
@ -19,6 +19,9 @@
|
||||
// * https://ktstephano.github.io/rendering/stratusgfx/aabbs
|
||||
// * https://en.wikipedia.org/wiki/Clipping_(computer_graphics)
|
||||
// * https://www.coranac.com/tonc/text/mode7.htm
|
||||
// * https://en.wikipedia.org/wiki/Back-face_culling
|
||||
// * https://en.wikipedia.org/wiki/Hidden-surface_determination#Occlusion_culling
|
||||
// * https://en.wikipedia.org/wiki/Bounding_volume_hierarchy
|
||||
|
||||
Graphic3DRenderer::Graphic3DRenderer() {
|
||||
mRTSize = {1280.f, 324.f};
|
||||
@ -87,6 +90,82 @@ void Graphic3DRenderer::Draw(sf::RenderTexture& context) {
|
||||
sf::RenderStates sRS(sBM);
|
||||
|
||||
// Hardcoded debug movement, TODO: remove it
|
||||
UpdateInternalTestObjects();
|
||||
|
||||
// Load main matrices
|
||||
M3D_MATRIX viewMat = mMainCamera->GetView();
|
||||
M3D_MATRIX projMat = mMainCamera->GetProj();
|
||||
M3D_MATRIX viewProjMat = viewMat * projMat;
|
||||
|
||||
// Create the frustrum "box"
|
||||
M3D_BoundingFrustum camFrustrum(projMat, false);
|
||||
camFrustrum.Transform(camFrustrum, M3D_MInverse(viewMat));
|
||||
|
||||
// Process scene's objects
|
||||
for (auto& obj : mRenderList) {
|
||||
M3D_BoundingBox projAABB = obj->GetAABB();
|
||||
auto oTMat = obj->GetTransform();
|
||||
|
||||
// Object outside frustrum clipping
|
||||
projAABB.Transform(projAABB, oTMat);
|
||||
M3D_ContainmentType objInFrustrum = camFrustrum.Contains(projAABB);
|
||||
if (objInFrustrum != DISJOINT) {
|
||||
size_t vCount = obj->GetObjectVerticesCount();
|
||||
auto& oMesh = obj->GetObjectMesh();
|
||||
M3D_F3 projVertices[vCount];
|
||||
|
||||
// Vertices NDC space transformation
|
||||
M3D_V3TransformPersDiv(
|
||||
projVertices, sizeof(M3D_F3),
|
||||
reinterpret_cast<const M3D_F3*>(oMesh.vertices.data()), sizeof(Vertex),
|
||||
vCount,
|
||||
oTMat * viewProjMat
|
||||
);
|
||||
|
||||
// Draw the object indice triangles
|
||||
sf::Vertex v_tri[4];
|
||||
for (auto& objPt : oMesh.parts) {
|
||||
auto indicePtr = static_cast<const uint32_t*>(objPt.indices.data());
|
||||
|
||||
for (uint32_t i = 0; i < objPt.GetIndicesCount(); i += 3) {
|
||||
// Misscontructed indices tree failsafe
|
||||
if (i+2 > objPt.GetIndicesCount())
|
||||
break;
|
||||
|
||||
// Triangle clipping
|
||||
//TODO: implement complete Cohen-Sutherland algo or similar
|
||||
M3D_VECTOR V1 = M3D_V4LoadF3(&projVertices[indicePtr[i]]);
|
||||
M3D_VECTOR V2 = M3D_V4LoadF3(&projVertices[indicePtr[i+1]]);
|
||||
M3D_VECTOR V3 = M3D_V4LoadF3(&projVertices[indicePtr[i+2]]);
|
||||
|
||||
V1 = M3D_V3TransformNDCToViewport(V1, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f);
|
||||
V2 = M3D_V3TransformNDCToViewport(V2, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f);
|
||||
V3 = M3D_V3TransformNDCToViewport(V3, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f);
|
||||
|
||||
sf::Color vColor;
|
||||
if (objInFrustrum == DISJOINT)
|
||||
vColor = sf::Color::Red;
|
||||
else if (objInFrustrum == INTERSECTS)
|
||||
vColor = sf::Color::Yellow;
|
||||
else
|
||||
vColor = oMesh.vertices[indicePtr[i]].color;
|
||||
|
||||
v_tri[0].position = sf::Vector2f(M3D_V4GetX(V1), M3D_V4GetY(V1));
|
||||
v_tri[0].color = vColor;
|
||||
v_tri[3] = v_tri[0];
|
||||
v_tri[1].position = sf::Vector2f(M3D_V4GetX(V2), M3D_V4GetY(V2));
|
||||
v_tri[1].color = vColor;
|
||||
v_tri[2].position = sf::Vector2f(M3D_V4GetX(V3), M3D_V4GetY(V3));
|
||||
v_tri[2].color = vColor;
|
||||
context.draw(v_tri, 4, sf::LineStrip, sRS);
|
||||
//context.draw(v_tri, 3, sf::Triangles, sRS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Graphic3DRenderer::UpdateInternalTestObjects() {
|
||||
static float thetaAngle = 0.31f;
|
||||
thetaAngle = thetaAngle >= 6.283185f ? -6.283185f : thetaAngle + 0.004f;
|
||||
static float thetaAngle2 = 2.12f;
|
||||
@ -97,62 +176,4 @@ void Graphic3DRenderer::Draw(sf::RenderTexture& context) {
|
||||
mRenderList[1]->SetRotation(thetaAngle2, 0.f, thetaAngle2 * 0.5f);
|
||||
mRenderList[2]->SetRotation(thetaAngle3, 0.f, thetaAngle3 * 0.5f);
|
||||
mRenderList[3]->SetRotation(0.f, thetaAngle, 0.f);
|
||||
|
||||
M3D_MATRIX viewProjMat = mMainCamera->GetView() * mMainCamera->GetProj();
|
||||
sf::Vertex v_tri[4];
|
||||
|
||||
uint32_t totVerticesCnt = 0, processedVerticesCnt = 0;
|
||||
for (auto obj : mRenderList)
|
||||
totVerticesCnt += obj->GetObjectMesh().GetVerticesCount();
|
||||
|
||||
// Do the vertices projection and perspective divide
|
||||
M3D_F3 projVertices[totVerticesCnt];
|
||||
for (auto obj : mRenderList) {
|
||||
auto& oMesh = obj->GetObjectMesh();
|
||||
M3D_V3TransformPersDiv(
|
||||
projVertices + processedVerticesCnt, sizeof(M3D_F3),
|
||||
reinterpret_cast<const M3D_F3*>(oMesh.vertices.data()), sizeof(M3D_F4),
|
||||
oMesh.vertices.size(),
|
||||
obj->GetTransform() * viewProjMat
|
||||
);
|
||||
|
||||
//TODO: Fill a z-depth buffer...
|
||||
|
||||
for (auto& objPt : obj->GetObjectMesh().parts) {
|
||||
auto indicePtr = static_cast<const uint32_t*>(objPt.indices.data());
|
||||
for (uint32_t i = 0; i < objPt.GetIndicesCount(); i += 3) {
|
||||
// Misscontructed indices tree failsafe
|
||||
if (i+2 > objPt.GetIndicesCount())
|
||||
break;
|
||||
|
||||
//TODO: Proceed with z-test: if z is lesser than previous z, draw the pixel and update z
|
||||
|
||||
// Simple clipping
|
||||
//TODO: implement complete Cohen-Sutherland algo or similar
|
||||
if (((projVertices + processedVerticesCnt)[indicePtr[i]]).z > 0 &&
|
||||
((projVertices + processedVerticesCnt)[indicePtr[i+1]]).z > 0 &&
|
||||
((projVertices + processedVerticesCnt)[indicePtr[i+2]]).z > 0) {
|
||||
M3D_VECTOR V1 = M3D_V4LoadF3(&(projVertices + processedVerticesCnt)[indicePtr[i]]);
|
||||
M3D_VECTOR V2 = M3D_V4LoadF3(&(projVertices + processedVerticesCnt)[indicePtr[i+1]]);
|
||||
M3D_VECTOR V3 = M3D_V4LoadF3(&(projVertices + processedVerticesCnt)[indicePtr[i+2]]);
|
||||
|
||||
V1 = M3D_V3TransformNDCToViewport(V1, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f);
|
||||
V2 = M3D_V3TransformNDCToViewport(V2, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f);
|
||||
V3 = M3D_V3TransformNDCToViewport(V3, 0.f, 0.f, mRTSize.x, mRTSize.y, 1.f, 100.f);
|
||||
|
||||
v_tri[0].position = sf::Vector2f(M3D_V4GetX(V1), M3D_V4GetY(V1));
|
||||
v_tri[0].color = oMesh.vertices[indicePtr[i]].color;
|
||||
v_tri[3] = v_tri[0];
|
||||
v_tri[1].position = sf::Vector2f(M3D_V4GetX(V2), M3D_V4GetY(V2));
|
||||
v_tri[1].color = oMesh.vertices[indicePtr[i+1]].color;
|
||||
v_tri[2].position = sf::Vector2f(M3D_V4GetX(V3), M3D_V4GetY(V3));
|
||||
v_tri[2].color = oMesh.vertices[indicePtr[i+2]].color;
|
||||
context.draw(v_tri, 4, sf::LineStrip, sRS);
|
||||
//context.draw(v_tri, 3, sf::Triangles, sRS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processedVerticesCnt += oMesh.GetVerticesCount();
|
||||
}
|
||||
}
|
@ -38,4 +38,6 @@ private:
|
||||
|
||||
std::vector<std::shared_ptr<WorldObject>> mRenderList; // List of elements to be rendered next frame
|
||||
|
||||
void UpdateInternalTestObjects();
|
||||
|
||||
};
|
@ -16,9 +16,9 @@ public:
|
||||
M3D_VECTOR GetPos() const { return M3D_V4LoadF3(&mPos); }
|
||||
M3D_F3 GetPos3f() const { return mPos; }
|
||||
M3D_MATRIX GetView() const { return M3D_V4LoadF4x4(&mViewMat); }
|
||||
M3D_F4X4 GetView4x4f() const { return mViewMat; }
|
||||
const M3D_F4X4& GetView4x4f() const { return mViewMat; }
|
||||
M3D_MATRIX GetProj() const { return M3D_V4LoadF4x4(&mProjMat); }
|
||||
M3D_F4X4 GetProj4x4f() const { return mProjMat; }
|
||||
const M3D_F4X4& GetProj4x4f() const { return mProjMat; }
|
||||
|
||||
void SetPosition(const float x, const float y, const float z) { mPos = M3D_F3(x, y, z); }
|
||||
void SetPosition(const M3D_F3 v) { mPos = v; }
|
||||
|
@ -596,6 +596,248 @@ constexpr M3D_F4X4 M3D_MIdentity4x4() {
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Collision enums and structures definition
|
||||
//
|
||||
|
||||
enum M3D_ContainmentType {
|
||||
DISJOINT = 0,
|
||||
INTERSECTS = 1,
|
||||
CONTAINS = 2
|
||||
};
|
||||
|
||||
enum M3D_PlaneIntersectionType {
|
||||
FRONT = 0,
|
||||
INTERSECTING = 1,
|
||||
BACK = 2
|
||||
};
|
||||
|
||||
struct M3D_BoundingBox; // AABB uhuh :3
|
||||
struct M3D_BoundingOrientedBox;
|
||||
struct M3D_BoundingFrustum;
|
||||
|
||||
struct M3D_BoundingSphere {
|
||||
M3D_F3 Center;
|
||||
float Radius;
|
||||
|
||||
M3D_BoundingSphere() noexcept : Center(0, 0, 0), Radius(1.f) {}
|
||||
|
||||
M3D_BoundingSphere(const M3D_BoundingSphere&) = default;
|
||||
M3D_BoundingSphere& operator=(const M3D_BoundingSphere&) = default;
|
||||
M3D_BoundingSphere(M3D_BoundingSphere&&) = default;
|
||||
M3D_BoundingSphere& operator=(M3D_BoundingSphere&&) = default;
|
||||
|
||||
constexpr M3D_BoundingSphere(const M3D_F3& center, float radius) noexcept : Center(center), Radius(radius) {}
|
||||
|
||||
|
||||
void Transform(M3D_BoundingSphere& Out, M3D_MATRIX M) const noexcept;
|
||||
void Transform(M3D_BoundingSphere& Out, float Scale, M3D_VECTOR Rotation, M3D_VECTOR Translation) const noexcept;
|
||||
|
||||
M3D_ContainmentType Contains(M3D_VECTOR Point) const noexcept;
|
||||
M3D_ContainmentType Contains(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingSphere& sh) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingBox& box) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingOrientedBox& box) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingFrustum& fr) const noexcept;
|
||||
|
||||
bool Intersects(const M3D_BoundingSphere& sh) const noexcept;
|
||||
bool Intersects(const M3D_BoundingBox& box) const noexcept;
|
||||
bool Intersects(const M3D_BoundingOrientedBox& box) const noexcept;
|
||||
bool Intersects(const M3D_BoundingFrustum& fr) const noexcept;
|
||||
bool Intersects(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2) const noexcept;
|
||||
M3D_PlaneIntersectionType Intersects(M3D_VECTOR Plane) const noexcept;
|
||||
bool Intersects(M3D_VECTOR Origin, M3D_VECTOR Direction, float& Dist) const noexcept;
|
||||
|
||||
M3D_ContainmentType ContainedBy(M3D_VECTOR Plane0, M3D_VECTOR Plane1, M3D_VECTOR Plane2,
|
||||
M3D_VECTOR& Plane3, M3D_VECTOR& Plane4, M3D_VECTOR& Plane5) const noexcept;
|
||||
|
||||
|
||||
static void CreateMerged(M3D_BoundingSphere& Out, const M3D_BoundingSphere& S1, const M3D_BoundingSphere& S2) noexcept;
|
||||
static void CreateFromBoundingBox(M3D_BoundingSphere& Out, const M3D_BoundingBox& box) noexcept;
|
||||
static void CreateFromBoundingBox(M3D_BoundingSphere& Out, const M3D_BoundingOrientedBox& box) noexcept;
|
||||
static void CreateFromPoints(M3D_BoundingSphere& Out, size_t Count, const M3D_F3* pPoints, size_t Stride) noexcept;
|
||||
|
||||
};
|
||||
|
||||
struct M3D_BoundingBox {
|
||||
static constexpr size_t CORNER_COUNT = 8;
|
||||
|
||||
M3D_F3 Center;
|
||||
M3D_F3 Extents;
|
||||
|
||||
M3D_BoundingBox() noexcept : Center(0, 0, 0), Extents(1.f, 1.f, 1.f) {}
|
||||
|
||||
M3D_BoundingBox(const M3D_BoundingBox&) = default;
|
||||
M3D_BoundingBox& operator=(const M3D_BoundingBox&) = default;
|
||||
M3D_BoundingBox(M3D_BoundingBox&&) = default;
|
||||
M3D_BoundingBox& operator=(M3D_BoundingBox&&) = default;
|
||||
|
||||
constexpr M3D_BoundingBox(const M3D_F3& center, const M3D_F3& extents) noexcept : Center(center), Extents(extents) {}
|
||||
|
||||
|
||||
void Transform(M3D_BoundingBox& Out, M3D_MATRIX M) const noexcept;
|
||||
void Transform(M3D_BoundingBox& Out, float Scale, M3D_VECTOR Rotation, M3D_VECTOR Translation) const noexcept;
|
||||
|
||||
void GetCorners(M3D_F3* Corners) const noexcept;
|
||||
|
||||
M3D_ContainmentType Contains(M3D_VECTOR Point) const noexcept;
|
||||
M3D_ContainmentType Contains(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingSphere& sh) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingBox& box) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingOrientedBox& box) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingFrustum& fr) const noexcept;
|
||||
|
||||
bool Intersects(const M3D_BoundingSphere& sh) const noexcept;
|
||||
bool Intersects(const M3D_BoundingBox& box) const noexcept;
|
||||
bool Intersects(const M3D_BoundingOrientedBox& box) const noexcept;
|
||||
bool Intersects(const M3D_BoundingFrustum& fr) const noexcept;
|
||||
bool Intersects(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2) const noexcept;
|
||||
M3D_PlaneIntersectionType Intersects(M3D_VECTOR Plane) const noexcept;
|
||||
bool Intersects(M3D_VECTOR Origin, M3D_VECTOR Direction, float& Dist) const noexcept;
|
||||
|
||||
M3D_ContainmentType ContainedBy(M3D_VECTOR Plane0, M3D_VECTOR Plane1, M3D_VECTOR Plane2,
|
||||
M3D_VECTOR& Plane3, M3D_VECTOR& Plane4, M3D_VECTOR& Plane5) const noexcept;
|
||||
|
||||
|
||||
static void CreateMerged(M3D_BoundingBox& Out, const M3D_BoundingBox& b1, const M3D_BoundingBox& b2) noexcept;
|
||||
static void CreateFromSphere(M3D_BoundingBox& Out, const M3D_BoundingSphere& sh) noexcept;
|
||||
static void CreateFromPoints(M3D_BoundingBox& Out, M3D_VECTOR pt1, M3D_VECTOR pt2) noexcept;
|
||||
static void CreateFromPoints(M3D_BoundingBox& Out, size_t Count, const M3D_F3* pPoints, size_t Stride) noexcept;
|
||||
};
|
||||
|
||||
struct M3D_BoundingOrientedBox {
|
||||
static constexpr size_t CORNER_COUNT = 8;
|
||||
|
||||
M3D_F3 Center;
|
||||
M3D_F3 Extents;
|
||||
M3D_F4 Orientation; // Unit quaternion representing rotation (box -> world).
|
||||
|
||||
M3D_BoundingOrientedBox() noexcept : Center(0, 0, 0), Extents(1.f, 1.f, 1.f), Orientation(0, 0, 0, 1.f) {}
|
||||
|
||||
M3D_BoundingOrientedBox(const M3D_BoundingOrientedBox&) = default;
|
||||
M3D_BoundingOrientedBox& operator=(const M3D_BoundingOrientedBox&) = default;
|
||||
M3D_BoundingOrientedBox(M3D_BoundingOrientedBox&&) = default;
|
||||
M3D_BoundingOrientedBox& operator=(M3D_BoundingOrientedBox&&) = default;
|
||||
|
||||
constexpr M3D_BoundingOrientedBox(const M3D_F3& center, const M3D_F3& extents, const M3D_F4& orientation) noexcept
|
||||
: Center(center), Extents(extents), Orientation(orientation) {}
|
||||
|
||||
|
||||
void Transform(M3D_BoundingOrientedBox& Out, M3D_MATRIX M) const noexcept;
|
||||
void Transform(M3D_BoundingOrientedBox& Out, float Scale, M3D_VECTOR Rotation, M3D_VECTOR Translation) const noexcept;
|
||||
|
||||
void GetCorners(M3D_F3* Corners) const noexcept;
|
||||
|
||||
M3D_ContainmentType Contains(M3D_VECTOR Point) const noexcept;
|
||||
M3D_ContainmentType Contains(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingSphere& sh) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingBox& box) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingOrientedBox& box) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingFrustum& fr) const noexcept;
|
||||
|
||||
bool Intersects(const M3D_BoundingSphere& sh) const noexcept;
|
||||
bool Intersects(const M3D_BoundingBox& box) const noexcept;
|
||||
bool Intersects(const M3D_BoundingOrientedBox& box) const noexcept;
|
||||
bool Intersects(const M3D_BoundingFrustum& fr) const noexcept;
|
||||
bool Intersects(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2) const noexcept;
|
||||
M3D_PlaneIntersectionType Intersects(M3D_VECTOR Plane) const noexcept;
|
||||
bool Intersects(M3D_VECTOR Origin, M3D_VECTOR Direction, float& Dist) const noexcept;
|
||||
|
||||
M3D_ContainmentType ContainedBy(M3D_VECTOR Plane0, M3D_VECTOR Plane1, M3D_VECTOR Plane2,
|
||||
M3D_VECTOR& Plane3, M3D_VECTOR& Plane4, M3D_VECTOR& Plane5) const noexcept;
|
||||
|
||||
|
||||
static void CreateFromBoundingBox(M3D_BoundingOrientedBox& Out, const M3D_BoundingBox& box) noexcept;
|
||||
static void CreateFromPoints(M3D_BoundingOrientedBox& Out, size_t Count, const M3D_F3* pPoints, size_t Stride) noexcept;
|
||||
};
|
||||
|
||||
struct M3D_BoundingFrustum {
|
||||
static constexpr size_t CORNER_COUNT = 8;
|
||||
|
||||
M3D_F3 Origin;
|
||||
M3D_F4 Orientation; // Quaternion representing rotation.
|
||||
|
||||
float RightSlope; // Positive X (X/Z)
|
||||
float LeftSlope; // Negative X
|
||||
float TopSlope; // Positive Y (Y/Z)
|
||||
float BottomSlope; // Negative Y
|
||||
float Near, Far; // Z of the near plane and far plane.
|
||||
|
||||
M3D_BoundingFrustum() noexcept :
|
||||
Origin(0, 0, 0), Orientation(0, 0, 0, 1.f), RightSlope(1.f), LeftSlope(-1.f),
|
||||
TopSlope(1.f), BottomSlope(-1.f), Near(0), Far(1.f) {}
|
||||
|
||||
M3D_BoundingFrustum(const M3D_BoundingFrustum&) = default;
|
||||
M3D_BoundingFrustum& operator=(const M3D_BoundingFrustum&) = default;
|
||||
M3D_BoundingFrustum(M3D_BoundingFrustum&&) = default;
|
||||
M3D_BoundingFrustum& operator=(M3D_BoundingFrustum&&) = default;
|
||||
|
||||
constexpr M3D_BoundingFrustum(const M3D_F3& origin, const M3D_F4& orientation,
|
||||
float rightSlope, float leftSlope, float topSlope, float bottomSlope,
|
||||
float nearPlane, float farPlane) noexcept
|
||||
: Origin(origin), Orientation(orientation),
|
||||
RightSlope(rightSlope), LeftSlope(leftSlope), TopSlope(topSlope), BottomSlope(bottomSlope),
|
||||
Near(nearPlane), Far(farPlane) {}
|
||||
M3D_BoundingFrustum(M3D_MATRIX Projection, bool rhcoords = false) noexcept;
|
||||
|
||||
|
||||
void Transform(M3D_BoundingFrustum& Out, M3D_MATRIX M) const noexcept;
|
||||
void Transform(M3D_BoundingFrustum& Out, float Scale, M3D_VECTOR Rotation, M3D_VECTOR Translation) const noexcept;
|
||||
|
||||
void GetCorners(M3D_F3* Corners) const noexcept;
|
||||
|
||||
M3D_ContainmentType Contains(M3D_VECTOR Point) const noexcept;
|
||||
M3D_ContainmentType Contains(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingSphere& sp) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingBox& box) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingOrientedBox& box) const noexcept;
|
||||
M3D_ContainmentType Contains(const M3D_BoundingFrustum& fr) const noexcept;
|
||||
|
||||
bool Intersects(const M3D_BoundingSphere& sh) const noexcept;
|
||||
bool Intersects(const M3D_BoundingBox& box) const noexcept;
|
||||
bool Intersects(const M3D_BoundingOrientedBox& box) const noexcept;
|
||||
bool Intersects(const M3D_BoundingFrustum& fr) const noexcept;
|
||||
|
||||
bool Intersects(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2) const noexcept;
|
||||
M3D_PlaneIntersectionType Intersects(M3D_VECTOR Plane) const noexcept;
|
||||
bool Intersects(M3D_VECTOR rayOrigin, M3D_VECTOR Direction, float& Dist) const noexcept;
|
||||
|
||||
M3D_ContainmentType ContainedBy(M3D_VECTOR Plane0, M3D_VECTOR Plane1, M3D_VECTOR Plane2,
|
||||
M3D_VECTOR& Plane3, M3D_VECTOR& Plane4, M3D_VECTOR& Plane5) const noexcept;
|
||||
|
||||
void GetPlanes(M3D_VECTOR* NearPlane, M3D_VECTOR* FarPlane, M3D_VECTOR* RightPlane,
|
||||
M3D_VECTOR* LeftPlane, M3D_VECTOR* TopPlane, M3D_VECTOR* BottomPlane) const noexcept;
|
||||
|
||||
|
||||
static void CreateFromMatrix(M3D_BoundingFrustum& Out, M3D_MATRIX Projection, bool rhcoords = false) noexcept;
|
||||
};
|
||||
|
||||
namespace M3D_TriangleTests {
|
||||
bool Intersects(M3D_VECTOR Origin, M3D_VECTOR Direction, M3D_VECTOR V0, M3D_VECTOR& V1, M3D_VECTOR& V2, float& Dist) noexcept;
|
||||
bool Intersects(M3D_VECTOR A0, M3D_VECTOR A1, M3D_VECTOR A2, M3D_VECTOR& B0, M3D_VECTOR& B1, M3D_VECTOR& B2) noexcept;
|
||||
M3D_PlaneIntersectionType Intersects(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2, M3D_VECTOR& Plane) noexcept;
|
||||
M3D_ContainmentType ContainedBy(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2,
|
||||
M3D_VECTOR& Plane0, M3D_VECTOR& Plane1, M3D_VECTOR& Plane2,
|
||||
M3D_VECTOR& Plane3, M3D_VECTOR& Plane4, M3D_VECTOR& Plane5) noexcept;
|
||||
|
||||
}
|
||||
|
||||
M3D_GCONST M3D_V4F32 M3D_BRayEpsilon = {{{1e-20f, 1e-20f, 1e-20f, 1e-20f}}};
|
||||
M3D_GCONST M3D_V4F32 M3D_BRayNegEpsilon = {{{-1e-20f, -1e-20f, -1e-20f, -1e-20f}}};
|
||||
M3D_GCONST M3D_V4F32 M3D_BFltMin = {{{-__FLT_MAX__, -__FLT_MAX__, -__FLT_MAX__, -__FLT_MAX__}}};
|
||||
M3D_GCONST M3D_V4F32 M3D_BFltMax = {{{__FLT_MAX__, __FLT_MAX__, __FLT_MAX__, __FLT_MAX__}}};
|
||||
M3D_GCONST M3D_V4F32 M3D_BBoxOffset[8] = {
|
||||
{{{-1.0f, -1.0f, 1.0f, 0.0f}}},
|
||||
{{{ 1.0f, -1.0f, 1.0f, 0.0f}}},
|
||||
{{{ 1.0f, 1.0f, 1.0f, 0.0f}}},
|
||||
{{{-1.0f, 1.0f, 1.0f, 0.0f}}},
|
||||
{{{-1.0f, -1.0f, -1.0f, 0.0f}}},
|
||||
{{{ 1.0f, -1.0f, -1.0f, 0.0f}}},
|
||||
{{{ 1.0f, 1.0f, -1.0f, 0.0f}}},
|
||||
{{{-1.0f, 1.0f, -1.0f, 0.0f}}},
|
||||
};
|
||||
|
||||
#include "3DMaths_vec.inl"
|
||||
#include "3DMaths_mat.inl"
|
||||
#include "3DMaths_bs.inl"
|
@ -10,3 +10,411 @@ namespace M3D_Internal {
|
||||
return vNormal;
|
||||
}
|
||||
}
|
||||
|
||||
inline void FastIntersectAxisAlignedBoxPlane(M3D_VECTOR Center, M3D_VECTOR Extents, M3D_VECTOR Plane, M3D_VECTOR& Outside, M3D_VECTOR& Inside) noexcept {
|
||||
// Compute the distance to the center of the box.
|
||||
M3D_VECTOR Dist = M3D_V4Dot(Center, Plane);
|
||||
|
||||
// Project the axes of the box onto the normal of the plane. Half the
|
||||
// length of the projection (sometime called the "radius") is equal to
|
||||
// h(u) * abs(n dot b(u))) + h(v) * abs(n dot b(v)) + h(w) * abs(n dot b(w))
|
||||
// where h(i) are extents of the box, n is the plane normal, and b(i) are the
|
||||
// axes of the box. In this case b(i) = [(1,0,0), (0,1,0), (0,0,1)].
|
||||
M3D_VECTOR Radius = M3D_V3Dot(Extents, M3D_V4Abs(Plane));
|
||||
|
||||
// Outside the plane?
|
||||
Outside = M3D_V4Greater(Dist, Radius);
|
||||
|
||||
// Fully inside the plane?
|
||||
Inside = M3D_V4Less(Dist, M3D_V4Negate(Radius));
|
||||
}
|
||||
|
||||
inline void FastIntersectTrianglePlane(M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2,
|
||||
M3D_VECTOR& Plane, M3D_VECTOR& Outside, M3D_VECTOR& Inside) noexcept {
|
||||
// Plane0
|
||||
M3D_VECTOR Dist0 = M3D_V4Dot(V0, Plane);
|
||||
M3D_VECTOR Dist1 = M3D_V4Dot(V1, Plane);
|
||||
M3D_VECTOR Dist2 = M3D_V4Dot(V2, Plane);
|
||||
|
||||
M3D_VECTOR MinDist = M3D_V4Min(Dist0, Dist1);
|
||||
MinDist = M3D_V4Min(MinDist, Dist2);
|
||||
|
||||
M3D_VECTOR MaxDist = M3D_V4Max(Dist0, Dist1);
|
||||
MaxDist = M3D_V4Max(MaxDist, Dist2);
|
||||
|
||||
M3D_VECTOR Zero = M3D_V4Zero();
|
||||
|
||||
// Outside the plane?
|
||||
Outside = M3D_V4Greater(MinDist, Zero);
|
||||
|
||||
// Fully inside the plane?
|
||||
Inside = M3D_V4Less(MaxDist, Zero);
|
||||
}
|
||||
|
||||
inline M3D_ContainmentType M3D_BoundingBox::ContainedBy(M3D_VECTOR Plane0, M3D_VECTOR Plane1, M3D_VECTOR Plane2,
|
||||
M3D_VECTOR& Plane3, M3D_VECTOR& Plane4, M3D_VECTOR& Plane5) const noexcept {
|
||||
// Load the box.
|
||||
M3D_VECTOR vCenter = M3D_V4LoadF3(&Center);
|
||||
M3D_VECTOR vExtents = M3D_V4LoadF3(&Extents);
|
||||
|
||||
// Set w of the center to one so we can dot4 with a plane.
|
||||
vCenter = M3D_V4SetW(vCenter, 1.0f);
|
||||
|
||||
M3D_VECTOR Outside, Inside;
|
||||
|
||||
// Test against each plane.
|
||||
FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane0, Outside, Inside);
|
||||
|
||||
M3D_VECTOR AnyOutside = Outside;
|
||||
M3D_VECTOR AllInside = Inside;
|
||||
|
||||
FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane1, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane2, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane3, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane4, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane5, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
// If the box is outside any plane it is outside.
|
||||
if (M3D_V4EqualInt(AnyOutside, M3D_V4TrueInt()))
|
||||
return DISJOINT;
|
||||
|
||||
// If the box is inside all planes it is inside.
|
||||
if (M3D_V4EqualInt(AllInside, M3D_V4TrueInt()))
|
||||
return CONTAINS;
|
||||
|
||||
// The box is not inside all planes or outside a plane, it may intersect.
|
||||
return INTERSECTS;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------------------------------------------------- */
|
||||
|
||||
inline void M3D_BoundingBox::CreateFromPoints(M3D_BoundingBox& Out, M3D_VECTOR pt1, M3D_VECTOR pt2) noexcept {
|
||||
M3D_VECTOR Min = M3D_V4Min(pt1, pt2);
|
||||
M3D_VECTOR Max = M3D_V4Max(pt1, pt2);
|
||||
|
||||
M3D_V4StoreF3(&Out.Center, M3D_V4Scale(M3D_V4Add(Min, Max), 0.5f));
|
||||
M3D_V4StoreF3(&Out.Extents, M3D_V4Scale(M3D_V4Subtract(Max, Min), 0.5f));
|
||||
}
|
||||
|
||||
inline void M3D_BoundingBox::CreateFromPoints(M3D_BoundingBox& Out, size_t Count, const M3D_F3* pPoints, size_t Stride) noexcept {
|
||||
// Find the minimum and maximum x, y, and z
|
||||
M3D_VECTOR vMin, vMax;
|
||||
|
||||
vMin = vMax = M3D_V4LoadF3(pPoints);
|
||||
|
||||
for (size_t i = 1; i < Count; ++i) {
|
||||
M3D_VECTOR Point = M3D_V4LoadF3(reinterpret_cast<const M3D_F3*>(reinterpret_cast<const uint8_t*>(pPoints) + i * Stride));
|
||||
|
||||
vMin = M3D_V4Min(vMin, Point);
|
||||
vMax = M3D_V4Max(vMax, Point);
|
||||
}
|
||||
|
||||
// Store center and extents.
|
||||
M3D_V4StoreF3(&Out.Center, M3D_V4Scale(M3D_V4Add(vMin, vMax), 0.5f));
|
||||
M3D_V4StoreF3(&Out.Extents, M3D_V4Scale(M3D_V4Subtract(vMax, vMin), 0.5f));
|
||||
}
|
||||
|
||||
inline void M3D_BoundingBox::Transform(M3D_BoundingBox& Out, M3D_MATRIX M) const noexcept {
|
||||
// Load center and extents.
|
||||
M3D_VECTOR vCenter = M3D_V4LoadF3(&Center);
|
||||
M3D_VECTOR vExtents = M3D_V4LoadF3(&Extents);
|
||||
|
||||
// Compute and transform the corners and find new min/max bounds.
|
||||
M3D_VECTOR Corner = M3D_V4MultiplyAdd(vExtents, M3D_BBoxOffset[0], vCenter);
|
||||
Corner = M3D_V3Transform(Corner, M);
|
||||
|
||||
M3D_VECTOR Min, Max;
|
||||
Min = Max = Corner;
|
||||
|
||||
for (size_t i = 1; i < CORNER_COUNT; ++i) {
|
||||
Corner = M3D_V4MultiplyAdd(vExtents, M3D_BBoxOffset[i], vCenter);
|
||||
Corner = M3D_V3Transform(Corner, M);
|
||||
|
||||
Min = M3D_V4Min(Min, Corner);
|
||||
Max = M3D_V4Max(Max, Corner);
|
||||
}
|
||||
|
||||
// Store center and extents.
|
||||
M3D_V4StoreF3(&Out.Center, M3D_V4Scale(M3D_V4Add(Min, Max), 0.5f));
|
||||
M3D_V4StoreF3(&Out.Extents, M3D_V4Scale(M3D_V4Subtract(Max, Min), 0.5f));
|
||||
}
|
||||
|
||||
inline void M3D_BoundingBox::GetCorners(M3D_F3* Corners) const noexcept {
|
||||
M3D_VECTOR vCenter = M3D_V4LoadF3(&Center);
|
||||
M3D_VECTOR vExtents = M3D_V4LoadF3(&Extents);
|
||||
|
||||
for (size_t i = 0; i < CORNER_COUNT; ++i) {
|
||||
M3D_VECTOR C = M3D_V4MultiplyAdd(vExtents, M3D_BBoxOffset[i], vCenter);
|
||||
M3D_V4StoreF3(&Corners[i], C);
|
||||
}
|
||||
}
|
||||
|
||||
inline M3D_BoundingFrustum::M3D_BoundingFrustum(M3D_MATRIX Projection, bool rhcoords) noexcept {
|
||||
CreateFromMatrix(*this, Projection, rhcoords);
|
||||
}
|
||||
|
||||
inline void M3D_BoundingFrustum::Transform(M3D_BoundingFrustum& Out, M3D_MATRIX M) const noexcept {
|
||||
// Load the frustum.
|
||||
M3D_VECTOR vOrigin = M3D_V4LoadF3(&Origin);
|
||||
M3D_VECTOR vOrientation = M3D_V4LoadF4(&Orientation);
|
||||
|
||||
// Composite the frustum rotation and the transform rotation
|
||||
M3D_MATRIX nM;
|
||||
nM.rows[0] = M3D_V3Normalize(M.rows[0]);
|
||||
nM.rows[1] = M3D_V3Normalize(M.rows[1]);
|
||||
nM.rows[2] = M3D_V3Normalize(M.rows[2]);
|
||||
nM.rows[3] = M3D_MIdentityR3;
|
||||
M3D_VECTOR Rotation = M3D_QRotationMatrix(nM);
|
||||
vOrientation = M3D_QMultiply(vOrientation, Rotation);
|
||||
|
||||
// Transform the center.
|
||||
vOrigin = M3D_V3Transform(vOrigin, M);
|
||||
|
||||
// Store the frustum.
|
||||
M3D_V4StoreF3(&Out.Origin, vOrigin);
|
||||
M3D_V4StoreF4(&Out.Orientation, vOrientation);
|
||||
|
||||
// Scale the near and far distances (the slopes remain the same).
|
||||
M3D_VECTOR dX = M3D_V3Dot(M.rows[0], M.rows[0]);
|
||||
M3D_VECTOR dY = M3D_V3Dot(M.rows[1], M.rows[1]);
|
||||
M3D_VECTOR dZ = M3D_V3Dot(M.rows[2], M.rows[2]);
|
||||
|
||||
M3D_VECTOR d = M3D_V4Max(dX, M3D_V4Max(dY, dZ));
|
||||
float Scale = sqrtf(M3D_V4GetX(d));
|
||||
|
||||
Out.Near = Near * Scale;
|
||||
Out.Far = Far * Scale;
|
||||
|
||||
// Copy the slopes.
|
||||
Out.RightSlope = RightSlope;
|
||||
Out.LeftSlope = LeftSlope;
|
||||
Out.TopSlope = TopSlope;
|
||||
Out.BottomSlope = BottomSlope;
|
||||
}
|
||||
|
||||
inline void M3D_BoundingFrustum::GetCorners(M3D_F3* Corners) const noexcept {
|
||||
// Load origin and orientation of the frustum.
|
||||
M3D_VECTOR vOrigin = M3D_V4LoadF3(&Origin);
|
||||
M3D_VECTOR vOrientation = M3D_V4LoadF4(&Orientation);
|
||||
|
||||
// Build the corners of the frustum.
|
||||
M3D_VECTOR vRightTop = M3D_V4Set(RightSlope, TopSlope, 1.0f, 0.0f);
|
||||
M3D_VECTOR vRightBottom = M3D_V4Set(RightSlope, BottomSlope, 1.0f, 0.0f);
|
||||
M3D_VECTOR vLeftTop = M3D_V4Set(LeftSlope, TopSlope, 1.0f, 0.0f);
|
||||
M3D_VECTOR vLeftBottom = M3D_V4Set(LeftSlope, BottomSlope, 1.0f, 0.0f);
|
||||
M3D_VECTOR vNear = M3D_V4ReplicatePtr(&Near);
|
||||
M3D_VECTOR vFar = M3D_V4ReplicatePtr(&Far);
|
||||
|
||||
// Returns 8 corners position of bounding frustum.
|
||||
// Near Far
|
||||
// 0----1 4----5
|
||||
// | | | |
|
||||
// | | | |
|
||||
// 3----2 7----6
|
||||
|
||||
M3D_VECTOR vCorners[CORNER_COUNT];
|
||||
vCorners[0] = M3D_V4Multiply(vLeftTop, vNear);
|
||||
vCorners[1] = M3D_V4Multiply(vRightTop, vNear);
|
||||
vCorners[2] = M3D_V4Multiply(vRightBottom, vNear);
|
||||
vCorners[3] = M3D_V4Multiply(vLeftBottom, vNear);
|
||||
vCorners[4] = M3D_V4Multiply(vLeftTop, vFar);
|
||||
vCorners[5] = M3D_V4Multiply(vRightTop, vFar);
|
||||
vCorners[6] = M3D_V4Multiply(vRightBottom, vFar);
|
||||
vCorners[7] = M3D_V4Multiply(vLeftBottom, vFar);
|
||||
|
||||
for (size_t i = 0; i < CORNER_COUNT; ++i) {
|
||||
M3D_VECTOR C = M3D_V4Add(M3D_V3Rotate(vCorners[i], vOrientation), vOrigin);
|
||||
M3D_V4StoreF3(&Corners[i], C);
|
||||
}
|
||||
}
|
||||
|
||||
inline M3D_ContainmentType M3D_BoundingFrustum::Contains(const M3D_BoundingBox& box) const noexcept {
|
||||
// Load origin and orientation of the frustum.
|
||||
M3D_VECTOR vOrigin = M3D_V4LoadF3(&Origin);
|
||||
M3D_VECTOR vOrientation = M3D_V4LoadF4(&Orientation);
|
||||
|
||||
// Create 6 planes (do it inline to encourage use of registers)
|
||||
M3D_VECTOR NearPlane = M3D_V4Set(0.0f, 0.0f, -1.0f, Near);
|
||||
NearPlane = M3D_Internal::M3D_PTransform(NearPlane, vOrientation, vOrigin);
|
||||
NearPlane = M3D_V3Normalize(NearPlane);
|
||||
|
||||
M3D_VECTOR FarPlane = M3D_V4Set(0.0f, 0.0f, 1.0f, -Far);
|
||||
FarPlane = M3D_Internal::M3D_PTransform(FarPlane, vOrientation, vOrigin);
|
||||
FarPlane = M3D_V3Normalize(FarPlane);
|
||||
|
||||
M3D_VECTOR RightPlane = M3D_V4Set(1.0f, 0.0f, -RightSlope, 0.0f);
|
||||
RightPlane = M3D_Internal::M3D_PTransform(RightPlane, vOrientation, vOrigin);
|
||||
RightPlane = M3D_V3Normalize(RightPlane);
|
||||
|
||||
M3D_VECTOR LeftPlane = M3D_V4Set(-1.0f, 0.0f, LeftSlope, 0.0f);
|
||||
LeftPlane = M3D_Internal::M3D_PTransform(LeftPlane, vOrientation, vOrigin);
|
||||
LeftPlane = M3D_V3Normalize(LeftPlane);
|
||||
|
||||
M3D_VECTOR TopPlane = M3D_V4Set(0.0f, 1.0f, -TopSlope, 0.0f);
|
||||
TopPlane = M3D_Internal::M3D_PTransform(TopPlane, vOrientation, vOrigin);
|
||||
TopPlane = M3D_V3Normalize(TopPlane);
|
||||
|
||||
M3D_VECTOR BottomPlane = M3D_V4Set(0.0f, -1.0f, BottomSlope, 0.0f);
|
||||
BottomPlane = M3D_Internal::M3D_PTransform(BottomPlane, vOrientation, vOrigin);
|
||||
BottomPlane = M3D_V3Normalize(BottomPlane);
|
||||
|
||||
return box.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane);
|
||||
}
|
||||
|
||||
inline void M3D_BoundingFrustum::GetPlanes(M3D_VECTOR* NearPlane, M3D_VECTOR* FarPlane, M3D_VECTOR* RightPlane,
|
||||
M3D_VECTOR* LeftPlane, M3D_VECTOR* TopPlane, M3D_VECTOR* BottomPlane) const noexcept {
|
||||
// Load origin and orientation of the frustum.
|
||||
M3D_VECTOR vOrigin = M3D_V4LoadF3(&Origin);
|
||||
M3D_VECTOR vOrientation = M3D_V4LoadF4(&Orientation);
|
||||
|
||||
if (NearPlane) {
|
||||
M3D_VECTOR vNearPlane = M3D_V4Set(0.0f, 0.0f, -1.0f, Near);
|
||||
vNearPlane = M3D_Internal::M3D_PTransform(vNearPlane, vOrientation, vOrigin);
|
||||
*NearPlane = M3D_V3Normalize(vNearPlane);
|
||||
}
|
||||
|
||||
if (FarPlane) {
|
||||
M3D_VECTOR vFarPlane = M3D_V4Set(0.0f, 0.0f, 1.0f, -Far);
|
||||
vFarPlane = M3D_Internal::M3D_PTransform(vFarPlane, vOrientation, vOrigin);
|
||||
*FarPlane = M3D_V3Normalize(vFarPlane);
|
||||
}
|
||||
|
||||
if (RightPlane) {
|
||||
M3D_VECTOR vRightPlane = M3D_V4Set(1.0f, 0.0f, -RightSlope, 0.0f);
|
||||
vRightPlane = M3D_Internal::M3D_PTransform(vRightPlane, vOrientation, vOrigin);
|
||||
*RightPlane = M3D_V3Normalize(vRightPlane);
|
||||
}
|
||||
|
||||
if (LeftPlane) {
|
||||
M3D_VECTOR vLeftPlane = M3D_V4Set(-1.0f, 0.0f, LeftSlope, 0.0f);
|
||||
vLeftPlane = M3D_Internal::M3D_PTransform(vLeftPlane, vOrientation, vOrigin);
|
||||
*LeftPlane = M3D_V3Normalize(vLeftPlane);
|
||||
}
|
||||
|
||||
if (TopPlane) {
|
||||
M3D_VECTOR vTopPlane = M3D_V4Set(0.0f, 1.0f, -TopSlope, 0.0f);
|
||||
vTopPlane = M3D_Internal::M3D_PTransform(vTopPlane, vOrientation, vOrigin);
|
||||
*TopPlane = M3D_V3Normalize(vTopPlane);
|
||||
}
|
||||
|
||||
if (BottomPlane) {
|
||||
M3D_VECTOR vBottomPlane = M3D_V4Set(0.0f, -1.0f, BottomSlope, 0.0f);
|
||||
vBottomPlane = M3D_Internal::M3D_PTransform(vBottomPlane, vOrientation, vOrigin);
|
||||
*BottomPlane = M3D_V3Normalize(vBottomPlane);
|
||||
}
|
||||
}
|
||||
|
||||
inline void M3D_BoundingFrustum::CreateFromMatrix(M3D_BoundingFrustum& Out, M3D_MATRIX Projection, bool rhcoords) noexcept {
|
||||
// Corners of the projection frustum in NDC space.
|
||||
static M3D_V4F32 NDCPoints[6] = {
|
||||
{{{1.0f, 0.0f, 1.0f, 1.0f}}}, // right (at far plane)
|
||||
{{{-1.0f, 0.0f, 1.0f, 1.0f}}}, // left
|
||||
{{{0.0f, 1.0f, 1.0f, 1.0f}}}, // top
|
||||
{{{0.0f, -1.0f, 1.0f, 1.0f}}}, // bottom
|
||||
|
||||
{{{0.0f, 0.0f, 0.0f, 1.0f}}}, // near
|
||||
{{{0.0f, 0.0f, 1.0f, 1.0f}}} // far
|
||||
};
|
||||
|
||||
M3D_MATRIX matInverse = M3D_MInverse(Projection);
|
||||
|
||||
// Compute the frustum corners in world space.
|
||||
M3D_VECTOR Points[6];
|
||||
|
||||
for (size_t i = 0; i < 6; ++i) {
|
||||
// Transform point.
|
||||
Points[i] = M3D_V4Transform(NDCPoints[i], matInverse);
|
||||
}
|
||||
|
||||
Out.Origin = M3D_F3(0.0f, 0.0f, 0.0f);
|
||||
Out.Orientation = M3D_F4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Compute the slopes.
|
||||
Points[0] = M3D_V4Multiply(Points[0], M3D_V4Reciprocal(M3D_V4SplatZ(Points[0])));
|
||||
Points[1] = M3D_V4Multiply(Points[1], M3D_V4Reciprocal(M3D_V4SplatZ(Points[1])));
|
||||
Points[2] = M3D_V4Multiply(Points[2], M3D_V4Reciprocal(M3D_V4SplatZ(Points[2])));
|
||||
Points[3] = M3D_V4Multiply(Points[3], M3D_V4Reciprocal(M3D_V4SplatZ(Points[3])));
|
||||
|
||||
Out.RightSlope = M3D_V4GetX(Points[0]);
|
||||
Out.LeftSlope = M3D_V4GetX(Points[1]);
|
||||
Out.TopSlope = M3D_V4GetY(Points[2]);
|
||||
Out.BottomSlope = M3D_V4GetY(Points[3]);
|
||||
|
||||
// Compute near and far.
|
||||
Points[4] = M3D_V4Multiply(Points[4], M3D_V4Reciprocal(M3D_V4SplatW(Points[4])));
|
||||
Points[5] = M3D_V4Multiply(Points[5], M3D_V4Reciprocal(M3D_V4SplatW(Points[5])));
|
||||
|
||||
if (rhcoords) {
|
||||
Out.Near = M3D_V4GetZ(Points[5]);
|
||||
Out.Far = M3D_V4GetZ(Points[4]);
|
||||
} else {
|
||||
Out.Near = M3D_V4GetZ(Points[4]);
|
||||
Out.Far = M3D_V4GetZ(Points[5]);
|
||||
}
|
||||
}
|
||||
|
||||
namespace M3D_TriangleTests {
|
||||
inline M3D_ContainmentType ContainedBy(
|
||||
M3D_VECTOR V0, M3D_VECTOR V1, M3D_VECTOR V2,
|
||||
M3D_VECTOR& Plane0,
|
||||
M3D_VECTOR& Plane1, M3D_VECTOR& Plane2,
|
||||
M3D_VECTOR& Plane3, M3D_VECTOR& Plane4, M3D_VECTOR& Plane5) noexcept {
|
||||
// Set w of the points to one so we can dot4 with a plane.
|
||||
M3D_VECTOR TV0 = M3D_V4SetW(V0, 1.0f);
|
||||
M3D_VECTOR TV1 = M3D_V4SetW(V1, 1.0f);
|
||||
M3D_VECTOR TV2 = M3D_V4SetW(V2, 1.0f);
|
||||
|
||||
M3D_VECTOR Outside, Inside;
|
||||
|
||||
// Test against each plane.
|
||||
FastIntersectTrianglePlane(TV0, TV1, TV2, Plane0, Outside, Inside);
|
||||
|
||||
M3D_VECTOR AnyOutside = Outside;
|
||||
M3D_VECTOR AllInside = Inside;
|
||||
|
||||
FastIntersectTrianglePlane(TV0, TV1, TV2, Plane1, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
FastIntersectTrianglePlane(TV0, TV1, TV2, Plane2, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
FastIntersectTrianglePlane(TV0, TV1, TV2, Plane3, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
FastIntersectTrianglePlane(TV0, TV1, TV2, Plane4, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
FastIntersectTrianglePlane(TV0, TV1, TV2, Plane5, Outside, Inside);
|
||||
AnyOutside = M3D_V4OrInt(AnyOutside, Outside);
|
||||
AllInside = M3D_V4AndInt(AllInside, Inside);
|
||||
|
||||
// If the triangle is outside any plane it is outside.
|
||||
if (M3D_V4EqualInt(AnyOutside, M3D_V4TrueInt()))
|
||||
return DISJOINT;
|
||||
|
||||
// If the triangle is inside all planes it is inside.
|
||||
if (M3D_V4EqualInt(AllInside, M3D_V4TrueInt()))
|
||||
return CONTAINS;
|
||||
|
||||
// The triangle is not inside all planes or outside a plane, it may intersect.
|
||||
return INTERSECTS;
|
||||
}
|
||||
}
|
@ -31,4 +31,6 @@ ObjectDbgCube::ObjectDbgCube() {
|
||||
MHELPER_INDICES_TRI_ADD(basePart.indices, 0, 2, 3);
|
||||
MHELPER_INDICES_TRI_ADD(basePart.indices, 4, 0, 1);
|
||||
mMesh.parts.push_back(basePart);
|
||||
|
||||
UpdateAABBFromMesh();
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
class WorldObject {
|
||||
public:
|
||||
virtual const Mesh& GetObjectMesh() const = 0;
|
||||
virtual const size_t GetObjectVerticesCount() const = 0;
|
||||
const M3D_MATRIX GetTransform() noexcept {
|
||||
M3D_MATRIX M = M3D_MIdentity();
|
||||
M *= M3D_TransformMatrixScale(M3D_V4LoadF3(&scale));
|
||||
@ -19,6 +20,8 @@ public:
|
||||
return out;
|
||||
}
|
||||
|
||||
const M3D_BoundingBox& GetAABB() const noexcept { return aabb; }
|
||||
|
||||
void SetPosition(M3D_F3& _pos) noexcept { pos = _pos; }
|
||||
void SetPosition(float _x, float _y, float _z) noexcept { pos = M3D_F3(_x, _y, _z); }
|
||||
void SetRotation(M3D_F3& _rot) noexcept { rot = _rot; }
|
||||
@ -30,7 +33,8 @@ public:
|
||||
protected:
|
||||
WorldObject() = default;
|
||||
|
||||
private:
|
||||
M3D_BoundingBox aabb;
|
||||
|
||||
M3D_F3 scale = M3D_F3(1.0f, 1.0f, 1.0f);
|
||||
M3D_F3 rot = M3D_F3(0.0f, 0.0f, 0.0f);
|
||||
M3D_F3 pos = M3D_F3(0.0f, 0.0f, 0.0f);
|
||||
@ -43,8 +47,12 @@ public:
|
||||
virtual ~WorldObjectAbstract() = 0;
|
||||
|
||||
const Mesh& GetObjectMesh() const noexcept override { return mMesh; }
|
||||
const size_t GetObjectVerticesCount() const noexcept override { return mMesh.GetVerticesCount(); }
|
||||
|
||||
void LoadMeshFromObjFile(std::string file);
|
||||
void UpdateAABBFromMesh() noexcept {
|
||||
M3D_BoundingBox::CreateFromPoints(aabb, GetObjectVerticesCount(), reinterpret_cast<const M3D_F3*>(GetObjectMesh().vertices.data()), sizeof(Vertex));
|
||||
}
|
||||
|
||||
protected:
|
||||
inline static Mesh mMesh;
|
||||
|
@ -61,4 +61,7 @@ void WorldObjectAbstract<D>::LoadMeshFromObjFile(std::string file) {
|
||||
|
||||
mMesh.parts.push_back(subpart);
|
||||
}
|
||||
|
||||
// Refresh AABB bounds
|
||||
UpdateAABBFromMesh();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user