From bda482e4eee76a5ba2139645682ae64dadacbc6b Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 5 Jul 2014 08:27:03 +0200 Subject: Fix FloatUtil.makePerspective(..): The tan(fovy/2) shall be used, not tan(fovy), fix callers; Simplify FloatUtil.makePerspective(..FovHVHalves..) Fix FloatUtil.makePerspective(..): The tan(fovy/2) shall be used, not tan(fovy), fix callers - This bug didn't hit (yet), since callers already performed the division (degree -> radian) by falsly claiming the passed value is in radian - where it was actually fov/2 in radians. Simplify FloatUtil.makePerspective(..FovHVHalves..) - Due to the fix above, it became pretty clear that the makeFrustum(..) method can be utilized. Simply apply all our tan-half-fov values on zNear. --- .../classes/com/jogamp/opengl/math/FloatUtil.java | 65 ++++------------------ .../com/jogamp/opengl/math/FovHVHalves.java | 39 +++++++++++-- .../classes/com/jogamp/opengl/util/PMVMatrix.java | 13 +++-- src/jogl/classes/jogamp/opengl/ProjectFloat.java | 11 +++- .../classes/jogamp/opengl/oculusvr/OVRUtil.java | 16 ++---- .../test/junit/jogl/stereo/StereoDemo01.java | 2 + 6 files changed, 71 insertions(+), 75 deletions(-) diff --git a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java index 3c6a867e6..d2e535eaf 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/math/FloatUtil.java @@ -558,18 +558,18 @@ public final class FloatUtil { * @param m_offset offset in given array m, i.e. start of the 4x4 matrix * @param initM if true, given matrix will be initialized w/ identity matrix, * otherwise only the frustum fields are set. - * @param fovy angle in radians + * @param fovy_rad angle in radians * @param aspect * @param zNear * @param zFar * @return given matrix for chaining */ public static float[] makePerspective(final float[] m, final int m_off, final boolean initM, - final float fovy, final float aspect, final float zNear, final float zFar) { - final float top=(float)Math.tan(fovy)*zNear; - final float bottom=-1.0f*top; - final float left=aspect*bottom; - final float right=aspect*top; + final float fovy_rad, final float aspect, final float zNear, final float zFar) { + final float top = tan(fovy_rad/2f) * zNear; // use tangent of half-fov ! + final float bottom = -1.0f * top; + final float left = aspect * bottom; + final float right = aspect * top; return makeFrustum(m, m_off, initM, left, right, bottom, top, zNear, zFar); } @@ -591,53 +591,12 @@ public final class FloatUtil { */ public static float[] makePerspective(final float[] m, final int m_offset, final boolean initM, final FovHVHalves fovhv, final float zNear, final float zFar) { - if( initM ) { - // m[m_offset+0+4*0] = 1f; - m[m_offset+1+4*0] = 0f; - m[m_offset+2+4*0] = 0f; - m[m_offset+3+4*0] = 0f; - - m[m_offset+0+4*1] = 0f; - // m[m_offset+1+4*1] = 1f; - m[m_offset+2+4*1] = 0f; - m[m_offset+3+4*1] = 0f; - - // m[m_offset+0+4*2] = 0f; - // m[m_offset+1+4*2] = 0f; - // m[m_offset+2+4*2] = 1f; - // m[m_offset+3+4*2] = 0f; - - m[m_offset+0+4*3] = 0f; - m[m_offset+1+4*3] = 0f; - // m[m_offset+2+4*3] = 0f; - // m[m_offset+3+4*3] = 1f; - } - - final float projScaleX = 2.0f / ( fovhv.left + fovhv.right ); - final float projScaleY = 2.0f / ( fovhv.top + fovhv.bottom ); - final float projOffsetX = ( fovhv.left - fovhv.right ) * projScaleX * 0.5f; - final float projOffsetY = -1f * ( fovhv.top - fovhv.bottom ) * projScaleY * 0.5f; - - // Produces X result, mapping clip edges to [-w,+w] - m[m_offset+0+4*0] = projScaleX; - m[m_offset+0+4*2] = -1f * projOffsetX; - - // Produces Y result, mapping clip edges to [-w,+w] (Y=up) - m[m_offset+1+4*1] = projScaleY; - m[m_offset+1+4*2] = -1f * projOffsetY; - - // Custom Z-buffer result .. same as frustum matrix! - m[m_offset+2+4*2] = -1.0f*(zFar+zNear)/(zFar-zNear); - m[m_offset+2+4*3] = -2.0f*(zFar*zNear)/(zFar-zNear); - // alternative: - // m[m_offset+2+4*2] = -1.0f * zFar / (zNear - zFar); - // m[m_offset+2+4*3] = (zFar * zNear) / (zNear - zFar); - - // Produces W result (= Z in) - m[m_offset+3+4*2] = -1.0f; - m[m_offset+3+4*3] = 0f; - - return m; + final FovHVHalves fovhvTan = fovhv.getInTangents(); // use tangent of half-fov ! + final float top = fovhvTan.top * zNear; + final float bottom = -1.0f * fovhvTan.bottom * zNear; + final float left = -1.0f * fovhvTan.left * zNear; + final float right = fovhvTan.right * zNear; + return makeFrustum(m, m_offset, initM, left, right, bottom, top, zNear, zFar); } /** diff --git a/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java b/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java index 18bba8c45..786d146e6 100644 --- a/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java +++ b/src/jogl/classes/com/jogamp/opengl/math/FovHVHalves.java @@ -48,7 +48,10 @@ public final class FovHVHalves { /** * Constructor for one {@link FovHVHalves} instance. - * + *

