private void UpdateFieldOfView(FieldOfView leftEyeFov, FieldOfView rightEyeFov) { CardboardDeviceParams cdp = mHmd.getCardboard(); ScreenParams screen = mHmd.getScreen(); Distortion distortion = cdp.getDistortion(); float idealFovAngle = (float)Math.ToDegrees(Math.Atan2(cdp.getLensDiameter() / 2.0F, cdp.getEyeToLensDistance())); float eyeToScreenDist = cdp.getEyeToLensDistance() + cdp.getScreenToLensDistance(); float outerDist = (screen.getWidthMeters() - cdp.getInterpupillaryDistance()) / 2.0F; float innerDist = cdp.getInterpupillaryDistance() / 2.0F; float bottomDist = cdp.getVerticalDistanceToLensCenter() - screen.getBorderSizeMeters(); float topDist = screen.getHeightMeters() + screen.getBorderSizeMeters() - cdp.getVerticalDistanceToLensCenter(); float outerAngle = (float)Math.ToDegrees(Math.Atan2(distortion.distort(outerDist), eyeToScreenDist)); float innerAngle = (float)Math.ToDegrees(Math.Atan2(distortion.distort(innerDist), eyeToScreenDist)); float bottomAngle = (float)Math.ToDegrees(Math.Atan2(distortion.distort(bottomDist), eyeToScreenDist)); float topAngle = (float)Math.ToDegrees(Math.Atan2(distortion.distort(topDist), eyeToScreenDist)); leftEyeFov.setLeft(Math.Min(outerAngle, idealFovAngle)); leftEyeFov.setRight(Math.Min(innerAngle, idealFovAngle)); leftEyeFov.setBottom(Math.Min(bottomAngle, idealFovAngle)); leftEyeFov.setTop(Math.Min(topAngle, idealFovAngle)); rightEyeFov.setLeft(Math.Min(innerAngle, idealFovAngle)); rightEyeFov.setRight(Math.Min(outerAngle, idealFovAngle)); rightEyeFov.setBottom(Math.Min(bottomAngle, idealFovAngle)); rightEyeFov.setTop(Math.Min(topAngle, idealFovAngle)); }
public void onProjectionChanged(HeadMountedDisplay hmd, EyeParams leftEye, EyeParams rightEye, float zNear, float zFar) { mHmd = new HeadMountedDisplay(hmd); mLeftEyeFov = new FieldOfView(leftEye.getFov()); mRightEyeFov = new FieldOfView(rightEye.getFov()); ScreenParams screen = mHmd.getScreen(); CardboardDeviceParams cdp = mHmd.getCardboard(); if (mProgramHolder == null) { mProgramHolder = createProgramHolder(); } EyeViewport leftEyeViewport = initViewportForEye(leftEye, 0.0F); EyeViewport rightEyeViewport = initViewportForEye(rightEye, leftEyeViewport.width); leftEye.getFov().toPerspectiveMatrix(zNear, zFar, leftEye.getTransform().GetPerspective(), 0); rightEye.getFov().toPerspectiveMatrix(zNear, zFar, rightEye.getTransform().GetPerspective(), 0); float textureWidthM = leftEyeViewport.width + rightEyeViewport.width; float textureHeightM = Math.Max(leftEyeViewport.height, rightEyeViewport.height); float xPxPerM = screen.getWidth() / screen.getWidthMeters(); float yPxPerM = screen.getHeight() / screen.getHeightMeters(); int textureWidthPx = Math.Round(textureWidthM * xPxPerM); int textureHeightPx = Math.Round(textureHeightM * yPxPerM); float xEyeOffsetMScreen = screen.getWidthMeters() / 2.0F - cdp.getInterpupillaryDistance() / 2.0F; float yEyeOffsetMScreen = cdp.getVerticalDistanceToLensCenter() - screen.getBorderSizeMeters(); mLeftEyeDistortionMesh = createDistortionMesh(leftEye, leftEyeViewport, textureWidthM, textureHeightM, xEyeOffsetMScreen, yEyeOffsetMScreen); xEyeOffsetMScreen = screen.getWidthMeters() - xEyeOffsetMScreen; mRightEyeDistortionMesh = createDistortionMesh(rightEye, rightEyeViewport, textureWidthM, textureHeightM, xEyeOffsetMScreen, yEyeOffsetMScreen); setupRenderTextureAndRenderbuffer(textureWidthPx, textureHeightPx); }
public void OnDrawFrame(IGL10 gl) { if ((mShuttingDown) || (mInvalidSurfaceSize)) { return; } ScreenParams screen = mHmd.getScreen(); CardboardDeviceParams cdp = mHmd.getCardboard(); mView.mHeadTracker.getLastHeadView(mHeadTransform.getHeadView(), 0); float halfInterpupillaryDistance = cdp.getInterpupillaryDistance() * 0.5F; if (mVRMode) { Android.Opengl.Matrix.SetIdentityM(mLeftEyeTranslate, 0); Android.Opengl.Matrix.SetIdentityM(mRightEyeTranslate, 0); Android.Opengl.Matrix.TranslateM(mLeftEyeTranslate, 0, halfInterpupillaryDistance, 0.0F, 0.0F); Android.Opengl.Matrix.TranslateM(mRightEyeTranslate, 0, -halfInterpupillaryDistance, 0.0F, 0.0F); Android.Opengl.Matrix.MultiplyMM(mLeftEye.getTransform().GetEyeView(), 0, mLeftEyeTranslate, 0, mHeadTransform.getHeadView(), 0); Android.Opengl.Matrix.MultiplyMM(mRightEye.getTransform().GetEyeView(), 0, mRightEyeTranslate, 0, mHeadTransform.getHeadView(), 0); } else { //Java.Lang.JavaSystem.Arraycopy(mHeadTransform.getHeadView(), 0, mMonocular.getTransform().GetEyeView(), 0, mHeadTransform.getHeadView().Length); Array.Copy(mHeadTransform.getHeadView(), 0, mMonocular.getTransform().GetEyeView(), 0, mHeadTransform.getHeadView().Length); } if (mProjectionChanged) { mMonocular.getViewport().setViewport(0, 0, screen.getWidth(), screen.getHeight()); if (!mVRMode) { float aspectRatio = screen.getWidth() / screen.getHeight(); Android.Opengl.Matrix.PerspectiveM(mMonocular.getTransform().GetPerspective(), 0, cdp.getFovY(), aspectRatio, mZNear, mZFar); } else if (mDistortionCorrectionEnabled) { UpdateFieldOfView(mLeftEye.getFov(), mRightEye.getFov()); mView.mDistortionRenderer.onProjectionChanged(mHmd, mLeftEye, mRightEye, mZNear, mZFar); } else { float distEyeToScreen = cdp.getVisibleViewportSize() / 2.0F / (float)Math.Tan(Math.ToRadians(cdp.getFovY()) / 2.0D); float left = screen.getWidthMeters() / 2.0F - halfInterpupillaryDistance; float right = halfInterpupillaryDistance; float bottom = cdp.getVerticalDistanceToLensCenter() - screen.getBorderSizeMeters(); float top = screen.getBorderSizeMeters() + screen.getHeightMeters() - cdp.getVerticalDistanceToLensCenter(); FieldOfView leftEyeFov = mLeftEye.getFov(); leftEyeFov.setLeft((float)Math.ToDegrees(Math.Atan2(left, distEyeToScreen))); leftEyeFov.setRight((float)Math.ToDegrees(Math.Atan2(right, distEyeToScreen))); leftEyeFov.setBottom((float)Math.ToDegrees(Math.Atan2(bottom, distEyeToScreen))); leftEyeFov.setTop((float)Math.ToDegrees(Math.Atan2(top, distEyeToScreen))); FieldOfView rightEyeFov = mRightEye.getFov(); rightEyeFov.setLeft(leftEyeFov.getRight()); rightEyeFov.setRight(leftEyeFov.getLeft()); rightEyeFov.setBottom(leftEyeFov.getBottom()); rightEyeFov.setTop(leftEyeFov.getTop()); leftEyeFov.toPerspectiveMatrix(mZNear, mZFar, mLeftEye.getTransform().GetPerspective(), 0); rightEyeFov.toPerspectiveMatrix(mZNear, mZFar, mRightEye.getTransform().GetPerspective(), 0); mLeftEye.getViewport().setViewport(0, 0, screen.getWidth() / 2, screen.getHeight()); mRightEye.getViewport().setViewport(screen.getWidth() / 2, 0, screen.getWidth() / 2, screen.getHeight()); } mProjectionChanged = false; } if (mVRMode) { if (mDistortionCorrectionEnabled) { mView.mDistortionRenderer.beforeDrawFrame(); if (mDistortionCorrectionScale == 1.0F) { mRenderer.OnDrawFrame(mHeadTransform, mLeftEye, mRightEye); } else { int leftX = mLeftEye.getViewport().x; int leftY = mLeftEye.getViewport().y; int leftWidth = mLeftEye.getViewport().width; int leftHeight = mLeftEye.getViewport().height; int rightX = mRightEye.getViewport().x; int rightY = mRightEye.getViewport().y; int rightWidth = mRightEye.getViewport().width; int rightHeight = mRightEye.getViewport().height; mLeftEye.getViewport().setViewport((int)(leftX * mDistortionCorrectionScale), (int)(leftY * mDistortionCorrectionScale), (int)(leftWidth * mDistortionCorrectionScale), (int)(leftHeight * mDistortionCorrectionScale)); mRightEye.getViewport().setViewport((int)(rightX * mDistortionCorrectionScale), (int)(rightY * mDistortionCorrectionScale), (int)(rightWidth * mDistortionCorrectionScale), (int)(rightHeight * mDistortionCorrectionScale)); mRenderer.OnDrawFrame(mHeadTransform, mLeftEye, mRightEye); mLeftEye.getViewport().setViewport(leftX, leftY, leftWidth, leftHeight); mRightEye.getViewport().setViewport(rightX, rightY, rightWidth, rightHeight); } mView.mDistortionRenderer.afterDrawFrame(); } else { mRenderer.OnDrawFrame(mHeadTransform, mLeftEye, mRightEye); } } else { mRenderer.OnDrawFrame(mHeadTransform, mMonocular, null); } mRenderer.OnFinishFrame(mMonocular.getViewport()); }