Jump to content
  • Advertisement
Sign in to follow this  
tomer_sh

OpenGL Frustum Question - I'm in a little problem

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all! - I do the following with OpenGL: gluPerspective(45.0f,(GLfloat)256.0/(GLfloat)192.0,0.1f,100.0f); - So from that you should know: - My Height Angle is 45 degrees - Screen Width is 256 - screen Height is 192 - Near plane at z = 0.1 - Far plane is at z = 100.0 - my question is: How do I gather all of this data to calculate the frustum's planes? I'm looking for the real calculus equations, and not by extracting data from Projection and ModelView matrices like most tutorials show. - question number 2: Not too long ago I stumbled with this code for Frustum calculation: look at it and please answer, how can I modify it so it will take into consideration the Height angle of FOV of my choise, so it will have compatiability with openGL' gluPerspective, or how can I make perspective of OpenGL that will have similar calculus as this code. I know I'm a bit confused, but a good explanation of the following calculus, and especially on why it doesn't work like OpenGL does with constant angle would be helpful. #define Screen_Width 256 #define Screen_Height 192 double fieldofview = 2.0; double xscreenscale = Screen_Width / 2; double yscreenscale = Screen_Height / 2; double maxscale = max(xscreenscale , yscreenscale ); void SetUpFrustum(void) { double angle, s, c; point_t normal; angle = atan(2.0 / fieldofview * maxscale / xscreenscale); s = sin(angle); c = cos(angle); // Left clip plane normal.v[0] = s; normal.v[1] = 0; normal.v[2] = c; SetWorldspaceClipPlane(&normal, &frustumplanes[0]); // Right clip plane normal.v[0] = -s; SetWorldspaceClipPlane(&normal, &frustumplanes[1]); angle = atan(2.0 / fieldofview * maxscale / yscreenscale); s = sin(angle); c = cos(angle); // Bottom clip plane normal.v[0] = 0; normal.v[1] = s; normal.v[2] = c; SetWorldspaceClipPlane(&normal, &frustumplanes[2]); // Top clip plane normal.v[1] = -s; SetWorldspaceClipPlane(&normal, &frustumplanes[3]); } anyaway, thanks in advance. your help is important

Share this post


Link to post
Share on other sites
Advertisement
there is no calculus here, only trig. I'll post a derivation once I get back from work.

Tim

Share this post


Link to post
Share on other sites
I'm currently using a derivation of this same function in a project (original code by M. Abrash). The height angle is determined by "yscreenscale" which is vertical_resolution / fieldofview. As you change the vertical screen size, this function will calculate the proper frustum planes. It works great.

Here's what my function looks like...

void SetUpFrustum(void)
{
Flt xangle, yangle, s, c;
Vec normal;

xangle = atan(2.0 / fieldofview * maxscale / xscreenscale );
s = sin(xangle);
c = cos(xangle);
normal[0] = s;
normal[1] = 0;
normal[2] = c;
VecCopy(normal, frustumplanes[0]);
normal[0] = -s;
VecCopy(normal, frustumplanes[1]);
yangle = atan(2.0 / fieldofview * maxscale / yscreenscale );
s = sin(yangle);
c = cos(yangle);
normal[0] = 0;
normal[1] = -s;
normal[2] = c;
VecCopy(normal, frustumplanes[2]);
normal[1] = s;
VecCopy(normal, frustumplanes[3]);
MakeVector(0.0, 0.0, frontPlaneDistance, frustumplanes[4]);
}

Share this post


Link to post
Share on other sites
thanks!

but you still didn't answer my question.
I need compitability between OpenGL's perspective to the frustum generation code

cheers, tomer

Share this post


Link to post
Share on other sites
I wrote and tested some simple code to allow passing the viewing angle in degrees to SetUpFrustum(). Does this help at all?


#define degtorad(a) (((double)(a)) * 3.14159/180.0)

void SetUpFrustum(double angle)
{
fieldofview = 2.0 * tan( degtorad(angle) / 2.0);
...
}

Share this post


Link to post
Share on other sites
Here my code to create a frustum object from 2 different approaches (I also have one for perspective correct stereo, but I don't think you care about that :):


/**
* calculate frustum from FOV/aspect
**/

void afrustum::setValues(float fov, float aspect, float n, float f)
{
float t = n * (float)tan(DEG2RAD(fov) * 0.5);
float b = -t;
float l = b * aspect;
float r = t * aspect;

setValues(t, b, l, r, n, f);
};

/**
* calculate frustum from tblrnf
**/

void afrustum::setValues(float t, float b, float l, float r, float n, float f)
{
top = t;
bottom = b;
left = l;
right = r;
nr = n;
fr = f;
n = -n;
f = -f;
left_p = aplane(avector(0.0f, 0.0f, 0.0f), avector(l , b , n), avector(l , t , n));
right_p = aplane(avector(0.0f, 0.0f, 0.0f), avector(r , b , n), avector(r , t , n));
top_p = aplane(avector(0.0f, 0.0f, 0.0f), avector(l , t , n), avector(r , t , n));
bottom_p = aplane(avector(0.0f, 0.0f, 0.0f), avector(l , b , n), avector(r , b , n));
near_p = aplane(avector(0.0f, 0.0f, n), avector(1.0f, 0.0, n), avector(0.0f, 1.0f, n));
far_p = aplane(avector(0.0f, 0.0f, f), avector(1.0f, 0.0, f), avector(0.0f, 1.0f, f));
};






The main idea is to convert to l,r,t,b,n,f format first. That's much more powerful and (IMO) easier to understand than the FOV version...
You can use glFrustum to create a matrix from the l,r,t,b,n,f values of the frustum.

The relevant portions of my plane class:

float a,b,c,d;
avector base, normal, pt1, pt2;

inline void get_equation()
{
a = normal.x;
b = normal.y;
c = normal.z;
d = -(a * base.x + b * base.y + c * base.z);
};

inline void get_normal()
{ // the ^ operator is the cross product...
normal = (pt1 - base) ^ (base - pt2);
normal.normalize();
};

/**
* create aplane from base point + normal vector
*
* @param b base vertex of the plane (point on the plane)
* @param n normal vector of the plane
**/

aplane(avector b, avector n)
{
base = b;
normal = n;
pt1 = avector();
pt2 = avector();
normal.normalize();
get_equation();
};

/**
* create aplane from base point + 2 vectors on the plane
*
* @param b base vertex of the plane (point on the plane)
* @param p1 first plane vector (vector from b parallel to the plane)
* @param p2 second plane vactor (vector on the plane, perpendicular to p1)
**/

aplane(avector b, avector p1, avector p2)
{
base = b;
pt1 = p1;
pt2 = p2;
get_normal();
get_equation();
};






Note that my plane class maintains two different (redundant) representation of a plane: base/normal and plane equation (a,b,c,d) I don't know which one you need.
Anyway, you should the solution to your problem from these code snippets...

Tom

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Guest
This topic is now closed to further replies.
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!