+ * It is recommended to pass and store values in tangent + * if used for perspective FOV calculations, since it will avoid conversion to tangent later on. + *

* @param left half horizontal FOV, left side, in tangent or radians * @param right half horizontal FOV, right side, in tangent or radians * @param top half vertical FOV, top side, in tangent or radians @@ -73,11 +76,26 @@ public final class FovHVHalves { * @param verticalFov whole vertical FOV in radians */ public static FovHVHalves createByRadians(final float horizontalFov, final float verticalFov) { - final float halfHorizFovTan = (float)Math.tan(horizontalFov/2f); - final float halfVertFovTan = (float)Math.tan(verticalFov/2f); + final float halfHorizFovTan = FloatUtil.tan(horizontalFov/2f); + final float halfVertFovTan = FloatUtil.tan(verticalFov/2f); return new FovHVHalves(halfHorizFovTan, halfHorizFovTan, halfVertFovTan, halfVertFovTan, true); } + /** + * Returns this instance values in tangent values. + *

+ * If this instance is {@link #inTangents} already, method returns this instance, + * otherwise a newly created instance w/ converted values to tangent. + *

+ */ + public final FovHVHalves getInTangents() { + if( inTangents ) { + return this; + } else { + return new FovHVHalves(FloatUtil.tan(left), FloatUtil.tan(right), FloatUtil.tan(top), FloatUtil.tan(bottom), true); + } + } + /** Returns the full horizontal FOV, i.e. {@link #left} + {@link #right}. */ public final float horzFov() { return left+right; } @@ -85,6 +103,19 @@ public final class FovHVHalves { public final float vertFov() { return top+bottom; } public final String toString() { - return "FovHVHalves["+(inTangents?"tangents":"radians")+": "+left+" l, "+right+" r, "+top+" t, "+bottom+" b]"; + return "FovHVH["+(inTangents?"tangents":"radians")+": "+left+" l, "+right+" r, "+top+" t, "+bottom+" b]"; + } + public final String toStringInDegrees() { + final float f = 180.0f / FloatUtil.PI; + final String storedAs = inTangents?"tangents":"radians"; + if( inTangents ) { + final float aleft = FloatUtil.atan(left); + final float aright = FloatUtil.atan(right); + final float atop = FloatUtil.atan(top); + final float abottom = FloatUtil.atan(bottom); + return "FovHVH[degrees: "+aleft*f+" l, "+aright*f+" r, "+atop*f+" t, "+abottom*f+" b, stored-as: "+storedAs+"]"; + } else { + return "FovHVH[degrees: "+left*f+" l, "+right*f+" r, "+top*f+" t, "+bottom*f+" b, stored-as: "+storedAs+"]"; + } } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java index 39608b116..289183b8e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java +++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java @@ -644,8 +644,8 @@ public final class PMVMatrix implements GLMatrixFunc { } @Override - public final void glRotatef(final float angdeg, final float x, final float y, final float z) { - glMultMatrixf(FloatUtil.makeRotationAxis(mat4Tmp1, 0, angdeg * FloatUtil.PI / 180.0f, x, y, z, mat4Tmp2), 0); + public final void glRotatef(final float ang_deg, final float x, final float y, final float z) { + glMultMatrixf(FloatUtil.makeRotationAxis(mat4Tmp1, 0, ang_deg * FloatUtil.PI / 180.0f, x, y, z, mat4Tmp2), 0); } /** @@ -671,9 +671,14 @@ public final class PMVMatrix implements GLMatrixFunc { /** * {@link #glMultMatrixf(FloatBuffer) Multiply} the {@link #glGetMatrixMode() current matrix} with the perspective/frustum matrix. + * + * @param fovy_deg fov angle in degrees + * @param aspect aspect ratio + * @param zNear + * @param zFar */ - public final void gluPerspective(final float fovy, final float aspect, final float zNear, final float zFar) { - glMultMatrixf( FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy*((float)Math.PI)/360.0f, aspect, zNear, zFar), 0 ); + public final void gluPerspective(final float fovy_deg, final float aspect, final float zNear, final float zFar) { + glMultMatrixf( FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_deg * FloatUtil.PI / 180.0f, aspect, zNear, zFar), 0 ); } /** diff --git a/src/jogl/classes/jogamp/opengl/ProjectFloat.java b/src/jogl/classes/jogamp/opengl/ProjectFloat.java index 2c7989237..5921eb9a9 100644 --- a/src/jogl/classes/jogamp/opengl/ProjectFloat.java +++ b/src/jogl/classes/jogamp/opengl/ProjectFloat.java @@ -165,13 +165,13 @@ public class ProjectFloat { /** * Method gluPerspective. * - * @param fovy angle in degrees + * @param fovy_deg fov angle in degrees * @param aspect * @param zNear * @param zFar */ - public void gluPerspective(final GLMatrixFunc gl, final float fovy, final float aspect, final float zNear, final float zFar) { - gl.glMultMatrixf(FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy / 2 * (float) Math.PI / 180, aspect, zNear, zFar), 0); + public void gluPerspective(final GLMatrixFunc gl, final float fovy_deg, final float aspect, final float zNear, final float zFar) { + gl.glMultMatrixf(FloatUtil.makePerspective(mat4Tmp1, 0, true, fovy_deg * FloatUtil.PI / 180.0f, aspect, zNear, zFar), 0); } /** @@ -235,6 +235,7 @@ public class ProjectFloat { /** * Map object coordinates to window coordinates. */ + @SuppressWarnings("deprecation") public boolean gluProject(final float objx, final float objy, final float objz, final FloatBuffer modelMatrix, final FloatBuffer projMatrix, @@ -283,6 +284,7 @@ public class ProjectFloat { * * @return */ + @SuppressWarnings("deprecation") public boolean gluProject(final float objx, final float objy, final float objz, final FloatBuffer modelMatrix, final FloatBuffer projMatrix, @@ -365,6 +367,7 @@ public class ProjectFloat { * @param obj_pos_offset * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity) */ + @SuppressWarnings("deprecation") public boolean gluUnProject(final float winx, final float winy, final float winz, final FloatBuffer modelMatrix, final FloatBuffer projMatrix, @@ -422,6 +425,7 @@ public class ProjectFloat { * * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity) */ + @SuppressWarnings("deprecation") public boolean gluUnProject(final float winx, final float winy, final float winz, final FloatBuffer modelMatrix, final FloatBuffer projMatrix, @@ -523,6 +527,7 @@ public class ProjectFloat { * * @return true if successful, otherwise false (failed to invert matrix, or becomes z is infinity) */ + @SuppressWarnings("deprecation") public boolean gluUnProject4(final float winx, final float winy, final float winz, final float clipw, final FloatBuffer modelMatrix, final FloatBuffer projMatrix, final IntBuffer viewport, diff --git a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java index 4de05fc92..48222ea97 100644 --- a/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java +++ b/src/oculusvr/classes/jogamp/opengl/oculusvr/OVRUtil.java @@ -122,17 +122,11 @@ public class OVRUtil { } public static ovrFovPort getOVRFovPort(final FovHVHalves fovHVHalves) { final ovrFovPort tanHalfFov = ovrFovPort.create(); - if( fovHVHalves.inTangents ) { - tanHalfFov.setLeftTan(fovHVHalves.left); - tanHalfFov.setRightTan(fovHVHalves.right); - tanHalfFov.setUpTan(fovHVHalves.top); - tanHalfFov.setDownTan(fovHVHalves.bottom); - } else { - tanHalfFov.setLeftTan((float)Math.tan(fovHVHalves.left)); - tanHalfFov.setRightTan((float)Math.tan(fovHVHalves.right)); - tanHalfFov.setUpTan((float)Math.tan(fovHVHalves.top)); - tanHalfFov.setDownTan((float)Math.tan(fovHVHalves.bottom)); - } + final FovHVHalves fovHVHalvesTan = fovHVHalves.getInTangents(); + tanHalfFov.setLeftTan(fovHVHalvesTan.left); + tanHalfFov.setRightTan(fovHVHalvesTan.right); + tanHalfFov.setUpTan(fovHVHalvesTan.top); + tanHalfFov.setDownTan(fovHVHalvesTan.bottom); return tanHalfFov; } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java index c4db20f37..b33b18358 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/stereo/StereoDemo01.java @@ -237,7 +237,9 @@ public class StereoDemo01 { // EyePos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, EyePos.y); final FovHVHalves[] defaultEyeFov = stereoDevice.getDefaultFOV(); System.err.println("Default Fov[0]: "+defaultEyeFov[0]); + System.err.println("Default Fov[0]: "+defaultEyeFov[0].toStringInDegrees()); System.err.println("Default Fov[1]: "+defaultEyeFov[1]); + System.err.println("Default Fov[1]: "+defaultEyeFov[1].toStringInDegrees()); final float[] eyePositionOffset = null == movieSimple ? StereoDevice.DEFAULT_EYE_POSITION_OFFSET // default : new float[] { 0f, 0.3f, 0f }; // better fixed movie position -- cgit v1.2.3