|
|
Modifying the projection matrix to perform oblique near-plane clipping
The following code modifies the OpenGL projection matrix so that the near plane coincides
with a given arbitrary plane. The far plane is adjusted so that the resulting view frustum
has the best shape possible. This code assumes that the original projection matrix is
a perspective projection (standard or infinite). The
clipPlane parameter
must be in camera-space coordinates, and its w-coordinate must be negative (corresponding
to the camera being on the negative side of the plane).
For algorithmic details, see Game Programming Gems 5, Section 2.6. This code uses the Vector4D class.
#include "Vector4D.h"
inline float sgn(float a)
{
if (a > 0.0F) return (1.0F);
if (a < 0.0F) return (-1.0F);
return (0.0F);
}
void ModifyProjectionMatrix(const Vector4D& clipPlane)
{
float matrix[16];
Vector4D q;
// Grab the current projection matrix from OpenGL
glGetFloatv(GL_PROJECTION_MATRIX, matrix);
// Calculate the clip-space corner point opposite the clipping plane
// as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
// transform it into camera space by multiplying it
// by the inverse of the projection matrix
q.x = (sgn(clipPlane.x) + matrix[8]) / matrix[0];
q.y = (sgn(clipPlane.y) + matrix[9]) / matrix[5];
q.z = -1.0F;
q.w = (1.0F + matrix[10]) / matrix[14];
// Calculate the scaled plane vector
Vector4D c = clipPlane * (2.0F / Dot(clipPlane, q));
// Replace the third row of the projection matrix
matrix[2] = c.x;
matrix[6] = c.y;
matrix[10] = c.z + 1.0F;
matrix[14] = c.w;
// Load it back into OpenGL
glMatrixMode(GL_PROJECTION);
glLoadMatrix(matrix);
}
|
|