Frustum planes calculation

This commit is contained in:
Evert Prants 2018-04-16 13:51:02 +03:00
parent 5354d42af8
commit 22060b455f
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
3 changed files with 109 additions and 1 deletions

View File

@ -272,7 +272,7 @@ void Application::run()
void Application::update(GLfloat dtime)
{
}
void Application::render()

View File

@ -61,6 +61,101 @@ glm::mat4 Camera::getViewMatrix()
return glm::lookAt(m_position, m_position + m_front, m_up);
}
void Camera::updateFrustum(void)
{
const glm::mat4 mvp = getViewMatrix() * m_projection;
// Extract the clipping planes; right, left, far, near, top, bottom
m_planes[0] = mvp[3] - mvp[0];
m_planes[1] = mvp[3] + mvp[0];
m_planes[2] = mvp[3] - mvp[2];
m_planes[3] = mvp[3] + mvp[2];
m_planes[4] = mvp[3] - mvp[1];
m_planes[5] = mvp[3] + mvp[1];
// Normalize vectors
for (unsigned int i = 0; i < 6; i++)
{
m_planes[i] = glm::normalize(m_planes[i]);
}
}
// Calculates the closest distance from a given point to a given clipping plane
float Camera::frustumDistanceToPlane(const int plane, const glm::vec3 &point) const
{
return m_planes[plane].x * point.x + m_planes[plane].y * point.y + m_planes[plane].z * point.z + m_planes[plane].w;
}
bool Camera::frustumContainsPoint(const glm::vec3 &point) const
{
// For each plane; return outside if the point is behind the plane
for (unsigned int i = 0; i < 6; i++)
{
if (frustumDistanceToPlane(i, point) <= 0.0)
return false;
}
// Return inside
return true;
}
int Camera::frustumContainsSphere(const glm::vec3 &position, const double radius) const
{
// Plane counter
int planeCount = 0;
// Use the point-to-plane distance to calculate the number of planes the sphere is in front of
for (unsigned int i = 0; i < 6; i++)
{
const double distance = frustumDistanceToPlane(i, position);
if (distance <= -radius)
return 0;
else if (distance > radius)
planeCount++;
}
// Return inside if in front of all planes; otherwise intersecting
return planeCount == 6 ? 1 : 2;
}
int Camera::frustumContainsBox(const glm::vec3 &min, const glm::vec3 &max) const
{
// Build a vector holding all box corners
std::vector<glm::vec3> points;
for (unsigned int i = 0; i < 8; i++)
{
points.push_back(glm::vec3(i < 4 ? max.x : min.x, i % 4 < 2 ? max.y : min.y, i % 2 ? max.z : min.z));
}
// Test the box as a polygon
return frustumContainsPolygon(points);
}
int Camera::frustumContainsPolygon(const std::vector<glm::vec3> &points) const
{
// Plane counter
int planeCount = 0;
// Use the point-to-plane distance to calculate the number of planes the polygon is in front of
for (unsigned int i = 0; i < 6; i++)
{
unsigned int pointCount = 0;
for (unsigned int j = 0; j < points.size(); j++)
{
if (frustumDistanceToPlane(i, points[j]) > 0.0)
pointCount++;
if (pointCount == 0)
return 0;
else if (pointCount == points.size())
planeCount++;
}
}
// Return inside if in front of all planes; otherwise intersecting
return planeCount == 6 ? 1 : 2;
}
void Camera::shaderViewProjection(Shader& shader)
{
shader.setUniform("viewMatrix", getViewMatrix());
@ -132,6 +227,7 @@ void Camera::updateProjection(void)
// Recalculate the projection matrix
glm::vec2 screenDims = Application::getInstance().getScreenDimensions();
m_projection = glm::perspective(getFOV(), (GLfloat)screenDims.x/(GLfloat)screenDims.y, 0.1f, 100.0f);
updateFrustum();
}
void Camera::updateCameraVectors(void)
@ -147,4 +243,6 @@ void Camera::updateCameraVectors(void)
// Normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement.
m_right = glm::normalize(glm::cross(m_front, m_worldUp));
m_up = glm::normalize(glm::cross(m_right, m_front));
updateFrustum();
}

View File

@ -52,6 +52,11 @@ public:
inline GLfloat getFOV() const { return m_zoom; }
inline glm::vec3 getPosition(void) const { return m_position; }
bool frustumContainsPoint(const glm::vec3 &point) const;
int frustumContainsSphere(const glm::vec3 &position, const double radius) const;
int frustumContainsBox(const glm::vec3 &min, const glm::vec3 &max) const;
int frustumContainsPolygon(const std::vector<glm::vec3> &points) const;
private:
glm::vec3 m_position;
glm::vec3 m_front;
@ -72,7 +77,12 @@ private:
// The Projection Matrix
glm::mat4 m_projection;
// Frustum Culling
glm::vec4 m_planes[6];
float frustumDistanceToPlane(const int plane, const glm::vec3 &point) const;
void updateCameraVectors(void);
void updateProjection(void);
void updateFrustum(void);
};
#endif // __CAMERA_H__