Skip to content

Instantly share code, notes, and snippets.

@terryjsmith
Last active February 10, 2023 09:52
Show Gist options
  • Save terryjsmith/7196d8c099e1478ea276bd751925a2f1 to your computer and use it in GitHub Desktop.
Save terryjsmith/7196d8c099e1478ea276bd751925a2f1 to your computer and use it in GitHub Desktop.
Frustum Camera::CalculateFrustum(float fnear, float ffar) {
Frustum returnFrustum;
// Calculate the near and far plane points
float nearHeight = 2 * tan(fov / 2) * fnear;
float nearWidth = nearHeight * aspect;
float farHeight = 2 * tan(fov / 2) * ffar;
float farWidth = farHeight * aspect;
// And their centers
vector3 nearCenter = position + (look * fnear);
vector3 farCenter = position + (look * ffar);
returnFrustum.center = position + (look * (ffar / 2.0f));
// And the actual coordinates
returnFrustum.fnear[Frustum::COORD_BOTTOMLEFT] = nearCenter - (up * (nearHeight / 2.0f)) - (right * (nearWidth / 2.0f));
returnFrustum.fnear[Frustum::COORD_BOTTOMRIGHT] = nearCenter - (up * (nearHeight / 2.0f)) + (right * (nearWidth / 2.0f));
returnFrustum.fnear[Frustum::COORD_TOPLEFT] = nearCenter + (up * (nearHeight / 2.0f)) - (right * (nearWidth / 2.0f));
returnFrustum.fnear[Frustum::COORD_TOPRIGHT] = nearCenter + (up * (nearHeight / 2.0f)) + (right * (nearWidth / 2.0f));
returnFrustum.ffar[Frustum::COORD_BOTTOMLEFT] = farCenter - (up * (farHeight / 2.0f)) - (right * (farWidth / 2.0f));
returnFrustum.ffar[Frustum::COORD_BOTTOMRIGHT] = farCenter - (up * (farHeight / 2.0f)) + (right * (farWidth / 2.0f));
returnFrustum.ffar[Frustum::COORD_TOPLEFT] = farCenter + (up * (farHeight / 2.0f)) - (right * (farWidth / 2.0f));
returnFrustum.ffar[Frustum::COORD_TOPRIGHT] = farCenter + (up * (farHeight / 2.0f)) + (right * (farWidth / 2.0f));
// Then create our frustum planes
returnFrustum.planes[Frustum::PLANE_NEAR].CreateFromPoints(m_viewFrustum.fnear[Frustum::COORD_BOTTOMLEFT], m_viewFrustum.fnear[Frustum::COORD_BOTTOMRIGHT], m_viewFrustum.fnear[Frustum::COORD_TOPLEFT]);
returnFrustum.planes[Frustum::PLANE_FAR].CreateFromPoints(m_viewFrustum.ffar[Frustum::COORD_TOPLEFT],m_viewFrustum.ffar[Frustum::COORD_TOPRIGHT], m_viewFrustum.ffar[Frustum::COORD_BOTTOMLEFT]);
returnFrustum.planes[Frustum::PLANE_LEFT].CreateFromPoints(m_viewFrustum.fnear[Frustum::COORD_BOTTOMLEFT], m_viewFrustum.fnear[Frustum::COORD_TOPLEFT], m_viewFrustum.ffar[Frustum::COORD_BOTTOMLEFT]);
returnFrustum.planes[Frustum::PLANE_RIGHT].CreateFromPoints(m_viewFrustum.ffar[Frustum::COORD_TOPRIGHT], m_viewFrustum.fnear[Frustum::COORD_TOPRIGHT], m_viewFrustum.ffar[Frustum::COORD_BOTTOMRIGHT]);
returnFrustum.planes[Frustum::PLANE_TOP].CreateFromPoints(m_viewFrustum.ffar[Frustum::COORD_TOPLEFT], m_viewFrustum.fnear[Frustum::COORD_TOPLEFT], m_viewFrustum.ffar[Frustum::COORD_TOPRIGHT]);
returnFrustum.planes[Frustum::PLANE_BOTTOM].CreateFromPoints(m_viewFrustum.fnear[Frustum::COORD_BOTTOMLEFT], m_viewFrustum.ffar[Frustum::COORD_BOTTOMLEFT], m_viewFrustum.fnear[Frustum::COORD_BOTTOMRIGHT]);
return returnFrustum;
}
int Frustum::Intersects(vector3& point) {
for(int i=0; i < 6; i++) {
if (planes[i].Distance(point) > 0)
return(0);
}
return(1);
}
int Frustum::Intersects(BoundingBox &box) {
for(int p = 0; p < 6; p++) {
if(planes[p].Distance(box.points[0]) < 0 )
continue;
if(planes[p].Distance(box.points[1]) < 0 )
continue;
if(planes[p].Distance(box.points[2]) < 0 )
continue;
if(planes[p].Distance(box.points[3]) < 0 )
continue;
if(planes[p].Distance(box.points[4]) < 0 )
continue;
if(planes[p].Distance(box.points[5]) < 0 )
continue;
if(planes[p].Distance(box.points[6]) < 0 )
continue;
if(planes[p].Distance(box.points[7]) < 0 )
continue;
return(0);
}
return(1);
}
/**
* Define our viewing frustum for frustum culling and other cool things
*/
class Frustum {
public:
Frustum();
~Frustum();
/**
* Check a single point
*/
int Intersects(vector3& point);
/**
* Check a bounding box
*/
int Intersects(BoundingBox& box);
public:
enum {
COORD_BOTTOMLEFT = 0,
COORD_BOTTOMRIGHT,
COORD_TOPLEFT,
COORD_TOPRIGHT
};
enum {
PLANE_LEFT = 0,
PLANE_RIGHT,
PLANE_BOTTOM,
PLANE_TOP,
PLANE_NEAR,
PLANE_FAR
};
public:
/**
* Defines our near and far vertices
*/
vector3 fnear[4];
vector3 ffar[4];
/**
* The center of the frustum (useful for extents/CSM)
*/
vector3 center;
/**
* Planes
*/
Plane planes[6];
};
#endif /* frustum_hpp */
void Plane::CreateFromPoints(vector3& p0, vector3& p1, vector3 &p2) {
vector3 v1 = p1 - p0;
vector3 v2 = p2 - p0;
abc = glm::normalize(glm::cross(v1, v2));
d = -glm::dot(p0, abc);
}
float Plane::Distance(vector3& point) {
return(abc.x * point.x + abc.y * point.y + abc.z * point.z + d);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment