Sign in to follow this  
Ylisen

Frustum corners from view projection

Recommended Posts

Ylisen    100
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 this post


Link to post
Share on other sites
haegarr    7372
OpenGL? D3D? Something else?

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

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

You'll get for example
[b]e[/b][sub]1[/sub] = [ x[size="2"][size="2"][sub]1[/sub][/size][/size] 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:
[b]e[/b][sub]1[/sub]/w[sub]1[/sub] = [ x[size="2"][size="2"][size="2"][sub]1[/sub][/size][/size][/size]/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 [b]P[/b][sup]-1[/sup]. BTW: Because we're speaking of points you have to choose w=1 in almost all cases.
[sup]
[/sup]

Share this post


Link to post
Share on other sites
LancerSolurus    630
If you are looking for a DirectX implementation, the following link provides an explanation and source code...

[url="http://www.chadvernon.com/blog/resources/directx9/frustum-culling/"]http://www.chadvernon.com/blog/resources/directx9/frustum-culling/[/url]

Share this post


Link to post
Share on other sites
rubenhak    154
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 this post


Link to post
Share on other sites
lauris71    841
My code with comments:

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.

[code]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[i] = ptransform.transformPoint3 (Ce);
}
}[/code]

Share this post


Link to post
Share on other sites
rubenhak    154
How about "[color=#1C2837][font=CourierNew, monospace][size=2][color=#000000]corners[/color][color=#666600][[/color][color=#000000]i[/color][color=#666600]]" [/color][/size][/font][/color]points? Are those in world coordinates?
[quote name='Lauris Kaplinski' timestamp='1317242810' post='4866949']
My code with comments:

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.

[code]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[i] = ptransform.transformPoint3 (Ce);
}
}[/code]
[/quote]

Share this post


Link to post
Share on other sites
lauris71    841
[quote name='rubenhak' timestamp='1317244329' post='4866957']
How about "[color="#1C2837"][font="CourierNew, monospace"][size="2"][color="#000000"]corners[/color][color="#666600"][[/color][color="#000000"]i[/color][color="#666600"]]" [/color][/size][/font][/color]points? Are those in world coordinates?
[/quote]
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 this post


Link to post
Share on other sites
rubenhak    154
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"][size="2"][code][/size][/font][/color]
[color="#010001"][font="Consolas"][size="2"]
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;
}[/size][/font][/color]
[color="#010001"][font="Consolas"] [/font][/color]
[color="#010001"][font="Consolas"][size="2"][/code][/size][/font][/color]
[color="#010001"][font="Consolas"][color="#010001"][color="#000000"]

Thanks,
Ruben
[/color][/color][/font][/color]

Share this post


Link to post
Share on other sites
rubenhak    154
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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this