com.mtbs3d.minecrift.MCOculus.java Source code

Java tutorial

Introduction

Here is the source code for com.mtbs3d.minecrift.MCOculus.java

Source

/**
 * Copyright 2013 Mark Browning, StellaArtois
 * Licensed under the LGPL 3.0 or later (See LICENSE.md for details)
 */
package com.mtbs3d.minecrift;

import com.mtbs3d.minecrift.api.*;

import de.fruitfly.ovr.EyeRenderParams;
import de.fruitfly.ovr.IOculusRift;
import de.fruitfly.ovr.OculusRift;
import de.fruitfly.ovr.UserProfileData;
import de.fruitfly.ovr.enums.EyeType;
import de.fruitfly.ovr.structs.*;
import net.minecraft.util.Vec3;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.util.vector.Quaternion;

public class MCOculus extends OculusRift //OculusRift does most of the heavy lifting 
        implements IEyePositionProvider, IOrientationProvider, IBasePlugin, IHMDInfo, IStereoProvider,
        IEventNotifier, IEventListener {

    public static final int NOT_CALIBRATING = 0;
    public static final int CALIBRATE_AWAITING_FIRST_ORIGIN = 1;
    public static final int CALIBRATE_AT_FIRST_ORIGIN = 2;
    public static final int CALIBRATE_COOLDOWN = 7;

    public static final long COOLDOWNTIME_MS = 1000L;

    private boolean isCalibrated = false;
    private long coolDownStart = 0L;
    private int calibrationStep = NOT_CALIBRATING;
    private int MagCalSampleCount = 0;
    private boolean forceMagCalibration = false; // Don't force mag cal initially
    private FrameTiming frameTiming = new FrameTiming();

    @Override
    public EyeType eyeRenderOrder(int index) {
        HmdDesc desc = getHMDInfo();
        if (index < 0 || index >= desc.EyeRenderOrder.length)
            return EyeType.ovrEye_Left;

        return desc.EyeRenderOrder[index];
    }

    @Override
    public boolean usesDistortion() {
        return true;
    }

    @Override
    public boolean isStereo() {
        return true;
    }

    @Override
    public boolean isGuiOrtho() {
        return false;
    }

    public FrameTiming getFrameTiming() {
        return frameTiming;
    };

    public static UserProfileData theProfileData = null;

    public void beginFrame() {
        frameTiming = super.beginFrameGetTiming();
    }

    public Posef beginEyeRender(EyeType eye) {
        return super.beginEyeRender(eye);
    }

    public Matrix4f getMatrix4fProjection(FovPort fov, float nearClip, float farClip) {
        return super.getMatrix4fProjection(fov, nearClip, farClip);
    }

    public void endEyeRender(EyeType eye) {
        super.endEyeRender(eye);
    }

    public void endFrame() {
        GL11.glDisable(GL11.GL_CULL_FACE); // Oculus wants CW orientations, avoid the problem by turning off culling...
        GL11.glDisable(GL11.GL_DEPTH_TEST); // Nothing is drawn with depth test on...

        // End the frame
        super.endFrame();

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); // Unbind GL_ARRAY_BUFFER for my own vertex arrays to work...
        GL11.glEnable(GL11.GL_CULL_FACE); // Turn back on...
        GL11.glEnable(GL11.GL_DEPTH_TEST); // Turn back on...
        GL11.glClearDepth(1); // Oculus set this to 0 (the near plane), return to normal...
        ARBShaderObjects.glUseProgramObjectARB(0); // Oculus shader is still active, turn it off...

        Display.processMessages();
    }

    @Override
    public HmdDesc getHMDInfo() {
        HmdDesc hmdDesc = new HmdDesc();
        if (isInitialized())
            hmdDesc = getHmdDesc();

        return hmdDesc;
    }

    @Override
    public String getName() {
        return "Oculus";
    }

    @Override
    public String getID() {
        return "oculus";
    }

    @Override
    public void update(float ipd, float yawHeadDegrees, float pitchHeadDegrees, float rollHeadDegrees,
            float worldYawOffsetDegrees, float worldPitchOffsetDegrees, float worldRollOffsetDegrees) {
        // TODO:
    }

    @Override
    public Vec3 getCenterEyePosition() {
        return null;
    }

    @Override
    public Vec3 getEyePosition(EyeType eye) {
        return super.getEyePosition(eye);
    }

    @Override
    public void resetOrigin() {
        // TODO:
    }

    @Override
    public void resetOriginRotation() {
        // TODO:
    }

    @Override
    public void setPrediction(float delta, boolean enable) {
        // TODO: Ignored for now
    }

    @Override
    public void beginAutomaticCalibration() {
        if (isInitialized())
            processCalibration();
    }

    @Override
    public void updateAutomaticCalibration() {
        if (isInitialized())
            processCalibration();
    }

    @Override
    public boolean isCalibrated() {
        if (!isInitialized())
            return true; // Return true if not initialised

        return isCalibrated;
    }

    @Override
    public String getCalibrationStep() {
        String step = "";

        switch (calibrationStep) {
        case CALIBRATE_AWAITING_FIRST_ORIGIN: {
            step = "Look ahead and press SPACEBAR";
            break;
        }
        case CALIBRATE_AT_FIRST_ORIGIN:
        case CALIBRATE_COOLDOWN: {
            step = "Done!";
            break;
        }
        }

        return step;
    }

    @Override
    public void eventNotification(int eventId) {
        switch (eventId) {
        case IOrientationProvider.EVENT_ORIENTATION_AT_ORIGIN: {
            if (calibrationStep == CALIBRATE_AWAITING_FIRST_ORIGIN) {
                calibrationStep = CALIBRATE_AT_FIRST_ORIGIN;
                processCalibration();
            }
            break;
        }
        case IBasePlugin.EVENT_CALIBRATION_SET_ORIGIN: {
            resetOrigin();
        }
        }
    }

    @Override
    public synchronized void registerListener(IEventListener listener) {
        listeners.add(listener);
    }

    @Override
    public synchronized void notifyListeners(int eventId) {
        for (IEventListener listener : listeners) {
            if (listener != null)
                listener.eventNotification(eventId);
        }
    }

    private void processCalibration() {
        switch (calibrationStep) {
        case NOT_CALIBRATING: {
            calibrationStep = CALIBRATE_AWAITING_FIRST_ORIGIN;
            isCalibrated = false;
            break;
        }
        case CALIBRATE_AT_FIRST_ORIGIN: {
            //_reset();

            // Calibration of Mag cal is now handled solely by the Oculus config utility.

            MagCalSampleCount = 0;
            coolDownStart = System.currentTimeMillis();
            calibrationStep = CALIBRATE_COOLDOWN;
            resetOrigin();
            notifyListeners(IBasePlugin.EVENT_CALIBRATION_SET_ORIGIN);

            break;
        }
        case CALIBRATE_COOLDOWN: {
            if ((System.currentTimeMillis() - coolDownStart) > COOLDOWNTIME_MS) {
                coolDownStart = 0;
                calibrationStep = NOT_CALIBRATING;
                isCalibrated = true;
            }
            break;
        }
        }
    }

    @Override
    public void poll(/*EyeType eyeHint, */float delta) {
        // Do nothing
    }

    @Override
    public float getHeadYawDegrees() {
        return 0.0f;//getYawDegrees_LH();
    }

    @Override
    public float getHeadPitchDegrees() {
        return 0.0f;//getPitchDegrees_LH();
    }

    @Override
    public float getHeadRollDegrees() {
        return 0.0f;//getRollDegrees_LH();
    }

    @Override
    public Quaternion getOrientationQuaternion() {
        Quatf orient = Quatf.IDENTITY;//super.getOrientQuatf();

        // Needs x, y, z, w
        return new Quaternion(orient.x, orient.y, orient.z, orient.w);
    }

    @Override
    public UserProfileData getProfileData() {
        UserProfileData userProfile = null;

        if (isInitialized()) {
            //userProfile = _getUserProfileData();   // TODO: Profiles
        }

        return userProfile;
    }

    @Override
    public String[] getUserProfiles() {
        String[] profileNames = null;

        if (isInitialized()) {
            //profileNames = _getUserProfiles();    // TODO: Profiles
        }

        return profileNames;
    }

    @Override
    public boolean loadProfile(String profileName) {
        if (!isInitialized())
            return false;

        return false;//_loadUserProfile(profileName);     // TODO: Profiles
    }

    public EyeRenderParams getEyeRenderParams(int viewPortWidth, int viewPortHeight) {
        return null;
    }

    public EyeRenderParams getEyeRenderParams(int viewPortX, int viewPortY, int viewPortWidth, int viewPortHeight,
            float nearClip, float farClip) {
        return null;
    }

    public EyeRenderParams getEyeRenderParams(int viewPortX, int viewPortY, int viewPortWidth, int viewPortHeight,
            float clipNear, float clipFar, float eyeToScreenDistanceScaleFactor, float lensSeparationScaleFactor) {
        return null;
    }

    public EyeRenderParams getEyeRenderParams(int viewPortX, int viewPortY, int viewPortWidth, int viewPortHeight,
            float clipNear, float clipFar, float eyeToScreenDistanceScaleFactor, float lensSeparationScaleFactor,
            float distortionFitX, float distortionFitY, IOculusRift.AspectCorrectionType aspectCorrectionType) {
        return null;
    }
}