# Frustum corners from view projection

This topic is 2321 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I have the view projection matrix and want to deduce the 8 corners of the frustum. The way I'm thinking is just doing the inverse of the view projection matrix and multiply it by the corners in screen space. The problem I'm having is the z & w values of these corners. x & y are 1..-1, z I presume should be 0 for the near plane and 1 for the far plane? If so, what should w be? I've tried a few combinations and can quickly see that I'm doing something wrong, because the farplane is set at 10000 and the distance between my points is somewhere in the region of 75~.

##### Share on other sites
OpenGL? D3D? Something else?

IIRC in OpenGL zNear is mapped to -1, and zFar is mapped to +1.

If you have the projection matrix P then do the following (shown using column vectors here):
P * [ right top far 1 ][sup]t[/sup] =: e[sub]1[/sub]
P * [ left bottom near 1 ][sup]t[/sup] =: e[sub]2[/sub]

You'll get for example
e[sub]1[/sub] = [ x[sub]1[/sub] y[sub]1[/sub] z[sub]1[/sub] w[sub]1[/sub] ][sup]t[/sup]
and need to normalize the vector so that w becomes 1:
e[sub]1[/sub]/w[sub]1[/sub] = [ x[sub]1[/sub]/w[sub]1[/sub] y[sub]1[/sub]/w[sub]1[/sub] z[sub]1[/sub]/w[sub]1[/sub] 1 ][sup]t[/sup]
[sub][/sub][sub][/sub]
Now look the value z[sub]1[/sub]/w[sub]1[/sub] (and z[sub]2[/sub]/w[sub]2[/sub], resp.) and you have the values in normalized device space that correspond to far (and near, resp.) in view space. You probably need to round them due to numerical inaccuracies.

With this knowledge you can pick the correct values from the inverse P[sup]-1[/sup]. BTW: Because we're speaking of points you have to choose w=1 in almost all cases.
[sup]
[/sup]

##### Share on other sites
If you are looking for a DirectX implementation, the following link provides an explanation and source code...

##### Share on other sites
What would be the way of calculation of frustum corners in case of OpenGL? How is it different from DirectX?

That article you provided calculates frustum planes. What would be the easiest way to construct corners?

##### Share on other sites

NB! you can ignore the ptransform matrix - it is used to convert frustum from view to world space in one step.

c[] is the actual matrix data of my matrix class (column major, like OpenGL matrices). Cd are points in device coordinates, Xc,Yc,Zc,Wc are clip coordinates, Ce is point in eye/view coordinates.

void Matrix4x4f::getCornersofReverseProjection (Vector3f corners[], const Matrix4x4f& ptransform) const { // Ceye = ModelView X Cobj // Cclip = Projection X Ceye // Cnormdev = Cclip / perspective static const float Cd[] = { -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1 }; for (int i = 0; i < 8; i++) { // Clip coordinates // Final W has to be 1 // R[3] * Xc + R[7] * Yc + R[11] * Zc + R[15] * Wc = 1 // R[3] * Xd * Wc + R[7] * Yd * Wc + R[11] * Zd * Wc + R[15] * Wc = 1 // Wc * (R[3] * Xd + R[7] * Yd + R[11] * Zd + R[15]) = 1 // Wc = 1 / (R[3] * Xd + R[7] * Yd + R[11] * Zd + R[15]); // f32 Wc = 1 / (c[3] * Cd[3 * i + X] + c[7] * Cd[3 * i + Y] + c[11] * Cd[3 * i + Z] + c[15]); f32 d = c[3] * Cd[3 * i + X] + c[7] * Cd[3 * i + Y] + c[11] * Cd[3 * i + Z] + c[15]; f32 Wc = 1 / d; f32 Xc = Cd[3 * i + X] * Wc; f32 Yc = Cd[3 * i + Y] * Wc; f32 Zc = Cd[3 * i + Z] * Wc; // Eye coordinates Elea::Vector4f Ce(transform (Xc, Yc, Zc, Wc)); // Go to three dimensions corners = ptransform.transformPoint3 (Ce); } }

##### Share on other sites
How about "[color=#1C2837][font=CourierNew, monospace][size=2][color=#000000]corners[color=#666600][[color=#000000]i[color=#666600]]" [/font]points? Are those in world coordinates?

NB! you can ignore the ptransform matrix - it is used to convert frustum from view to world space in one step.

c[] is the actual matrix data of my matrix class (column major, like OpenGL matrices). Cd are points in device coordinates, Xc,Yc,Zc,Wc are clip coordinates, Ce is point in eye/view coordinates.

void Matrix4x4f::getCornersofReverseProjection (Vector3f corners[], const Matrix4x4f& ptransform) const { // Ceye = ModelView X Cobj // Cclip = Projection X Ceye // Cnormdev = Cclip / perspective static const float Cd[] = { -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1 }; for (int i = 0; i < 8; i++) { // Clip coordinates // Final W has to be 1 // R[3] * Xc + R[7] * Yc + R[11] * Zc + R[15] * Wc = 1 // R[3] * Xd * Wc + R[7] * Yd * Wc + R[11] * Zd * Wc + R[15] * Wc = 1 // Wc * (R[3] * Xd + R[7] * Yd + R[11] * Zd + R[15]) = 1 // Wc = 1 / (R[3] * Xd + R[7] * Yd + R[11] * Zd + R[15]); // f32 Wc = 1 / (c[3] * Cd[3 * i + X] + c[7] * Cd[3 * i + Y] + c[11] * Cd[3 * i + Z] + c[15]); f32 d = c[3] * Cd[3 * i + X] + c[7] * Cd[3 * i + Y] + c[11] * Cd[3 * i + Z] + c[15]; f32 Wc = 1 / d; f32 Xc = Cd[3 * i + X] * Wc; f32 Yc = Cd[3 * i + Y] * Wc; f32 Zc = Cd[3 * i + Z] * Wc; // Eye coordinates Elea::Vector4f Ce(transform (Xc, Yc, Zc, Wc)); // Go to three dimensions corners = ptransform.transformPoint3 (Ce); } }

##### Share on other sites

How about "[color="#1C2837"][font="CourierNew, monospace"][color="#000000"]corners[color="#666600"][[color="#000000"]i[color="#666600"]]" [/font]points? Are those in world coordinates?

In the example above they are in view coordinates transformed by ptransform matrix. If the latter is identity, they are in view space, if it is current view matrix they are in world space.

##### Share on other sites
Hi,

I'm more thinking about calculating Frustum corners based on clipping planes.
Will this chunk of code calculate intersected point for three planes correctly?

[color="#010001"][font="Consolas"][/font] [color="#010001"][font="Consolas"] glm::vec3 BoundingFrustum::IntersectionPoint(const Plane & a, const Plane & b, const Plane & c) { glm::vec3 v1, v2, v3; float f = - glm::dot(a.GetNormal(), glm::cross(b.GetNormal(), c.GetNormal())); v1 = (a.GetDistance() * (glm::cross(b.GetNormal(), c.GetNormal()))); v2 = (b.GetDistance() * (glm::cross(c.GetNormal(), a.GetNormal()))); v3 = (c.GetDistance() * (glm::cross(a.GetNormal(), b.GetNormal()))); glm::vec3 vec = v1 + v2 + v3; return vec / f; }[/font] [color="#010001"][font="Consolas"] [/font] [color="#010001"][font="Consolas"][/font]
[color="#010001"][font="Consolas"][color="#010001"][color="#000000"]

Thanks,
Ruben
[/font]

##### Share on other sites
Hi everybody,

I developed algorithms to calculated frustum corners. As an input it gets projection matrix, calculates clipping planes, and then just doing plane intersection it calculates frustum corners.
I will be using it in a complex algorithm and now need to make sure that corners are getting calculated properly. So now it's time to test it.

What would be the best way to test this out?

If it makes difference, I'm writing with OpenGL.

Thanks,
Ruben