All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jogamp.opengl.oculusvr.OVRStereoDevice Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2014 JogAmp Community. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice, this list of
 *       conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list
 *       of conditions and the following disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are those of the
 * authors and should not be interpreted as representing official policies, either expressed
 * or implied, of JogAmp Community.
 */
package jogamp.opengl.oculusvr;

import com.jogamp.nativewindow.util.Dimension;
import com.jogamp.nativewindow.util.DimensionImmutable;
import com.jogamp.nativewindow.util.PointImmutable;
import com.jogamp.nativewindow.util.Rectangle;
import com.jogamp.nativewindow.util.RectangleImmutable;
import com.jogamp.oculusvr.OVR;
import com.jogamp.oculusvr.OvrHmdContext;
import com.jogamp.oculusvr.ovrEyeRenderDesc;
import com.jogamp.oculusvr.ovrFovPort;
import com.jogamp.oculusvr.ovrHmdDesc;
import com.jogamp.oculusvr.ovrSizei;
import com.jogamp.oculusvr.ovrTrackingState;
import com.jogamp.opengl.math.FovHVHalves;
import com.jogamp.opengl.math.geom.Frustum;
import com.jogamp.opengl.util.stereo.LocationSensorParameter;
import com.jogamp.opengl.util.stereo.StereoDevice;
import com.jogamp.opengl.util.stereo.StereoDeviceFactory;
import com.jogamp.opengl.util.stereo.StereoDeviceRenderer;
import com.jogamp.opengl.util.stereo.StereoUtil;

public class OVRStereoDevice implements StereoDevice {
    /** 1.6 up, 5 forward */
    private static final float[] DEFAULT_EYE_POSITION_OFFSET = { 0.0f, 1.6f, -5.0f };

    private final StereoDeviceFactory factory;
    public final int deviceIndex;
    private final FovHVHalves[] defaultEyeFov;

    public ovrHmdDesc hmdDesc;
    public OvrHmdContext handle;

    private final int supportedSensorBits;
    private int usedSensorBits;
    private boolean sensorsStarted = false;

    private final int[] eyeRenderOrder;
    private final int supportedDistortionBits, recommendedDistortionBits, minimumDistortionBits;

    private final String deviceName;
    private final DimensionImmutable resolution;
    private final int requiredRotation;
    private final PointImmutable position;
    private final int dkVersion;

    private final LocationSensorParameter locationSensorParams;

    public OVRStereoDevice(final StereoDeviceFactory factory, final ovrHmdDesc hmdDesc, final int deviceIndex) {
        if( null == hmdDesc ) {
            throw new IllegalArgumentException("Passed null hmdDesc");
        }
        final OvrHmdContext nativeContext = hmdDesc.getHandle();
        if( null == nativeContext ) {
            throw new IllegalArgumentException("hmdDesc has null OvrHmdContext");
        }
        this.factory = factory;
        this.handle = nativeContext;
        this.deviceIndex = deviceIndex;
        this.hmdDesc = hmdDesc;

        final ovrFovPort[] defaultOVREyeFov = hmdDesc.getDefaultEyeFov(0, new ovrFovPort[ovrHmdDesc.getEyeRenderOrderArrayLength()]);
        defaultEyeFov = new FovHVHalves[defaultOVREyeFov.length];
        for(int i=0; i now["+StereoUtil.sensorBitsToString(usedSensorBits)+"]");
            }
        }
    }

    @Override
    public final boolean startSensors(final int desiredSensorBits, final int requiredSensorBits) {
        if( isValid() && !sensorsStarted ) {
            if( requiredSensorBits != ( supportedSensorBits & requiredSensorBits ) ) {
                // required sensors not available
                if( StereoDevice.DEBUG ) {
                    System.err.println("XXX: startSensors failed: n/a required sensors ["+StereoUtil.sensorBitsToString(requiredSensorBits)+"]");
                }
                return false;
            }
            if( 0 == ( supportedSensorBits & ( requiredSensorBits | desiredSensorBits ) ) ) {
                // no sensors available
                if( StereoDevice.DEBUG ) {
                    System.err.println("XXX: startSensors failed: n/a any sensors");
                }
                return false;
            }
            // Start the sensor which provides the Rift’s pose and motion.
            final int requiredTrackingCaps = OVRUtil.sensorBits2TrackingCaps(requiredSensorBits);
            final int desiredTrackingCaps = requiredTrackingCaps | OVRUtil.sensorBits2TrackingCaps(desiredSensorBits);
            final boolean res;
            if( OVR.ovrHmd_ConfigureTracking(hmdDesc, desiredTrackingCaps, requiredTrackingCaps) ) {
                sensorsStarted = true;
                updateUsedSensorBits(OVR.ovrHmd_GetTrackingState(hmdDesc, 0.0));
                res = true;
            } else {
                res = false;
            }
            if( StereoDevice.DEBUG ) {
                System.err.println("XXX: startSensors: "+res+", started "+sensorsStarted+
                        ": required["+StereoUtil.sensorBitsToString(requiredSensorBits)+"]"+
                        ", desired["+StereoUtil.sensorBitsToString(desiredSensorBits)+"]"+
                        ", enabled["+StereoUtil.sensorBitsToString(usedSensorBits)+"]");
            }
            return res;
        } else {
            // No state change -> Success
            return true;
        }
    }
    @Override
    public final boolean stopSensors() {
        if( isValid() && sensorsStarted ) {
            OVR.ovrHmd_ConfigureTracking(hmdDesc, 0, 0); // STOP
            sensorsStarted = false;
            usedSensorBits = 0;
            return true;
        } else {
            // No state change -> Success
            return true;
        }
    }
    @Override
    public final boolean getSensorsStarted() { return sensorsStarted; }

    @Override
    public final int getSupportedSensorBits() {
        return supportedSensorBits;
    }

    @Override
    public final int getEnabledSensorBits() {
        return usedSensorBits;
    }

    @Override
    public final int[] getEyeRenderOrder() {
        return eyeRenderOrder;
    }

    @Override
    public final int getSupportedDistortionBits() {
        return supportedDistortionBits;
    };

    @Override
    public final int getRecommendedDistortionBits() {
        return recommendedDistortionBits;
    }

    @Override
    public final int getMinimumDistortionBits() {
        return minimumDistortionBits;
    }

    @Override
    public final StereoDeviceRenderer createRenderer(final int distortionBits,
                                                     final int textureCount, final float[] eyePositionOffset,
                                                     final FovHVHalves[] eyeFov, final float pixelsPerDisplayPixel, final int textureUnit) {
        final ovrFovPort ovrEyeFov0 = OVRUtil.getOVRFovPort(eyeFov[0]);
        final ovrFovPort ovrEyeFov1 = OVRUtil.getOVRFovPort(eyeFov[1]);

        final ovrEyeRenderDesc[] eyeRenderDesc = new ovrEyeRenderDesc[2];
        eyeRenderDesc[0] = OVR.ovrHmd_GetRenderDesc(hmdDesc, OVR.ovrEye_Left, ovrEyeFov0);
        eyeRenderDesc[1] = OVR.ovrHmd_GetRenderDesc(hmdDesc, OVR.ovrEye_Right, ovrEyeFov1);
        if( StereoDevice.DEBUG ) {
            System.err.println("XXX: eyeRenderDesc[0] "+OVRUtil.toString(eyeRenderDesc[0]));
            System.err.println("XXX: eyeRenderDesc[1] "+OVRUtil.toString(eyeRenderDesc[1]));
        }

        final DimensionImmutable eye0TextureSize = OVRUtil.getOVRSizei(OVR.ovrHmd_GetFovTextureSize(hmdDesc, OVR.ovrEye_Left,  eyeRenderDesc[0].getFov(), pixelsPerDisplayPixel));
        final DimensionImmutable eye1TextureSize = OVRUtil.getOVRSizei(OVR.ovrHmd_GetFovTextureSize(hmdDesc, OVR.ovrEye_Right, eyeRenderDesc[1].getFov(), pixelsPerDisplayPixel));
        if( StereoDevice.DEBUG ) {
            System.err.println("XXX: recommenedTex0Size "+eye0TextureSize);
            System.err.println("XXX: recommenedTex1Size "+eye1TextureSize);
        }
        // final int maxWidth = Math.max(eye0TextureSize.getWidth(), eye1TextureSize.getWidth());
        final int maxHeight = Math.max(eye0TextureSize.getHeight(), eye1TextureSize.getHeight());

        final DimensionImmutable[] eyeTextureSizes = new DimensionImmutable[] { eye0TextureSize, eye1TextureSize };
        final DimensionImmutable totalTextureSize = new Dimension(eye0TextureSize.getWidth() + eye1TextureSize.getWidth(), maxHeight);
        if( StereoDevice.DEBUG ) {
            System.err.println("XXX: textureSize Single "+eyeTextureSizes);
            System.err.println("XXX: textureSize Total  "+totalTextureSize);
        }

        final RectangleImmutable[] eyeViewports = new RectangleImmutable[2];
        if( 1 == textureCount ) { // validated in ctor below!
            // one big texture/FBO, viewport to target space
            eyeViewports[0] = new Rectangle(0, 0,
                                            eye0TextureSize.getWidth(),
                                            maxHeight);
            eyeViewports[1] = new Rectangle(eye0TextureSize.getWidth(), 0,
                                            eye1TextureSize.getWidth(),
                                            maxHeight);
        } else {
            // two textures/FBOs w/ postprocessing, which renders textures/FBOs into target space
            eyeViewports[0] = new Rectangle(0, 0,
                                            eye0TextureSize.getWidth(),
                                            eye0TextureSize.getHeight());
            eyeViewports[1] = new Rectangle(0, 0,
                                            eye1TextureSize.getWidth(),
                                            eye1TextureSize.getHeight());
        }
        return new OVRStereoDeviceRenderer(this, distortionBits, textureCount, eyePositionOffset,
                                           eyeRenderDesc, eyeTextureSizes, totalTextureSize, eyeViewports, textureUnit);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy