| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- /*
- * Copyright (c) 2009-2017 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * 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.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "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 THE COPYRIGHT OWNER 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.
- */
- package com.jme3.util;
- import com.jme3.app.VREnvironment;
- import com.jme3.input.vr.OculusVR;
- import com.jme3.input.vr.VRAPI;
- import com.jme3.math.ColorRGBA;
- import com.jme3.math.Quaternion;
- import com.jme3.math.Vector2f;
- import com.jme3.math.Vector3f;
- import com.jme3.renderer.Camera;
- import com.jme3.renderer.ViewPort;
- import com.jme3.scene.Spatial;
- import com.jme3.texture.*;
- import java.nio.IntBuffer;
- import java.util.Iterator;
- import java.util.logging.Logger;
- import org.lwjgl.ovr.*;
- import static org.lwjgl.ovr.OVR.*;
- import static org.lwjgl.ovr.OVRErrorCode.*;
- /**
- * A rendering system for Oculus's LibOVR API.
- *
- * @author Campbell Suter <[email protected]>
- */
- public class VRViewManagerOculus extends AbstractVRViewManager {
- private static final Logger LOG = Logger.getLogger(VRViewManagerOculus.class.getName());
- private final VREnvironment environment;
- private final OculusVR hardware;
- // Copied from OSVR
- //final & temp values for camera calculations
- private final Vector3f finalPosition = new Vector3f();
- private final Quaternion finalRotation = new Quaternion();
- private final Vector3f hmdPos = new Vector3f();
- private final Quaternion hmdRot = new Quaternion();
- public VRViewManagerOculus(VREnvironment environment) {
- this.environment = environment;
- VRAPI hardware = environment.getVRHardware();
- if (!(hardware instanceof OculusVR)) {
- throw new IllegalStateException("Cannot use Oculus VR view manager on non-Oculus hardware state!");
- }
- this.hardware = (OculusVR) hardware;
- if (!environment.compositorAllowed()) {
- throw new UnsupportedOperationException("Cannot render without compositor on LibOVR");
- }
- }
- @Override
- public void initialize() {
- setupCamerasAndViews();
- }
- private long session() {
- return hardware.getSessionPointer();
- }
- @Override
- public void update(float tpf) {
- // TODO
- hardware.updatePose();
- // TODO deduplicate
- if (environment != null) {
- // grab the observer
- Object obs = environment.getObserver();
- Quaternion objRot;
- Vector3f objPos;
- if (obs instanceof Camera) {
- objRot = ((Camera) obs).getRotation();
- objPos = ((Camera) obs).getLocation();
- } else {
- objRot = ((Spatial) obs).getWorldRotation();
- objPos = ((Spatial) obs).getWorldTranslation();
- }
- // grab the hardware handle
- VRAPI dev = environment.getVRHardware();
- if (dev != null) {
- // update the HMD's position & orientation
- dev.getPositionAndOrientation(hmdPos, hmdRot);
- if (obs != null) {
- // update hmdPos based on obs rotation
- finalRotation.set(objRot);
- finalRotation.mult(hmdPos, hmdPos);
- finalRotation.multLocal(hmdRot);
- }
- finalizeCamera(dev.getHMDVectorPoseLeftEye(), objPos, leftCamera);
- finalizeCamera(dev.getHMDVectorPoseRightEye(), objPos, rightCamera);
- } else {
- leftCamera.setFrame(objPos, objRot);
- rightCamera.setFrame(objPos, objRot);
- }
- if (environment.hasTraditionalGUIOverlay()) {
- // update the mouse?
- environment.getVRMouseManager().update(tpf);
- // update GUI position?
- if (environment.getVRGUIManager().wantsReposition || environment.getVRGUIManager().getPositioningMode() != VRGUIPositioningMode.MANUAL) {
- environment.getVRGUIManager().positionGuiNow(tpf);
- environment.getVRGUIManager().updateGuiQuadGeometricState();
- }
- }
- } else {
- throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
- }
- }
- /**
- * Place the camera within the scene.
- *
- * @param eyePos the eye position.
- * @param obsPosition the observer position.
- * @param cam the camera to place.
- */
- private void finalizeCamera(Vector3f eyePos, Vector3f obsPosition, Camera cam) {
- finalRotation.mult(eyePos, finalPosition);
- finalPosition.addLocal(hmdPos);
- if (obsPosition != null) {
- finalPosition.addLocal(obsPosition);
- }
- finalPosition.y += getHeightAdjustment();
- cam.setFrame(finalPosition, finalRotation);
- }
- @Override
- public void render() {
- for (int eye = 0; eye < 2; eye++) {
- // TODO do we need this? Don't we set the camera positions ourselves?
- OVRPosef eyePose = hardware.getEyePosesPtr()[eye];
- hardware.getLayer0().RenderPose(eye, eyePose);
- IntBuffer currentIndexB = BufferUtils.createIntBuffer(1);
- ovr_GetTextureSwapChainCurrentIndex(session(), hardware.getChain(), currentIndexB);
- int index = currentIndexB.get();
- (eye == ovrEye_Left ? leftViewPort : rightViewPort).setOutputFrameBuffer(hardware.getFramebuffers()[index]);
- }
- // Now the game will render into the buffers given to us by LibOVR
- }
- @Override
- public void postRender() {
- // We're done with our textures now - the game is done drawing into them.
- ovr_CommitTextureSwapChain(session(), hardware.getChain());
- // Send the result to the HMD
- int result = ovr_SubmitFrame(session(), 0, null, hardware.getLayers());
- if (result != ovrSuccess) {
- throw new IllegalStateException("Failed to submit frame!");
- }
- }
- /*
- *********************************************************
- * Show's over, now it's just boring camera stuff etc. *
- *********************************************************
- */
- /**
- * Set up the cameras and views for each eye and the mirror display.
- */
- private void setupCamerasAndViews() {
- // TODO: Use LobOVR IPD etc
- if (environment != null) {
- // get desired frustrum from original camera
- Camera origCam = environment.getCamera();
- float fFar = origCam.getFrustumFar();
- float fNear = origCam.getFrustumNear();
- // restore frustrum on distortion scene cam, if needed
- if (environment.isInstanceRendering()) {
- leftCamera = origCam;
- } else if (environment.compositorAllowed() == false) {
- origCam.setFrustumFar(100f);
- origCam.setFrustumNear(1f);
- leftCamera = origCam.clone();
- prepareCameraSize(origCam, 2f);
- } else {
- leftCamera = origCam.clone();
- }
- getLeftCamera().setFrustumPerspective(environment.getDefaultFOV(), environment.getDefaultAspect(), fNear, fFar);
- prepareCameraSize(getLeftCamera(), 1f);
- if (environment.getVRHardware() != null) {
- getLeftCamera().setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionLeftEye(getLeftCamera()));
- }
- //org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER_SRGB);
- if (!environment.isInstanceRendering()) {
- leftViewPort = setupViewBuffers(getLeftCamera(), LEFT_VIEW_NAME);
- rightCamera = getLeftCamera().clone();
- if (environment.getVRHardware() != null) {
- getRightCamera().setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionRightEye(getRightCamera()));
- }
- rightViewPort = setupViewBuffers(getRightCamera(), RIGHT_VIEW_NAME);
- } else if (environment.getApplication() != null) {
- LOG.severe("THIS CODE NEED CHANGES !!!");
- leftViewPort = environment.getApplication().getViewPort();
- //leftViewport.attachScene(app.getRootNode());
- rightCamera = getLeftCamera().clone();
- if (environment.getVRHardware() != null) {
- getRightCamera().setProjectionMatrix(environment.getVRHardware().getHMDMatrixProjectionRightEye(getRightCamera()));
- }
- org.lwjgl.opengl.GL11.glEnable(org.lwjgl.opengl.GL30.GL_CLIP_DISTANCE0);
- //FIXME: [jme-vr] Fix with JMonkey next release
- //RenderManager._VRInstancing_RightCamProjection = camRight.getViewProjectionMatrix();
- // TODO: Add LibOVR support
- // setupFinalFullTexture(environment.getApplication().getViewPort().getCamera());
- } else {
- throw new IllegalStateException("This VR environment is not attached to any application.");
- }
- // setup gui
- environment.getVRGUIManager().setupGui(getLeftCamera(), getRightCamera(), getLeftViewPort(), getRightViewPort());
- if (environment.getVRHardware() != null) {
- // call these to cache the results internally
- environment.getVRHardware().getHMDMatrixPoseLeftEye();
- environment.getVRHardware().getHMDMatrixPoseRightEye();
- }
- } else {
- throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
- }
- }
- private void prepareCameraSize(Camera cam, float xMult) {
- // TODO this function is identical to that in VRViewManagerOpenVR; merge the two.
- if (environment != null) {
- if (environment.getApplication() != null) {
- Vector2f size = new Vector2f();
- VRAPI vrhmd = environment.getVRHardware();
- if (vrhmd == null) {
- size.x = 1280f;
- size.y = 720f;
- } else {
- vrhmd.getRenderSize(size);
- }
- if (size.x < environment.getApplication().getContext().getSettings().getWidth()) {
- size.x = environment.getApplication().getContext().getSettings().getWidth();
- }
- if (size.y < environment.getApplication().getContext().getSettings().getHeight()) {
- size.y = environment.getApplication().getContext().getSettings().getHeight();
- }
- if (environment.isInstanceRendering()) {
- size.x *= 2f;
- }
- // other adjustments
- size.x *= xMult;
- size.x *= getResolutionMuliplier();
- size.y *= getResolutionMuliplier();
- if (cam.getWidth() != size.x || cam.getHeight() != size.y) {
- cam.resize((int) size.x, (int) size.y, false);
- }
- } else {
- throw new IllegalStateException("This VR environment is not attached to any application.");
- }
- } else {
- throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
- }
- }
- private ViewPort setupViewBuffers(Camera cam, String viewName) {
- // TODO this function is identical to that in VRViewManagerOpenVR; merge the two.
- if (environment != null) {
- if (environment.getApplication() != null) {
- // create offscreen framebuffer
- FrameBuffer offBufferLeft = new FrameBuffer(cam.getWidth(), cam.getHeight(), 1);
- //offBufferLeft.setSrgb(true);
- //setup framebuffer's texture
- Texture2D offTex = new Texture2D(cam.getWidth(), cam.getHeight(), Image.Format.RGBA8);
- offTex.setMinFilter(Texture.MinFilter.BilinearNoMipMaps);
- offTex.setMagFilter(Texture.MagFilter.Bilinear);
- //setup framebuffer to use texture
- offBufferLeft.setDepthBuffer(Image.Format.Depth);
- offBufferLeft.setColorTexture(offTex);
- ViewPort viewPort = environment.getApplication().getRenderManager().createPreView(viewName, cam);
- viewPort.setClearFlags(true, true, true);
- viewPort.setBackgroundColor(ColorRGBA.Black);
- Iterator<Spatial> spatialIter = environment.getApplication().getViewPort().getScenes().iterator();
- while (spatialIter.hasNext()) {
- viewPort.attachScene(spatialIter.next());
- }
- //set viewport to render to offscreen framebuffer
- viewPort.setOutputFrameBuffer(offBufferLeft);
- return viewPort;
- } else {
- throw new IllegalStateException("This VR environment is not attached to any application.");
- }
- } else {
- throw new IllegalStateException("This VR view manager is not attached to any VR environment.");
- }
- }
- }
|