frustum_t proj_frustum(const float4x4& proj, bool normalize_planes) { // Gil Gribb & Klaus Hartmann, assumed public domain // http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf // http://crazyjoke.free.fr/doc/3D/plane%20extraction.pdf frustum_t f; f[oCUBE_LEFT].x = proj[0][3] + proj[0][0]; f[oCUBE_LEFT].y = proj[1][3] + proj[1][0]; f[oCUBE_LEFT].z = proj[2][3] + proj[2][0]; f[oCUBE_LEFT].w = proj[3][3] + proj[3][0]; f[oCUBE_RIGHT].x = proj[0][3] - proj[0][0]; f[oCUBE_RIGHT].y = proj[1][3] - proj[1][0]; f[oCUBE_RIGHT].z = proj[2][3] - proj[2][0]; f[oCUBE_RIGHT].w = proj[3][3] - proj[3][0]; f[oCUBE_TOP].x = proj[0][3] - proj[0][1]; f[oCUBE_TOP].y = proj[1][3] - proj[1][1]; f[oCUBE_TOP].z = proj[2][3] - proj[2][1]; f[oCUBE_TOP].w = proj[3][3] - proj[3][1]; f[oCUBE_BOTTOM].x = proj[0][3] + proj[0][1]; f[oCUBE_BOTTOM].y = proj[1][3] + proj[1][1]; f[oCUBE_BOTTOM].z = proj[2][3] + proj[2][1]; f[oCUBE_BOTTOM].w = proj[3][3] + proj[3][1]; if (has_projection(proj)) { f[oCUBE_NEAR].x = proj[0][2]; f[oCUBE_NEAR].y = proj[1][2]; f[oCUBE_NEAR].z = proj[2][2]; f[oCUBE_NEAR].w = proj[3][2]; } else { f[oCUBE_NEAR].x = proj[0][3] + proj[0][2]; f[oCUBE_NEAR].y = proj[1][3] + proj[1][2]; f[oCUBE_NEAR].z = proj[2][3] + proj[2][2]; f[oCUBE_NEAR].w = proj[3][3] + proj[3][2]; } f[oCUBE_FAR].x = proj[0][3] - proj[0][2]; f[oCUBE_FAR].y = proj[1][3] - proj[1][2]; f[oCUBE_FAR].z = proj[2][3] - proj[2][2]; f[oCUBE_FAR].w = proj[3][3] - proj[3][2]; if (normalize_planes) for (auto& p : f) p = normalize_plane(p); return f; }
/** * @brief Update the frustum clipping planes. */ void RCamera::update_frustum() { float pm[16]; float mvm[16]; /* get the projection matrix */ glGetFloatv(GL_PROJECTION_MATRIX, pm); /* get the model view matrix */ glGetFloatv(GL_MODELVIEW_MATRIX, mvm); matrix4 m_pm(pm); matrix4 m_mvm(mvm); matrix4 clip = m_mvm * m_pm; clip.transpose(); frustum[0][0] = clip[3][0] - clip[0][0]; frustum[0][1] = clip[3][1] - clip[0][1]; frustum[0][2] = clip[3][2] - clip[0][2]; frustum[0][3] = clip[3][3] - clip[0][3]; normalize_plane(&frustum[0][0], &frustum[0][1], &frustum[0][2], &frustum[0][3]); frustum[1][0] = clip[3][0] + clip[0][0]; frustum[1][1] = clip[3][1] + clip[0][1]; frustum[1][2] = clip[3][2] + clip[0][2]; frustum[1][3] = clip[3][3] + clip[0][3]; normalize_plane(&frustum[1][0], &frustum[1][1], &frustum[1][2], &frustum[1][3]); frustum[2][0] = clip[3][0] + clip[1][0]; frustum[2][1] = clip[3][1] + clip[1][1]; frustum[2][2] = clip[3][2] + clip[1][2]; frustum[2][3] = clip[3][3] + clip[1][3]; normalize_plane(&frustum[2][0], &frustum[2][1], &frustum[2][2], &frustum[2][3]); frustum[3][0] = clip[3][0] - clip[1][0]; frustum[3][1] = clip[3][1] - clip[1][1]; frustum[3][2] = clip[3][2] - clip[1][2]; frustum[3][3] = clip[3][3] - clip[1][3]; normalize_plane(&frustum[3][0], &frustum[3][1], &frustum[3][2], &frustum[3][3]); frustum[4][0] = clip[3][0] - clip[2][0]; frustum[4][1] = clip[3][1] - clip[2][1]; frustum[4][2] = clip[3][2] - clip[2][2]; frustum[4][3] = clip[3][3] - clip[2][3]; normalize_plane(&frustum[4][0], &frustum[4][1], &frustum[4][2], &frustum[4][3]); frustum[5][0] = clip[3][0] + clip[2][0]; frustum[5][1] = clip[3][1] + clip[2][1]; frustum[5][2] = clip[3][2] + clip[2][2]; frustum[5][3] = clip[3][3] + clip[2][3]; normalize_plane(&frustum[5][0], &frustum[5][1], &frustum[5][2], &frustum[5][3]); }