gluPerspective

BlitzMax Forums/OpenGL Module/gluPerspective

JoshK(Posted 2006) [#1]
gluPerspective() takes the vertical fov, aspect, and near and far view ranges. I want the viewport to always use the same horizontal fov, and adjust the vertical fov so that it isn't stretched, regardless of the viewport height.

Viewport width=1024
Viewport height=768
desired horizontal fov=90 degrees

The aspect is the width divided by the height, which is 1024/768=1.33333333. I tried this:

gluPerspective 90.0/1.3333333,1.3333333,near,far

But this did not give me a little less than 90 degrees view in the horizontal direction. The only way I could get a perfect 90-degree view in the horizontal direction was like this:

gluPerspective 90.0/1.3333333,1.5,near,far

What's going on here? I noticed that 90.0/1.3333333/1.5=45.0, which might be significant.

Then I tried using glFrustum:
glfrustum -nearrange/zoom,nearrange/zoom,-nearrange/aspect/zoom,nearrange/aspect/zoom,nearrange,farrange

When zoom=1.0, I get a perfect 90-degree fov in the horizontal direction. However, when I try changing zoom to 2.0, for a 45-degree fov, I get a somewhat larger fov in the horizontal direction (approximately 50-60 degrees).


JoshK(Posted 2006) [#2]
Well, after drawing it out on paper I saw that this takes a little trig to do. I have never seen a mention of precision zooming with the frustum, so I will post my solution here.

With zoom=1.0, the horizontal fov will be 90.0. With a zoom of 2.0, the horizontal fov will be 45.0 degrees. The vertical fov is dependent on viewport height. The aspect is the viewport width divided by the viewport height:

zoom#=2.0 // for a 45-degree fov. Use 1.0 for 90 degrees.
aspect#=width#/height#
theta#=Tan(45.0/zoom#) // temporary angle value
glfrustum -nearrange#*theta#,nearrange#*theta#,-nearrange#/aspect#*theta#,nearrange#/aspect#*theta#,nearrange#,farrange#


Oddball(Posted 2006) [#3]
Here's an alternative to gluPerspective that takes the fovx as a parameter instead of the fovy. All other params stay the same.
Function Perspective( fovx:Float, ratio:Float, near:Float, far:Float )
		Local x:Float=Tan(fovx/2.0)*near
		Local y:Float=x/ratio
		glFrustum -x,x,-y,y,near,far
End Function
Hope it's of some use to you.


Tom(Posted 2006) [#4]
Here's manual versions of gluPerspective (methods in my camera type), glh.. sets the FOV horizontally, glv vertically. Might be of help.

	Method glhPerspective() '

		Local xmin:Double, xmax:Double, ymin:Double, ymax:Double
		Local m:Double[16]

		xmax = zNear * Tan(fov*.5)
		xmin = -xmax

		ymin = xmin / aspect
		ymax = xmax / aspect

		m[0] = (2 * zNear) / (xmax - xmin)
		m[5] = (2 * zNear) / (ymax - ymin)
		m[10]= -(zFar + zNear) / (zFar - zNear)

		m[2] = (xmax + xmin) / (xmax - xmin)
		m[6] = (ymax + ymin) / (ymax - ymin)
		m[11] = -1

		m[14] = -(2 * zFar * zNear) / (zFar - zNear);

		glMultMatrixd m
	End Method

	Method glvPerspective()
		Local xmin:Double, xmax:Double, ymin:Double, ymax:Double
		Local m:Double[16]

		xmax = zNear * Tan(fov*.5)
		xmin = -xmax

		ymin = xmin / aspect
		ymax = xmax / aspect

		m[0] = (2 * zNear) / (xmax - xmin)
		m[5] = (2 * zNear) / (ymax - ymin)
		m[10]= -(zFar + zNear) / (zFar - zNear)

		m[2] = (xmax + xmin) / (xmax - xmin)
		m[6] = (ymax + ymin) / (ymax - ymin)
		m[11] = -aspect

		m[14] = -(2 * zFar * zNear) / (zFar - zNear);
   
		glMultMatrixd m
	End Method



JoshK(Posted 2006) [#5]
I figured it out for glfrustum, which I will just stick with. The zoom component is particularly important, and I recommend anyone setting up and opengl camera use what I write in my second post.