mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Fixed issue with far distance of cascades being underestimated, especially first cascade
This commit is contained in:
parent
0b6dcb2717
commit
c0ca7a129d
5 changed files with 168 additions and 39 deletions
|
@ -53,6 +53,41 @@ const glm::mat4& LightStage::Shadow::Cascade::getProjection() const {
|
||||||
return _frustum->getProjection();
|
return _frustum->getProjection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float LightStage::Shadow::Cascade::computeFarDistance(const ViewFrustum& viewFrustum, const Transform& shadowViewInverse,
|
||||||
|
float left, float right, float bottom, float top, float viewMaxShadowDistance) const {
|
||||||
|
// Far distance should be extended to the intersection of the infinitely extruded shadow frustum
|
||||||
|
// with the view frustum side planes. To do so, we generate 10 triangles in shadow space which are the result of
|
||||||
|
// tesselating the side and far faces of the view frustum and clip them with the 4 side planes of the
|
||||||
|
// shadow frustum. The resulting clipped triangle vertices with the farthest Z gives the desired
|
||||||
|
// shadow frustum far distance.
|
||||||
|
std::array<Triangle, 10> viewFrustumTriangles;
|
||||||
|
Plane shadowClipPlanes[4] = {
|
||||||
|
Plane(glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, top, 0.0f)),
|
||||||
|
Plane(glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, bottom, 0.0f)),
|
||||||
|
Plane(glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(left, 0.0f, 0.0f)),
|
||||||
|
Plane(glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(right, 0.0f, 0.0f))
|
||||||
|
};
|
||||||
|
|
||||||
|
viewFrustum.tesselateSidesAndFar(shadowViewInverse, viewFrustumTriangles.data(), viewMaxShadowDistance);
|
||||||
|
|
||||||
|
static const int MAX_TRIANGLE_COUNT = 16;
|
||||||
|
auto far = 0.0f;
|
||||||
|
|
||||||
|
for (auto& triangle : viewFrustumTriangles) {
|
||||||
|
Triangle clippedTriangles[MAX_TRIANGLE_COUNT];
|
||||||
|
auto clippedTriangleCount = clipTriangleWithPlanes(triangle, shadowClipPlanes, 4, clippedTriangles, MAX_TRIANGLE_COUNT);
|
||||||
|
|
||||||
|
for (auto i = 0; i < clippedTriangleCount; i++) {
|
||||||
|
const auto& clippedTriangle = clippedTriangles[i];
|
||||||
|
far = glm::max(far, -clippedTriangle.v0.z);
|
||||||
|
far = glm::max(far, -clippedTriangle.v1.z);
|
||||||
|
far = glm::max(far, -clippedTriangle.v2.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return far;
|
||||||
|
}
|
||||||
|
|
||||||
LightStage::Shadow::Shadow(model::LightPointer light, unsigned int cascadeCount) : _light{ light } {
|
LightStage::Shadow::Shadow(model::LightPointer light, unsigned int cascadeCount) : _light{ light } {
|
||||||
cascadeCount = std::min(cascadeCount, (unsigned int)SHADOW_CASCADE_MAX_COUNT);
|
cascadeCount = std::min(cascadeCount, (unsigned int)SHADOW_CASCADE_MAX_COUNT);
|
||||||
Schema schema;
|
Schema schema;
|
||||||
|
@ -62,11 +97,12 @@ LightStage::Shadow::Shadow(model::LightPointer light, unsigned int cascadeCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightStage::Shadow::setKeylightFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum,
|
void LightStage::Shadow::setKeylightFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum,
|
||||||
float viewMinShadowDistance, float viewMaxShadowDistance, float viewOverlapDistance,
|
float viewMinCascadeShadowDistance, float viewMaxCascadeShadowDistance,
|
||||||
|
float viewCascadeOverlapDistance, float viewMaxShadowDistance,
|
||||||
float nearDepth, float farDepth) {
|
float nearDepth, float farDepth) {
|
||||||
assert(viewMinShadowDistance < viewMaxShadowDistance);
|
assert(viewMinCascadeShadowDistance < viewMaxCascadeShadowDistance);
|
||||||
assert(nearDepth < farDepth);
|
assert(nearDepth < farDepth);
|
||||||
assert(viewOverlapDistance > 0.0f);
|
assert(viewCascadeOverlapDistance > 0.0f);
|
||||||
assert(cascadeIndex < _cascades.size());
|
assert(cascadeIndex < _cascades.size());
|
||||||
|
|
||||||
// Orient the keylight frustum
|
// Orient the keylight frustum
|
||||||
|
@ -89,17 +125,17 @@ void LightStage::Shadow::setKeylightFrustum(unsigned int cascadeIndex, const Vie
|
||||||
// Position the keylight frustum
|
// Position the keylight frustum
|
||||||
cascade._frustum->setPosition(viewFrustum.getPosition() - (nearDepth + farDepth)*direction);
|
cascade._frustum->setPosition(viewFrustum.getPosition() - (nearDepth + farDepth)*direction);
|
||||||
|
|
||||||
const Transform view{ cascade._frustum->getView()};
|
const Transform shadowView{ cascade._frustum->getView()};
|
||||||
const Transform viewInverse{ view.getInverseMatrix() };
|
const Transform shadowViewInverse{ shadowView.getInverseMatrix() };
|
||||||
|
|
||||||
auto nearCorners = viewFrustum.getCorners(viewMinShadowDistance);
|
auto nearCorners = viewFrustum.getCorners(viewMinCascadeShadowDistance);
|
||||||
auto farCorners = viewFrustum.getCorners(viewMaxShadowDistance);
|
auto farCorners = viewFrustum.getCorners(viewMaxCascadeShadowDistance);
|
||||||
|
|
||||||
vec3 min{ viewInverse.transform(nearCorners.bottomLeft) };
|
vec3 min{ shadowViewInverse.transform(nearCorners.bottomLeft) };
|
||||||
vec3 max{ min };
|
vec3 max{ min };
|
||||||
// Expand keylight frustum to fit view frustum
|
// Expand keylight frustum to fit view frustum
|
||||||
auto fitFrustum = [&min, &max, &viewInverse](const vec3& viewCorner) {
|
auto fitFrustum = [&min, &max, &shadowViewInverse](const vec3& viewCorner) {
|
||||||
const auto corner = viewInverse.transform(viewCorner);
|
const auto corner = shadowViewInverse.transform(viewCorner);
|
||||||
|
|
||||||
min.x = glm::min(min.x, corner.x);
|
min.x = glm::min(min.x, corner.x);
|
||||||
min.y = glm::min(min.y, corner.y);
|
min.y = glm::min(min.y, corner.y);
|
||||||
|
@ -116,13 +152,11 @@ void LightStage::Shadow::setKeylightFrustum(unsigned int cascadeIndex, const Vie
|
||||||
fitFrustum(farCorners.bottomRight);
|
fitFrustum(farCorners.bottomRight);
|
||||||
fitFrustum(farCorners.topLeft);
|
fitFrustum(farCorners.topLeft);
|
||||||
fitFrustum(farCorners.topRight);
|
fitFrustum(farCorners.topRight);
|
||||||
|
|
||||||
// TODO: Far distance should be extended to the intersection of the exteruded shadow frustum far plane
|
|
||||||
// with the view frustum.
|
|
||||||
|
|
||||||
// Re-adjust near shadow distance
|
// Re-adjust near shadow distance
|
||||||
auto near = glm::min(-max.z, nearDepth);
|
auto near = glm::min(-max.z, nearDepth);
|
||||||
auto far = -min.z;
|
auto far = cascade.computeFarDistance(viewFrustum, shadowViewInverse, min.x, max.x, min.y, max.y, viewMaxShadowDistance);
|
||||||
|
|
||||||
glm::mat4 ortho = glm::ortho<float>(min.x, max.x, min.y, max.y, near, far);
|
glm::mat4 ortho = glm::ortho<float>(min.x, max.x, min.y, max.y, near, far);
|
||||||
cascade._frustum->setProjection(ortho);
|
cascade._frustum->setProjection(ortho);
|
||||||
|
|
||||||
|
@ -132,10 +166,10 @@ void LightStage::Shadow::setKeylightFrustum(unsigned int cascadeIndex, const Vie
|
||||||
// Update the buffer
|
// Update the buffer
|
||||||
auto& schema = _schemaBuffer.edit<Schema>();
|
auto& schema = _schemaBuffer.edit<Schema>();
|
||||||
if (cascadeIndex == getCascadeCount() - 1) {
|
if (cascadeIndex == getCascadeCount() - 1) {
|
||||||
schema.maxDistance = viewMaxShadowDistance;
|
schema.maxDistance = viewMaxCascadeShadowDistance;
|
||||||
schema.invFalloffDistance = 1.0f / viewOverlapDistance;
|
schema.invFalloffDistance = 1.0f / viewCascadeOverlapDistance;
|
||||||
}
|
}
|
||||||
schema.cascades[cascadeIndex].reprojection = _biasMatrix * ortho * viewInverse.getMatrix();
|
schema.cascades[cascadeIndex].reprojection = _biasMatrix * ortho * shadowViewInverse.getMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightStage::Shadow::setFrustum(unsigned int cascadeIndex, const ViewFrustum& shadowFrustum) {
|
void LightStage::Shadow::setFrustum(unsigned int cascadeIndex, const ViewFrustum& shadowFrustum) {
|
||||||
|
|
|
@ -65,12 +65,16 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::shared_ptr<ViewFrustum> _frustum;
|
std::shared_ptr<ViewFrustum> _frustum;
|
||||||
|
|
||||||
|
float computeFarDistance(const ViewFrustum& viewFrustum, const Transform& shadowViewInverse,
|
||||||
|
float left, float right, float bottom, float top, float viewMaxShadowDistance) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
Shadow(model::LightPointer light, unsigned int cascadeCount = 1);
|
Shadow(model::LightPointer light, unsigned int cascadeCount = 1);
|
||||||
|
|
||||||
void setKeylightFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum,
|
void setKeylightFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum,
|
||||||
float viewMinShadowDistance, float viewMaxShadowDistance, float viewOverlapDistance,
|
float viewMinCascadeShadowDistance, float viewMaxCascadeShadowDistance,
|
||||||
|
float viewCascadeOverlapDistance, float viewMaxShadowDistance,
|
||||||
float nearDepth = 1.0f, float farDepth = 1000.0f);
|
float nearDepth = 1.0f, float farDepth = 1000.0f);
|
||||||
void setFrustum(unsigned int cascadeIndex, const ViewFrustum& shadowFrustum);
|
void setFrustum(unsigned int cascadeIndex, const ViewFrustum& shadowFrustum);
|
||||||
|
|
||||||
|
|
|
@ -89,24 +89,7 @@ static void adjustNearFar(const AABox& inShapeBounds, ViewFrustum& shadowFrustum
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
sceneBoundVertices[i] = shadowViewInverse.transform(inShapeBounds.getVertex(static_cast<BoxVertex>(i)));
|
sceneBoundVertices[i] = shadowViewInverse.transform(inShapeBounds.getVertex(static_cast<BoxVertex>(i)));
|
||||||
}
|
}
|
||||||
// This indirection array is just a protection in case the ViewFrustum::PlaneIndex enum
|
shadowFrustum.getUniformlyTransformedSidePlanes(shadowViewInverse, shadowClipPlanes);
|
||||||
// changes order especially as we don't need to test the NEAR and FAR planes.
|
|
||||||
static const ViewFrustum::PlaneIndex planeIndices[4] = {
|
|
||||||
ViewFrustum::TOP_PLANE,
|
|
||||||
ViewFrustum::BOTTOM_PLANE,
|
|
||||||
ViewFrustum::LEFT_PLANE,
|
|
||||||
ViewFrustum::RIGHT_PLANE
|
|
||||||
};
|
|
||||||
// Same goes for the shadow frustum planes.
|
|
||||||
for (i = 0; i < 4; i++) {
|
|
||||||
const auto& worldPlane = shadowFrustum.getPlanes()[planeIndices[i]];
|
|
||||||
// We assume the transform doesn't have a non uniform scale component to apply the
|
|
||||||
// transform to the normal without using the correct transpose of inverse, which should be the
|
|
||||||
// case for a view matrix.
|
|
||||||
auto planeNormal = shadowViewInverse.transformDirection(worldPlane.getNormal());
|
|
||||||
auto planePoint = shadowViewInverse.transform(worldPlane.getPoint());
|
|
||||||
shadowClipPlanes[i].setNormalAndPoint(planeNormal, planePoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
float near = std::numeric_limits<float>::max();
|
float near = std::numeric_limits<float>::max();
|
||||||
float far = 0.0f;
|
float far = 0.0f;
|
||||||
|
@ -278,7 +261,8 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
||||||
minCascadeDistance = std::max(minCascadeDistance, nearClip);
|
minCascadeDistance = std::max(minCascadeDistance, nearClip);
|
||||||
}
|
}
|
||||||
maxCascadeDistance = std::min(maxCascadeDistance, farClip);
|
maxCascadeDistance = std::min(maxCascadeDistance, farClip);
|
||||||
globalShadow->setKeylightFrustum(_cascadeIndex, args->getViewFrustum(), minCascadeDistance, maxCascadeDistance, shadowOverlapDistance, SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR);
|
globalShadow->setKeylightFrustum(_cascadeIndex, args->getViewFrustum(), minCascadeDistance, maxCascadeDistance,
|
||||||
|
shadowOverlapDistance, HIGH_CASCADE_MAX_DISTANCE, SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR);
|
||||||
|
|
||||||
// Set the keylight render args
|
// Set the keylight render args
|
||||||
args->pushViewFrustum(*(globalShadow->getCascade(_cascadeIndex).getFrustum()));
|
args->pushViewFrustum(*(globalShadow->getCascade(_cascadeIndex).getFrustum()));
|
||||||
|
|
|
@ -691,7 +691,7 @@ void ViewFrustum::getFurthestPointFromCamera(const AACube& box, glm::vec3& furth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) const {
|
const ViewFrustum::Corners ViewFrustum::getCorners(const float depth) const {
|
||||||
glm::vec3 normal = glm::normalize(_direction);
|
glm::vec3 normal = glm::normalize(_direction);
|
||||||
|
|
||||||
auto getCorner = [&](enum::BoxVertex nearCorner, enum::BoxVertex farCorner) {
|
auto getCorner = [&](enum::BoxVertex nearCorner, enum::BoxVertex farCorner) {
|
||||||
|
@ -750,3 +750,98 @@ void ViewFrustum::invalidate() {
|
||||||
}
|
}
|
||||||
_centerSphereRadius = -1.0e6f; // -10^6 should be negative enough
|
_centerSphereRadius = -1.0e6f; // -10^6 should be negative enough
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::getSidePlanes(::Plane planes[4]) const {
|
||||||
|
planes[0] = _planes[TOP_PLANE];
|
||||||
|
planes[1] = _planes[BOTTOM_PLANE];
|
||||||
|
planes[2] = _planes[LEFT_PLANE];
|
||||||
|
planes[3] = _planes[RIGHT_PLANE];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::getTransformedSidePlanes(const Transform& transform, ::Plane planes[4]) const {
|
||||||
|
glm::mat4 normalTransform;
|
||||||
|
transform.getInverseTransposeMatrix(normalTransform);
|
||||||
|
getSidePlanes(planes);
|
||||||
|
for (auto i = 0; i < 4; i++) {
|
||||||
|
// We assume the transform doesn't have a non uniform scale component to apply the
|
||||||
|
// transform to the normal without using the correct transpose of inverse.
|
||||||
|
auto transformedNormal = normalTransform * Transform::Vec4(planes[i].getNormal(), 0.0f);
|
||||||
|
auto planePoint = transform.transform(planes[i].getPoint());
|
||||||
|
glm::vec3 planeNormal(transformedNormal.x, transformedNormal.y, transformedNormal.z);
|
||||||
|
planes[i].setNormalAndPoint(planeNormal, planePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::getUniformlyTransformedSidePlanes(const Transform& transform, ::Plane planes[4]) const {
|
||||||
|
getSidePlanes(planes);
|
||||||
|
for (auto i = 0; i < 4; i++) {
|
||||||
|
// We assume the transform doesn't have a non uniform scale component to apply the
|
||||||
|
// transform to the normal without using the correct transpose of inverse.
|
||||||
|
auto planeNormal = transform.transformDirection(planes[i].getNormal());
|
||||||
|
auto planePoint = transform.transform(planes[i].getPoint());
|
||||||
|
planes[i].setNormalAndPoint(planeNormal, planePoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::tesselateSides(Triangle triangles[8]) const {
|
||||||
|
tesselateSides(_cornersWorld, triangles);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::tesselateSides(const Transform& transform, Triangle triangles[8]) const {
|
||||||
|
glm::vec3 points[8];
|
||||||
|
|
||||||
|
for (auto i = 0; i < 8; i++) {
|
||||||
|
points[i] = transform.transform(_cornersWorld[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tesselateSides(points, triangles);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::tesselateSidesAndFar(const Transform& transform, Triangle triangles[10], float farDistance) const {
|
||||||
|
glm::vec3 points[8];
|
||||||
|
|
||||||
|
// First 4 points are at near
|
||||||
|
for (auto i = 0; i < 4; i++) {
|
||||||
|
points[i] = transform.transform(_cornersWorld[i]);
|
||||||
|
}
|
||||||
|
auto farCorners = getCorners(farDistance);
|
||||||
|
|
||||||
|
points[BOTTOM_LEFT_FAR] = transform.transform(farCorners.bottomLeft);
|
||||||
|
points[BOTTOM_RIGHT_FAR] = transform.transform(farCorners.bottomRight);
|
||||||
|
points[TOP_LEFT_FAR] = transform.transform(farCorners.topLeft);
|
||||||
|
points[TOP_RIGHT_FAR] = transform.transform(farCorners.topRight);
|
||||||
|
|
||||||
|
tesselateSides(points, triangles);
|
||||||
|
// Add far side
|
||||||
|
triangles[8].v0 = points[BOTTOM_LEFT_FAR];
|
||||||
|
triangles[8].v1 = points[BOTTOM_RIGHT_FAR];
|
||||||
|
triangles[8].v2 = points[TOP_RIGHT_FAR];
|
||||||
|
|
||||||
|
triangles[9].v0 = points[BOTTOM_LEFT_FAR];
|
||||||
|
triangles[9].v1 = points[TOP_LEFT_FAR];
|
||||||
|
triangles[9].v2 = points[TOP_RIGHT_FAR];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::tesselateSides(const glm::vec3 points[8], Triangle triangles[8]) {
|
||||||
|
static_assert(BOTTOM_RIGHT_NEAR == (BOTTOM_LEFT_NEAR + 1), "Assuming a certain sequence in corners");
|
||||||
|
static_assert(TOP_RIGHT_NEAR == (BOTTOM_RIGHT_NEAR + 1), "Assuming a certain sequence in corners");
|
||||||
|
static_assert(TOP_LEFT_NEAR == (TOP_RIGHT_NEAR + 1), "Assuming a certain sequence in corners");
|
||||||
|
static_assert(BOTTOM_RIGHT_FAR == (BOTTOM_LEFT_FAR + 1), "Assuming a certain sequence in corners");
|
||||||
|
static_assert(TOP_RIGHT_FAR == (BOTTOM_RIGHT_FAR + 1), "Assuming a certain sequence in corners");
|
||||||
|
static_assert(TOP_LEFT_FAR == (TOP_RIGHT_FAR + 1), "Assuming a certain sequence in corners");
|
||||||
|
static const int triangleVertexIndices[8][3] = {
|
||||||
|
{ BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR },{ BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR },
|
||||||
|
{ BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR, TOP_RIGHT_FAR },{ BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR },
|
||||||
|
{ TOP_RIGHT_NEAR, TOP_LEFT_NEAR, TOP_RIGHT_FAR },{ TOP_LEFT_NEAR, TOP_RIGHT_FAR, TOP_LEFT_FAR },
|
||||||
|
{ BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR, TOP_LEFT_FAR },{ BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR, TOP_LEFT_FAR }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto i = 0; i < 8; i++) {
|
||||||
|
auto& triangle = triangles[i];
|
||||||
|
auto vertexIndices = triangleVertexIndices[i];
|
||||||
|
|
||||||
|
triangle.v0 = points[vertexIndices[0]];
|
||||||
|
triangle.v1 = points[vertexIndices[1]];
|
||||||
|
triangle.v2 = points[vertexIndices[2]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
glm::vec3 bottomRight;
|
glm::vec3 bottomRight;
|
||||||
// Get the corners depth units from frustum position, along frustum orientation
|
// Get the corners depth units from frustum position, along frustum orientation
|
||||||
};
|
};
|
||||||
const Corners getCorners(const float& depth) const;
|
const Corners getCorners(const float depth) const;
|
||||||
|
|
||||||
// getters for corners
|
// getters for corners
|
||||||
const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; }
|
const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; }
|
||||||
|
@ -90,6 +90,10 @@ public:
|
||||||
void setCenterRadius(float radius) { _centerSphereRadius = radius; }
|
void setCenterRadius(float radius) { _centerSphereRadius = radius; }
|
||||||
float getCenterRadius() const { return _centerSphereRadius; }
|
float getCenterRadius() const { return _centerSphereRadius; }
|
||||||
|
|
||||||
|
void tesselateSides(Triangle triangles[8]) const;
|
||||||
|
void tesselateSides(const Transform& transform, Triangle triangles[8]) const;
|
||||||
|
void tesselateSidesAndFar(const Transform& transform, Triangle triangles[10], float farDistance) const;
|
||||||
|
|
||||||
void calculate();
|
void calculate();
|
||||||
|
|
||||||
typedef enum { OUTSIDE = 0, INTERSECT, INSIDE } intersection;
|
typedef enum { OUTSIDE = 0, INTERSECT, INSIDE } intersection;
|
||||||
|
@ -134,6 +138,12 @@ public:
|
||||||
enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };
|
enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };
|
||||||
|
|
||||||
const ::Plane* getPlanes() const { return _planes; }
|
const ::Plane* getPlanes() const { return _planes; }
|
||||||
|
void getSidePlanes(::Plane planes[4]) const;
|
||||||
|
// Transform can have a different scale value in X,Y,Z components
|
||||||
|
void getTransformedSidePlanes(const Transform& transform, ::Plane planes[4]) const;
|
||||||
|
// Transform is assumed to have the same scale value in all three X,Y,Z components, which
|
||||||
|
// allows for a faster computation.
|
||||||
|
void getUniformlyTransformedSidePlanes(const Transform& transform, ::Plane planes[4]) const;
|
||||||
|
|
||||||
void invalidate(); // causes all reasonable intersection tests to fail
|
void invalidate(); // causes all reasonable intersection tests to fail
|
||||||
|
|
||||||
|
@ -175,6 +185,8 @@ private:
|
||||||
template <typename TBOX>
|
template <typename TBOX>
|
||||||
CubeProjectedPolygon computeProjectedPolygon(const TBOX& box) const;
|
CubeProjectedPolygon computeProjectedPolygon(const TBOX& box) const;
|
||||||
|
|
||||||
|
static void tesselateSides(const glm::vec3 points[8], Triangle triangles[8]);
|
||||||
|
|
||||||
};
|
};
|
||||||
using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
|
using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue