I think I have it figured out.
First of all A and B need to be in the camera space, meaning that the line that goes out the center of the camera (the line formed by S + N * t) will fall directly on the z axis. This means that the X and Y of this line will always be 0 or.
Px = 0
Py = 0
This leaves us with only one variable to solve for or Pz.
We know that the distance between P and A is the same as P and B so
Ax^2 + Ay^2 + (Az - Pz)^2 = Bx^2 + By^2 + (Bz - Pz)^2
at this point we just solve for Pz.
Pz = ((Bx^2 + By^2 + Bz^2) - (Ax^2 + Ay^2 + Az^2)) / (2(Bz - Az))
The only thing left to do is the transform P into world space and calculate the radius of the circle by finding the distance between P and A or P and B.
If I didn't explain clearly enough let me know and I can give some detail.
Minimum bounding sphere of a Frustum
Let E be the eyepoint. Let the view direction be D, the up direction be U, and the right direction be R. D, U, and R are unit length and mutually perpendicular. The frustum values are dmin (near), dmax (far), rmax (right), -rmax (left), umax (up), and -umax (down). The sphere center is C = E + s*D for some s. A vertex of the near plane is P0 = E + dmin*D + umax*U + rmax*R. A vertex of the far plane is P1 = E + dmax*D + (dmax*umax/dmin)*U + (dmax*rmax/dmin)*R. The squared distances from P0 to C and P1 to C must be equal, so (s-dmin)^2 + rmax^2 + umax^2 = (s - dmax)^2 + (dmax*rmax/dmin)^2 + (dmax*umax/dmin)^2. This leads to s = ((dmin + dmax)/2)*(1 + (rmax/dmin)^2 + (umax/dmin)^2).
This is actually the circumscribed sphere, which I believe is the minimum-volume sphere as long as center C is inside the frustum, which means as long as s <= dmax. When s > dmax, the minimum-volume sphere is the one whose center is E+dmax*D. The radius is distance from C to a vertex on the far plane. In the case s < dmax, the radius is the distance from C to any of the 8 vertices, but you can just substitute the value of s in either of the squared distances I mentioned and then take the square root.
@Mussi: I solved them using Maple, you should give it a try, nice app
@Owl: I have tried checking miniball algorithm out, Dave Eberly also has an implementation in his website, which is very complicated and as long as frustum has 8 verts and is symmetric I don't think I need to implement that.
@Dave, @HappyCoder
thanks guys, as long as I got HappyCoder's method more clearly, I'll try to implement that first and check the results
another method I'm currently using is that, I use barycentric minimum bounding spheres method (described here) for two tetrahedrons inside of the frustum. if indices 0~3 is vertices of the frustum's near plane, and 4~7 for far plane, I calculate one sphere for 0-2-5-7, and one for 1-3-4-6 (opposite tetrahedrons) , and merge two spheres. I think get acceptable results from this, but it's still pretty big especially for frustums with high aspect ratio (fov is high and (far-near) is small), although I don't think I can get small bounding spheres for those, because of the nature of the shape.
@Owl: I have tried checking miniball algorithm out, Dave Eberly also has an implementation in his website, which is very complicated and as long as frustum has 8 verts and is symmetric I don't think I need to implement that.
@Dave, @HappyCoder
thanks guys, as long as I got HappyCoder's method more clearly, I'll try to implement that first and check the results
another method I'm currently using is that, I use barycentric minimum bounding spheres method (described here) for two tetrahedrons inside of the frustum. if indices 0~3 is vertices of the frustum's near plane, and 4~7 for far plane, I calculate one sphere for 0-2-5-7, and one for 1-3-4-6 (opposite tetrahedrons) , and merge two spheres. I think get acceptable results from this, but it's still pretty big especially for frustums with high aspect ratio (fov is high and (far-near) is small), although I don't think I can get small bounding spheres for those, because of the nature of the shape.
//----------------------------------------------------------------------------
void ComputeMinimumVolumeSphereOfFrustum (const float eye[3],
const float direction[3], const float dmin, const float dmax,
const float rmax, const float umax, float center[3], float& radius)
{
float invDMin = 1.0f/dmin;
float u = umax*invDMin;
float r = rmax*invDMin;
float u2pr2 = u*u + r*r;
float s = 0.5f*(dmin + dmax)*(1.0f + u2pr2);
if (s >= dmax)
{
s = dmax;
radius = dmax*sqrt(u2pr2);
}
else
{
float diff = 1.0f - s/dmax;
radius = dmax*sqrt(diff*diff + u2pr2);
}
for (int i = 0; i < 3; ++i)
{
center = eye + s*direction;
}
}
//----------------------------------------------------------------------------
template <int n, typename Real>
void ComputeMiniballFrustum (const Real eye[n], const Real direction[n],
const Real min0, const Real max[n], Real center[n], Real& radius)
{
Real invMin0 = ((Real)1)/min0;
float ratio[n], sqrLength = (Real)0;
for (int i = 1; i < n; ++i)
{
ratio = max*invMin0;
sqrLength += ratio*ratio;
}
Real s = ((Real)0.5)*(min0 + max[0])*((Real)1 + sqrLength);
if (s >= max[0])
{
s = max[0];
radius = max[0]*sqrt(sqrLength);
}
else
{
Real diff = (Real)1 - s/max[0];
radius = max[0]*sqrt(diff*diff + sqrLength);
}
for (int i = 0; i < n; ++i)
{
center = eye + s*direction;
}
}
//----------------------------------------------------------------------------
int main ()
{
float eye[3] = { 0.0f, 0.0f, 0.0f };
float direction[3] = { 0.0f, 0.0f, 1.0f };
float dmin = 10.0f, dmax = 1000.0f, rmax = 2.0f, umax = 1.0f;
float center0[3], radius0;
ComputeMinimumVolumeSphereOfFrustum(eye, direction, dmin,
dmax, rmax, umax, center0, radius0);
float min0 = dmin, max[3] = { dmax, rmax, umax };
float center1[3], radius1;
ComputeMiniballFrustum<3,float>(eye, direction, min0, max, center1,
radius1);
return 0;
}
//----------------------------------------------------------------------------
Methods described by HappyCoder and David Eberly as well as the method I described in my previous post (slower), worked and gave identical results
thanks
@Postie: no I couldn't get that to work, I used barycentric coordinates to calculate circum circle of three points, and chose different set of points, but none of them gave minimum sphere of the frustum
thanks
@Postie: no I couldn't get that to work, I used barycentric coordinates to calculate circum circle of three points, and chose different set of points, but none of them gave minimum sphere of the frustum
Methods described by HappyCoder and David Eberly as well as the method I described in my previous post (slower), worked and gave identical results
thanks
@Postie: no I couldn't get that to work, I used barycentric coordinates to calculate circum circle of three points, and chose different set of points, but none of them gave minimum sphere of the frustum
thanks
@Postie: no I couldn't get that to work, I used barycentric coordinates to calculate circum circle of three points, and chose different set of points, but none of them gave minimum sphere of the frustum
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement