From 56cbd57b00a4c3e43ccfe9a7a2afd9715ce71bab Mon Sep 17 00:00:00 2001 From: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Date: Thu, 1 Aug 2024 23:35:12 +0200 Subject: [PATCH 01/27] [WIP] Add openXR support (#230) Add first attempt OpenXR support TODO - Test on all different OpenXR platforms - Figure out key binding system - Verify all functionality Co-authored-by: The Judge <53906078+thejudge156@users.noreply.github.com> Co-authored-by: fayer3 --- build.gradle | 5 + .../extensions/RenderTargetExtension.java | 2 + .../gui/settings/GuiRenderOpticsSettings.java | 2 +- .../java/org/vivecraft/client_vr/VRState.java | 36 +- .../vivecraft/client_vr/VRTextureTarget.java | 15 +- .../vivecraft/client_vr/gui/GuiRadial.java | 2 +- .../client_vr/provider/ActionParams.java | 2 +- .../vivecraft/client_vr/provider/MCVR.java | 126 +- .../client_vr/provider/VRRenderer.java | 60 +- .../control/HapticMusicPlayer.java | 10 +- .../control/TrackpadSwipeSampler.java | 8 +- .../VRInputAction.java | 13 +- .../control/VRInputActionSet.java | 2 +- .../control/VivecraftMovementInput.java | 11 + .../client_vr/provider/nullvr/NullVR.java | 7 +- .../provider/nullvr/NullVRStereoRenderer.java | 51 +- .../provider/openvr_lwjgl/MCOpenVR.java | 124 +- .../openvr_lwjgl/OpenVRStereoRenderer.java | 52 +- .../control/VivecraftMovementInput.java | 12 - .../client_vr/provider/openxr/MCOpenXR.java | 1494 +++++++++++++++++ .../openxr/OpenXRHapticSchedular.java | 47 + .../provider/openxr/OpenXRStereoRenderer.java | 182 ++ .../client_vr/provider/openxr/OpenXRUtil.java | 50 + .../client_vr/provider/openxr/XRBindings.java | 137 ++ .../render/helpers/VRPassHelper.java | 11 +- .../client_vr/settings/VRSettings.java | 14 +- .../client/blaze3d/RenderTargetMixin.java | 5 + .../mixin/client_vr/KeyboardInputVRMixin.java | 4 +- .../mixin/client_vr/MinecraftVRMixin.java | 20 +- .../assets/vivecraft/lang/en_us.json | 4 + fabric/build.gradle | 4 + forge/build.gradle | 8 + neoforge/build.gradle | 8 + 33 files changed, 2278 insertions(+), 250 deletions(-) rename common/src/main/java/org/vivecraft/client_vr/provider/{openvr_lwjgl => }/control/HapticMusicPlayer.java (77%) rename common/src/main/java/org/vivecraft/client_vr/provider/{openvr_lwjgl => }/control/TrackpadSwipeSampler.java (88%) rename common/src/main/java/org/vivecraft/client_vr/provider/{openvr_lwjgl => control}/VRInputAction.java (96%) rename common/src/main/java/org/vivecraft/client_vr/provider/{openvr_lwjgl => }/control/VRInputActionSet.java (96%) create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/control/VivecraftMovementInput.java delete mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/VivecraftMovementInput.java create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java diff --git a/build.gradle b/build.gradle index b7eaa2889..83ac7389a 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,11 @@ subprojects { implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-linux") implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") + + implementation("org.lwjgl:lwjgl-openxr:3.3.2") + implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") + //implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-macos") + implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") } tasks.withType(JavaCompile) { diff --git a/common/src/main/java/org/vivecraft/client/extensions/RenderTargetExtension.java b/common/src/main/java/org/vivecraft/client/extensions/RenderTargetExtension.java index 43b951e49..ff1c98e07 100644 --- a/common/src/main/java/org/vivecraft/client/extensions/RenderTargetExtension.java +++ b/common/src/main/java/org/vivecraft/client/extensions/RenderTargetExtension.java @@ -17,6 +17,8 @@ public interface RenderTargetExtension { void vivecraft$setTextid(int texid); + void vivecraft$setColorid(int colorid); + void vivecraft$setUseStencil(boolean useStencil); boolean vivecraft$getUseStencil(); diff --git a/common/src/main/java/org/vivecraft/client/gui/settings/GuiRenderOpticsSettings.java b/common/src/main/java/org/vivecraft/client/gui/settings/GuiRenderOpticsSettings.java index cf80cbd19..610d5771b 100644 --- a/common/src/main/java/org/vivecraft/client/gui/settings/GuiRenderOpticsSettings.java +++ b/common/src/main/java/org/vivecraft/client/gui/settings/GuiRenderOpticsSettings.java @@ -24,7 +24,7 @@ public class GuiRenderOpticsSettings extends GuiVROptionsBase { VRSettings.VrOptions.HANDHELD_CAMERA_RENDER_SCALE, VRSettings.VrOptions.HANDHELD_CAMERA_FOV, VRSettings.VrOptions.RELOAD_EXTERNAL_CAMERA, - VRSettings.VrOptions.MIRROR_EYE + VRSettings.VrOptions.MIRROR_EYE, }; static VRSettings.VrOptions[] MROptions = new VRSettings.VrOptions[]{ VRSettings.VrOptions.MIXED_REALITY_UNITY_LIKE, diff --git a/common/src/main/java/org/vivecraft/client_vr/VRState.java b/common/src/main/java/org/vivecraft/client_vr/VRState.java index 52c412da3..16b32f9da 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRState.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRState.java @@ -13,6 +13,7 @@ import org.vivecraft.client_vr.menuworlds.MenuWorldRenderer; import org.vivecraft.client_vr.provider.nullvr.NullVR; import org.vivecraft.client_vr.provider.openvr_lwjgl.MCOpenVR; +import org.vivecraft.client_vr.provider.openxr.MCOpenXR; import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.client_xr.render_pass.RenderPassManager; @@ -40,25 +41,26 @@ public static void initializeVR() { vrInitialized = true; ClientDataHolderVR dh = ClientDataHolderVR.getInstance(); - if (dh.vrSettings.stereoProviderPluginID == VRSettings.VRProvider.OPENVR) { - // make sure the lwjgl version is the right one - // TODO: move this into the init, does mean all callocs need to be done later - // check that the right lwjgl version is loaded that we ship the openvr part of - if (!Version.getVersion().startsWith("3.3.2")) { - String suppliedJar = ""; - try { - suppliedJar = new File(Version.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getName(); - } catch (Exception e) { - VRSettings.logger.error("couldn't check lwjgl source:", e); - } - - throw new RenderConfigException("VR Init Error", Component.translatable("vivecraft.messages.rendersetupfailed", I18n.get("vivecraft.messages.invalidlwjgl", Version.getVersion(), "3.3.2", suppliedJar), "OpenVR_LWJGL")); + Minecraft instance = Minecraft.getInstance(); + // make sure the lwjgl version is the right one + // TODO: move this into the init, does mean all callocs need to be done later + // check that the right lwjgl version is loaded that we ship the openvr part of + if (!Version.getVersion().startsWith("3.3.2")) { + String suppliedJar = ""; + try { + suppliedJar = new File(Version.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getName(); + } catch (Exception e) { + VRSettings.logger.error("couldn't check lwjgl source:", e); } - dh.vr = new MCOpenVR(Minecraft.getInstance(), dh); - } else { - dh.vr = new NullVR(Minecraft.getInstance(), dh); + throw new RenderConfigException("VR Init Error", Component.translatable("vivecraft.messages.rendersetupfailed", I18n.get("vivecraft.messages.invalidlwjgl", Version.getVersion(), "3.3.2", suppliedJar), "OpenVR_LWJGL")); } + switch (dh.vrSettings.stereoProviderPluginID) { + case OPENVR -> dh.vr = new MCOpenVR(instance, dh); + case OPENXR -> dh.vr = new MCOpenXR(instance, dh); + default -> dh.vr = new NullVR(instance, dh); + } + if (!dh.vr.init()) { throw new RenderConfigException("VR Init Error", Component.translatable("vivecraft.messages.rendersetupfailed", dh.vr.initStatus, dh.vr.getName())); } @@ -66,7 +68,7 @@ public static void initializeVR() { dh.vrRenderer = dh.vr.createVRRenderer(); dh.vrRenderer.lastGuiScale = Minecraft.getInstance().options.guiScale().get(); - dh.vrRenderer.setupRenderConfiguration(); + dh.vrRenderer.setupRenderConfiguration(false); //TODO look into why I have the boolean RenderPassManager.setVanillaRenderPass(); dh.vrPlayer = new VRPlayer(); diff --git a/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java b/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java index b29b88b88..4195de565 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java @@ -1,14 +1,16 @@ package org.vivecraft.client_vr; import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; +import org.lwjgl.opengl.GL30; import org.vivecraft.client.Xplat; import org.vivecraft.client.extensions.RenderTargetExtension; public class VRTextureTarget extends RenderTarget { private final String name; - public VRTextureTarget(String name, int width, int height, boolean usedepth, boolean onMac, int texid, boolean depthtex, boolean linearFilter, boolean useStencil) { super(usedepth); this.name = name; @@ -23,6 +25,17 @@ public VRTextureTarget(String name, int width, int height, boolean usedepth, boo this.setClearColor(0, 0, 0, 0); } + public VRTextureTarget(String name, int width, int height, int colorid, int index) { + super(true); + this.name = name; + RenderSystem.assertOnGameThreadOrInit(); + this.resize(width, height, Minecraft.ON_OSX); + ((RenderTargetExtension) this).vivecraft$setColorid(colorid); + GlStateManager._glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferId); + GL30.glFramebufferTextureLayer(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, colorid, 0, index); + this.setClearColor(0, 0, 0, 0); + } + @Override public String toString() { StringBuilder stringbuilder = new StringBuilder(); diff --git a/common/src/main/java/org/vivecraft/client_vr/gui/GuiRadial.java b/common/src/main/java/org/vivecraft/client_vr/gui/GuiRadial.java index a68a9d3d0..16bbfeb2d 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gui/GuiRadial.java +++ b/common/src/main/java/org/vivecraft/client_vr/gui/GuiRadial.java @@ -7,7 +7,7 @@ import net.minecraft.network.chat.Component; import org.vivecraft.client.gui.framework.TwoHandedScreen; import org.vivecraft.client_vr.provider.MCVR; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; +import org.vivecraft.client_vr.provider.control.VRInputAction; public class GuiRadial extends TwoHandedScreen { private boolean isShift = false; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/ActionParams.java b/common/src/main/java/org/vivecraft/client_vr/provider/ActionParams.java index 5586e4994..5b4015eaa 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/ActionParams.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/ActionParams.java @@ -1,6 +1,6 @@ package org.vivecraft.client_vr.provider; -import org.vivecraft.client_vr.provider.openvr_lwjgl.control.VRInputActionSet; +import org.vivecraft.client_vr.provider.control.VRInputActionSet; public class ActionParams { public final VRInputActionSet actionSetOverride; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java index 6f78158b7..fd9508569 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java @@ -1,5 +1,6 @@ package org.vivecraft.client_vr.provider; +import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.ChatScreen; @@ -25,9 +26,10 @@ import org.vivecraft.client_vr.gameplay.screenhandlers.GuiHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.RadialHandler; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; -import org.vivecraft.client_vr.provider.openvr_lwjgl.control.VRInputActionSet; -import org.vivecraft.client_vr.provider.openvr_lwjgl.control.VivecraftMovementInput; +import org.vivecraft.client_vr.provider.control.TrackpadSwipeSampler; +import org.vivecraft.client_vr.provider.control.VRInputAction; +import org.vivecraft.client_vr.provider.control.VRInputActionSet; +import org.vivecraft.client_vr.provider.control.VivecraftMovementInput; import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.settings.VRHotkeys; @@ -108,6 +110,8 @@ public abstract class MCVR { protected int quickTorchPreviousSlot; protected Map inputActions = new HashMap<>(); protected Map inputActionsByKeyBinding = new HashMap<>(); + protected final Map trackpadSwipeSamplers = new HashMap<>(); + protected boolean inputInitialized; public MCVR(Minecraft mc, ClientDataHolderVR dh, VivecraftVRMod vrMod) { this.mc = mc; @@ -131,7 +135,50 @@ public static MCVR get() { public abstract String getID(); - public abstract void processInputs(); + public void processInputs() { + if (!this.dh.vrSettings.seated && !ClientDataHolderVR.viewonly && this.inputInitialized) { + for (VRInputAction vrinputaction : this.inputActions.values()) { + if (vrinputaction.isHanded()) { + for (ControllerType controllertype : ControllerType.values()) { + vrinputaction.setCurrentHand(controllertype); + this.processInputAction(vrinputaction); + } + } else { + this.processInputAction(vrinputaction); + } + } + + this.processScrollInput(GuiHandler.keyScrollAxis, () -> + { + InputSimulator.scrollMouse(0.0D, 1.0D); + }, () -> + { + InputSimulator.scrollMouse(0.0D, -1.0D); + }); + this.processScrollInput(VivecraftVRMod.INSTANCE.keyHotbarScroll, () -> + { + this.changeHotbar(-1); + }, () -> + { + this.changeHotbar(1); + }); + this.processSwipeInput(VivecraftVRMod.INSTANCE.keyHotbarSwipeX, () -> + { + this.changeHotbar(1); + }, () -> + { + this.changeHotbar(-1); + }, null, null); + this.processSwipeInput(VivecraftVRMod.INSTANCE.keyHotbarSwipeY, null, null, () -> + { + this.changeHotbar(-1); + }, () -> + { + this.changeHotbar(1); + }); + this.ignorePressesNextFrame = false; + } + } public abstract void destroy(); @@ -1145,6 +1192,76 @@ protected void changeHotbar(int dir) { } } + protected void processInputAction(VRInputAction action) { + if (action.isActive() && action.isEnabledRaw() + // try to prevent double left clicks + && (!ClientDataHolderVR.getInstance().vrSettings.ingameBindingsInGui + || !(action.actionSet == VRInputActionSet.INGAME && action.keyBinding.key.getType() == InputConstants.Type.MOUSE && action.keyBinding.key.getValue() == 0 && mc.screen != null))) { + if (action.isButtonChanged()) { + if (action.isButtonPressed() && action.isEnabled()) { + if (!this.ignorePressesNextFrame) { + action.pressBinding(); + } + } else { + action.unpressBinding(); + } + } + } else { + action.unpressBinding(); + } + } + + protected void processScrollInput(KeyMapping keyBinding, Runnable upCallback, Runnable downCallback) { + VRInputAction vrinputaction = this.getInputAction(keyBinding); + + if (vrinputaction.isEnabled() && vrinputaction.getLastOrigin() != 0L && vrinputaction.getAxis2D(true).getY() != 0.0F) { + float f = vrinputaction.getAxis2D(false).getY(); + + if (f > 0.0F) { + upCallback.run(); + } else if (f < 0.0F) { + downCallback.run(); + } + } + } + + protected void processSwipeInput(KeyMapping keyBinding, Runnable leftCallback, Runnable rightCallback, Runnable upCallback, Runnable downCallback) { + VRInputAction vrinputaction = this.getInputAction(keyBinding); + + if (vrinputaction.isEnabled() && vrinputaction.getLastOrigin() != 0L) { + ControllerType controllertype = this.findActiveBindingControllerType(keyBinding); + + if (controllertype != null) { + if (!this.trackpadSwipeSamplers.containsKey(keyBinding.getName())) { + this.trackpadSwipeSamplers.put(keyBinding.getName(), new TrackpadSwipeSampler()); + } + + TrackpadSwipeSampler trackpadswipesampler = this.trackpadSwipeSamplers.get(keyBinding.getName()); + trackpadswipesampler.update(controllertype, vrinputaction.getAxis2D(false)); + + if (trackpadswipesampler.isSwipedUp() && upCallback != null) { + this.triggerHapticPulse(controllertype, 0.001F, 400.0F, 0.5F); + upCallback.run(); + } + + if (trackpadswipesampler.isSwipedDown() && downCallback != null) { + this.triggerHapticPulse(controllertype, 0.001F, 400.0F, 0.5F); + downCallback.run(); + } + + if (trackpadswipesampler.isSwipedLeft() && leftCallback != null) { + this.triggerHapticPulse(controllertype, 0.001F, 400.0F, 0.5F); + leftCallback.run(); + } + + if (trackpadswipesampler.isSwipedRight() && rightCallback != null) { + this.triggerHapticPulse(controllertype, 0.001F, 400.0F, 0.5F); + rightCallback.run(); + } + } + } + } + private void addActionParams(Map map, KeyMapping keyBinding, String requirement, String type, VRInputActionSet actionSetOverride) { ActionParams actionparams = new ActionParams(requirement, type, actionSetOverride); map.put(keyBinding.getName(), actionparams); @@ -1174,6 +1291,7 @@ private void addActionParams(Map map, KeyMapping keyBindin public abstract boolean isActive(); + public abstract ControllerType getOriginControllerType(long i); public boolean capFPS() { return false; } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java index baca749ed..228c029bc 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java @@ -55,8 +55,6 @@ public abstract class VRRenderer { protected int dispLastWidth; protected int dispLastHeight; public Matrix4f[] eyeproj = new Matrix4f[2]; - public RenderTarget framebufferEye0; - public RenderTarget framebufferEye1; public RenderTarget framebufferMR; public RenderTarget framebufferUndistorted; public RenderTarget framebufferVrRender; @@ -75,8 +73,6 @@ public abstract class VRRenderer { public int lastRenderDistanceChunks = -1; public long lastWindow = 0L; public float lastWorldScale = 0.0F; - protected int LeftEyeTextureId = -1; - protected int RightEyeTextureId = -1; public int mirrorFBHeight; public int mirrorFBWidth; protected boolean reinitFramebuffers = true; @@ -101,7 +97,7 @@ protected void checkGLError(String message) { } } - public abstract void createRenderTexture(int var1, int var2); + public abstract void createRenderTexture(int var1, int var2) throws RenderConfigException; public abstract Matrix4f getProjectionMatrix(int var1, float var2, float var3); @@ -109,17 +105,8 @@ protected void checkGLError(String message) { public abstract boolean providesStencilMask(); - public void deleteRenderTextures() { - if (this.LeftEyeTextureId > 0) { - RenderSystem.deleteTexture(this.LeftEyeTextureId); - } - - if (this.RightEyeTextureId > 0) { - RenderSystem.deleteTexture(this.RightEyeTextureId); - } - - this.LeftEyeTextureId = this.RightEyeTextureId = -1; - } + public abstract RenderTarget getLeftEyeTarget(); + public abstract RenderTarget getRightEyeTarget(); public void doStencil(boolean inverse) { Minecraft minecraft = Minecraft.getInstance(); @@ -437,7 +424,7 @@ public void resizeFrameBuffers(String cause) { this.resizeFrameBuffers = true; } - public void setupRenderConfiguration() throws Exception { + public void setupRenderConfiguration(boolean render) throws Exception { Minecraft minecraft = Minecraft.getInstance(); ClientDataHolderVR dataholder = ClientDataHolderVR.getInstance(); @@ -529,6 +516,10 @@ public void setupRenderConfiguration() throws Exception { } } + //for OPENXR, it needs to reinit + this.eyeproj[0] = this.getProjectionMatrix(0, ((GameRendererExtension) minecraft.gameRenderer).vivecraft$getMinClipDistance(), ((GameRendererExtension) minecraft.gameRenderer).vivecraft$getClipDistance()); + this.eyeproj[1] = this.getProjectionMatrix(1, ((GameRendererExtension) minecraft.gameRenderer).vivecraft$getMinClipDistance(), ((GameRendererExtension) minecraft.gameRenderer).vivecraft$getClipDistance()); + if (this.reinitFramebuffers) { this.reinitShadersFlag = true; this.checkGLError("Start Init"); @@ -568,30 +559,7 @@ public void setupRenderConfiguration() throws Exception { destroy(); - if (this.LeftEyeTextureId == -1) { - this.createRenderTexture(eyew, eyeh); - - if (this.LeftEyeTextureId == -1) { - throw new RenderConfigException("Failed to initialise stereo rendering plugin: " + this.getName(), Component.literal(this.getLastError())); - } - - dataholder.print("Provider supplied render texture IDs: " + this.LeftEyeTextureId + " " + this.RightEyeTextureId); - dataholder.print("Provider supplied texture resolution: " + eyew + " x " + eyeh); - } - - this.checkGLError("Render Texture setup"); - - if (this.framebufferEye0 == null) { - this.framebufferEye0 = new VRTextureTarget("L Eye", eyew, eyeh, false, false, this.LeftEyeTextureId, false, true, false); - dataholder.print(this.framebufferEye0.toString()); - this.checkGLError("Left Eye framebuffer setup"); - } - - if (this.framebufferEye1 == null) { - this.framebufferEye1 = new VRTextureTarget("R Eye", eyew, eyeh, false, false, this.RightEyeTextureId, false, true, false); - dataholder.print(this.framebufferEye1.toString()); - this.checkGLError("Right Eye framebuffer setup"); - } + this.createRenderTexture(eyew, eyeh); float resolutionScale = ResolutionControlHelper.isLoaded() ? ResolutionControlHelper.getCurrentScaleFactor() : 1.0F; @@ -826,15 +794,5 @@ public void destroy() { this.fsaaLastPassResultFBO.destroyBuffers(); this.fsaaLastPassResultFBO = null; } - - if (this.framebufferEye0 != null) { - this.framebufferEye0.destroyBuffers(); - this.framebufferEye0 = null; - } - - if (this.framebufferEye1 != null) { - this.framebufferEye1.destroyBuffers(); - this.framebufferEye1 = null; - } } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/HapticMusicPlayer.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/HapticMusicPlayer.java similarity index 77% rename from common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/HapticMusicPlayer.java rename to common/src/main/java/org/vivecraft/client_vr/provider/control/HapticMusicPlayer.java index 27cb7081e..33859b11b 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/HapticMusicPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/HapticMusicPlayer.java @@ -1,7 +1,7 @@ -package org.vivecraft.client_vr.provider.openvr_lwjgl.control; +package org.vivecraft.client_vr.provider.control; +import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.provider.ControllerType; -import org.vivecraft.client_vr.provider.openvr_lwjgl.MCOpenVR; import javax.annotation.Nullable; import java.util.HashMap; @@ -62,10 +62,10 @@ public void play() { if (object instanceof Note hapticmusicplayer$music$note) { if (hapticmusicplayer$music$note.controller != null) { - MCOpenVR.get().triggerHapticPulse(hapticmusicplayer$music$note.controller, hapticmusicplayer$music$note.durationSeconds, hapticmusicplayer$music$note.frequency, hapticmusicplayer$music$note.amplitude, f); + ClientDataHolderVR.getInstance().vr.triggerHapticPulse(hapticmusicplayer$music$note.controller, hapticmusicplayer$music$note.durationSeconds, hapticmusicplayer$music$note.frequency, hapticmusicplayer$music$note.amplitude, f); } else { - MCOpenVR.get().triggerHapticPulse(ControllerType.RIGHT, hapticmusicplayer$music$note.durationSeconds, hapticmusicplayer$music$note.frequency, hapticmusicplayer$music$note.amplitude, f); - MCOpenVR.get().triggerHapticPulse(ControllerType.LEFT, hapticmusicplayer$music$note.durationSeconds, hapticmusicplayer$music$note.frequency, hapticmusicplayer$music$note.amplitude, f); + ClientDataHolderVR.getInstance().vr.get().triggerHapticPulse(ControllerType.RIGHT, hapticmusicplayer$music$note.durationSeconds, hapticmusicplayer$music$note.frequency, hapticmusicplayer$music$note.amplitude, f); + ClientDataHolderVR.getInstance().vr.get().triggerHapticPulse(ControllerType.LEFT, hapticmusicplayer$music$note.durationSeconds, hapticmusicplayer$music$note.frequency, hapticmusicplayer$music$note.amplitude, f); } } else if (object instanceof Delay hapticmusicplayer$music$delay) { f += hapticmusicplayer$music$delay.durationSeconds; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/TrackpadSwipeSampler.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/TrackpadSwipeSampler.java similarity index 88% rename from common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/TrackpadSwipeSampler.java rename to common/src/main/java/org/vivecraft/client_vr/provider/control/TrackpadSwipeSampler.java index fd581e0b5..0c3079d62 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/TrackpadSwipeSampler.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/TrackpadSwipeSampler.java @@ -1,8 +1,8 @@ -package org.vivecraft.client_vr.provider.openvr_lwjgl.control; +package org.vivecraft.client_vr.provider.control; import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.provider.ControllerType; -import org.vivecraft.client_vr.provider.openvr_lwjgl.MCOpenVR; import org.vivecraft.common.utils.lwjgl.Vector2f; import org.vivecraft.common.utils.math.Vector2; @@ -25,9 +25,9 @@ public TrackpadSwipeSampler() { } public void update(ControllerType hand, Vector2 position) { - MCOpenVR.get().getInputAction(VivecraftVRMod.INSTANCE.keyTrackpadTouch).setCurrentHand(hand); + ClientDataHolderVR.getInstance().vr.getInputAction(VivecraftVRMod.INSTANCE.keyTrackpadTouch).setCurrentHand(hand); - if (MCOpenVR.get().getInputAction(VivecraftVRMod.INSTANCE.keyTrackpadTouch).isButtonPressed()) { + if (ClientDataHolderVR.getInstance().vr.getInputAction(VivecraftVRMod.INSTANCE.keyTrackpadTouch).isButtonPressed()) { this.buffer[this.index].set(position.getX(), position.getY()); if (++this.index >= this.buffer.length) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/VRInputAction.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java similarity index 96% rename from common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/VRInputAction.java rename to common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java index 0dca0469d..5da8cf5d0 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/VRInputAction.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java @@ -1,13 +1,12 @@ -package org.vivecraft.client_vr.provider.openvr_lwjgl; +package org.vivecraft.client_vr.provider.control; import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyMapping; import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.client_vr.provider.HandedKeyBinding; import org.vivecraft.client_vr.provider.InputSimulator; -import org.vivecraft.client_vr.provider.MCVR; -import org.vivecraft.client_vr.provider.openvr_lwjgl.control.VRInputActionSet; import org.vivecraft.common.utils.math.Vector2; import org.vivecraft.common.utils.math.Vector3; @@ -219,17 +218,17 @@ public VRInputAction setPriority(int priority) { public boolean isEnabled() { if (!this.isEnabledRaw(this.currentHand)) { return false; - } else if (MCOpenVR.get() == null) { + } else if (ClientDataHolderVR.getInstance().vr == null) { return false; } else { long i = this.getLastOrigin(); - ControllerType controllertype = MCOpenVR.get().getOriginControllerType(i); + ControllerType controllertype = ClientDataHolderVR.getInstance().vr.getOriginControllerType(i); if (controllertype == null && this.isHanded()) { return false; } else { - for (VRInputAction vrinputaction : MCOpenVR.get().getInputActions()) { - if (vrinputaction != this && vrinputaction.isEnabledRaw(controllertype) && vrinputaction.isActive() && vrinputaction.getPriority() > this.getPriority() && MCVR.get().getOrigins(vrinputaction).contains(i)) { + for (VRInputAction vrinputaction : ClientDataHolderVR.getInstance().vr.getInputActions()) { + if (vrinputaction != this && vrinputaction.isEnabledRaw(controllertype) && vrinputaction.isActive() && vrinputaction.getPriority() > this.getPriority() && ClientDataHolderVR.getInstance().vr.getOrigins(vrinputaction).contains(i)) { if (vrinputaction.isHanded()) { return !((HandedKeyBinding) vrinputaction.keyBinding).isPriorityOnController(controllertype); } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/VRInputActionSet.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputActionSet.java similarity index 96% rename from common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/VRInputActionSet.java rename to common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputActionSet.java index b99331369..7cdec10d8 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/VRInputActionSet.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputActionSet.java @@ -1,4 +1,4 @@ -package org.vivecraft.client_vr.provider.openvr_lwjgl.control; +package org.vivecraft.client_vr.provider.control; import net.minecraft.client.KeyMapping; import org.vivecraft.client.VivecraftVRMod; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/control/VivecraftMovementInput.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/VivecraftMovementInput.java new file mode 100644 index 000000000..79de67246 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/VivecraftMovementInput.java @@ -0,0 +1,11 @@ +package org.vivecraft.client_vr.provider.control; + +import net.minecraft.client.KeyMapping; +import org.vivecraft.client_vr.ClientDataHolderVR; + +public class VivecraftMovementInput { + public static float getMovementAxisValue(KeyMapping keyBinding) { + VRInputAction vrinputaction = ClientDataHolderVR.getInstance().vr.getInputAction(keyBinding); + return Math.abs(vrinputaction.getAxis1DUseTracked()); + } +} diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java index 09ff0186b..e01ebb089 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java @@ -12,7 +12,7 @@ import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.provider.VRRenderer; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; +import org.vivecraft.client_vr.provider.control.VRInputAction; import org.vivecraft.common.utils.math.Matrix4f; import java.util.List; @@ -195,6 +195,11 @@ public boolean isActive() { return vrActive; } + @Override + public ControllerType getOriginControllerType(long i) { + return ControllerType.LEFT; + } + @Override public boolean capFPS() { return true; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVRStereoRenderer.java index b8d020266..74c847c87 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVRStereoRenderer.java @@ -1,16 +1,27 @@ package org.vivecraft.client_vr.provider.nullvr; +import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.TextureUtil; import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.network.chat.Component; import net.minecraft.util.Tuple; import org.joml.Matrix4f; import org.lwjgl.opengl.GL11; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRTextureTarget; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.provider.VRRenderer; +import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.render.RenderPass; public class NullVRStereoRenderer extends VRRenderer { + + protected int LeftEyeTextureId = -1; + protected int RightEyeTextureId = -1; + public RenderTarget framebufferEye0; + public RenderTarget framebufferEye1; + public NullVRStereoRenderer(MCVR vr) { super(vr); } @@ -40,7 +51,7 @@ public String getLastError() { } @Override - public void createRenderTexture(int lwidth, int lheight) { + public void createRenderTexture(int lwidth, int lheight) throws RenderConfigException { this.LeftEyeTextureId = GlStateManager._genTexture(); int i = GlStateManager._getInteger(GL11.GL_TEXTURE_BINDING_2D); RenderSystem.bindTexture(this.LeftEyeTextureId); @@ -56,6 +67,25 @@ public void createRenderTexture(int lwidth, int lheight) { RenderSystem.texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); GlStateManager._texImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, lwidth, lheight, 0, GL11.GL_RGBA, GL11.GL_INT, null); RenderSystem.bindTexture(i); + + ClientDataHolderVR dataholder = ClientDataHolderVR.getInstance(); + if (this.LeftEyeTextureId == -1) { + throw new RenderConfigException("Failed to initialise stereo rendering plugin: " + this.getName(), Component.literal(this.getLastError())); + } + + this.checkGLError("Render Texture setup"); + + if (this.framebufferEye0 == null) { + this.framebufferEye0 = new VRTextureTarget("L Eye", lwidth, lheight, false, false, this.LeftEyeTextureId, false, true, false); + dataholder.print(this.framebufferEye0.toString()); + this.checkGLError("Left Eye framebuffer setup"); + } + + if (this.framebufferEye1 == null) { + this.framebufferEye1 = new VRTextureTarget("R Eye", lwidth, lheight, false, false, this.RightEyeTextureId, false, true, false); + dataholder.print(this.framebufferEye1.toString()); + this.checkGLError("Right Eye framebuffer setup"); + } } @Override @@ -67,6 +97,16 @@ public boolean providesStencilMask() { return false; } + @Override + public RenderTarget getLeftEyeTarget() { + return framebufferEye0; + } + + @Override + public RenderTarget getRightEyeTarget() { + return framebufferEye1; + } + @Override public float[] getStencilMask(RenderPass eye) { @@ -91,6 +131,15 @@ public String getinitError() { @Override public void destroy() { super.destroy(); + if (this.framebufferEye0 != null) { + this.framebufferEye0.destroyBuffers(); + this.framebufferEye0 = null; + } + + if (this.framebufferEye1 != null) { + this.framebufferEye1.destroyBuffers(); + this.framebufferEye1 = null; + } if (this.LeftEyeTextureId > -1) { TextureUtil.releaseTextureId(this.LeftEyeTextureId); this.LeftEyeTextureId = -1; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index 6c967a0fe..5e466cc39 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -24,8 +24,9 @@ import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.RadialHandler; import org.vivecraft.client_vr.provider.*; -import org.vivecraft.client_vr.provider.openvr_lwjgl.control.TrackpadSwipeSampler; -import org.vivecraft.client_vr.provider.openvr_lwjgl.control.VRInputActionSet; +import org.vivecraft.client_vr.provider.control.TrackpadSwipeSampler; +import org.vivecraft.client_vr.provider.control.VRInputAction; +import org.vivecraft.client_vr.provider.control.VRInputActionSet; import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.settings.VRHotkeys; import org.vivecraft.client_vr.settings.VRSettings; @@ -76,7 +77,6 @@ public class MCOpenVR extends MCVR { private final IntBuffer hmdErrorStore = MemoryUtil.memCallocInt(1); private IntBuffer hmdErrorStoreBuf; private TrackedDevicePose.Buffer hmdTrackedDevicePoses; - private boolean inputInitialized; private long leftControllerHandle; private long leftHapticHandle; private long leftPoseHandle; @@ -87,7 +87,6 @@ public class MCOpenVR extends MCVR { private long rightHapticHandle; private long rightPoseHandle; private final VRTextureBounds texBounds = VRTextureBounds.calloc(); - private final Map trackpadSwipeSamplers = new HashMap<>(); private boolean tried; private final Queue vrEvents = new LinkedList<>(); final Texture texType0 = Texture.calloc(); @@ -367,51 +366,6 @@ public void poll(long frameIndex) { } } - public void processInputs() { - if (!this.dh.vrSettings.seated && !ClientDataHolderVR.viewonly && this.inputInitialized) { - for (VRInputAction vrinputaction : this.inputActions.values()) { - if (vrinputaction.isHanded()) { - for (ControllerType controllertype : ControllerType.values()) { - vrinputaction.setCurrentHand(controllertype); - this.processInputAction(vrinputaction); - } - } else { - this.processInputAction(vrinputaction); - } - } - - this.processScrollInput(GuiHandler.keyScrollAxis, () -> - { - InputSimulator.scrollMouse(0.0D, 1.0D); - }, () -> - { - InputSimulator.scrollMouse(0.0D, -1.0D); - }); - this.processScrollInput(VivecraftVRMod.INSTANCE.keyHotbarScroll, () -> - { - this.changeHotbar(-1); - }, () -> - { - this.changeHotbar(1); - }); - this.processSwipeInput(VivecraftVRMod.INSTANCE.keyHotbarSwipeX, () -> - { - this.changeHotbar(1); - }, () -> - { - this.changeHotbar(-1); - }, null, null); - this.processSwipeInput(VivecraftVRMod.INSTANCE.keyHotbarSwipeY, null, null, () -> - { - this.changeHotbar(-1); - }, () -> - { - this.changeHotbar(1); - }); - this.ignorePressesNextFrame = false; - } - } - @Deprecated protected void triggerBindingHapticPulse(KeyMapping binding, int duration) { ControllerType controllertype = this.findActiveBindingControllerType(binding); @@ -1002,76 +956,6 @@ private void pollVREvents() { } } - private void processInputAction(VRInputAction action) { - if (action.isActive() && action.isEnabledRaw() - // try to prevent double left clicks - && (!ClientDataHolderVR.getInstance().vrSettings.ingameBindingsInGui - || !(action.actionSet == VRInputActionSet.INGAME && action.keyBinding.key.getType() == InputConstants.Type.MOUSE && action.keyBinding.key.getValue() == 0 && mc.screen != null))) { - if (action.isButtonChanged()) { - if (action.isButtonPressed() && action.isEnabled()) { - if (!this.ignorePressesNextFrame) { - action.pressBinding(); - } - } else { - action.unpressBinding(); - } - } - } else { - action.unpressBinding(); - } - } - - private void processScrollInput(KeyMapping keyBinding, Runnable upCallback, Runnable downCallback) { - VRInputAction vrinputaction = this.getInputAction(keyBinding); - - if (vrinputaction.isEnabled() && vrinputaction.getLastOrigin() != 0L && vrinputaction.getAxis2D(true).getY() != 0.0F) { - float f = vrinputaction.getAxis2D(false).getY(); - - if (f > 0.0F) { - upCallback.run(); - } else if (f < 0.0F) { - downCallback.run(); - } - } - } - - private void processSwipeInput(KeyMapping keyBinding, Runnable leftCallback, Runnable rightCallback, Runnable upCallback, Runnable downCallback) { - VRInputAction vrinputaction = this.getInputAction(keyBinding); - - if (vrinputaction.isEnabled() && vrinputaction.getLastOrigin() != 0L) { - ControllerType controllertype = this.findActiveBindingControllerType(keyBinding); - - if (controllertype != null) { - if (!this.trackpadSwipeSamplers.containsKey(keyBinding.getName())) { - this.trackpadSwipeSamplers.put(keyBinding.getName(), new TrackpadSwipeSampler()); - } - - TrackpadSwipeSampler trackpadswipesampler = this.trackpadSwipeSamplers.get(keyBinding.getName()); - trackpadswipesampler.update(controllertype, vrinputaction.getAxis2D(false)); - - if (trackpadswipesampler.isSwipedUp() && upCallback != null) { - this.triggerHapticPulse(controllertype, 0.001F, 400.0F, 0.5F); - upCallback.run(); - } - - if (trackpadswipesampler.isSwipedDown() && downCallback != null) { - this.triggerHapticPulse(controllertype, 0.001F, 400.0F, 0.5F); - downCallback.run(); - } - - if (trackpadswipesampler.isSwipedLeft() && leftCallback != null) { - this.triggerHapticPulse(controllertype, 0.001F, 400.0F, 0.5F); - leftCallback.run(); - } - - if (trackpadswipesampler.isSwipedRight() && rightCallback != null) { - this.triggerHapticPulse(controllertype, 0.001F, 400.0F, 0.5F); - rightCallback.run(); - } - } - } - } - private void processVREvents() { while (!this.vrEvents.isEmpty()) { VREvent vrevent = this.vrEvents.poll(); @@ -1272,7 +1156,7 @@ long getInputSourceHandle(String path) { } } - ControllerType getOriginControllerType(long inputValueHandle) { + public ControllerType getOriginControllerType(long inputValueHandle) { if (inputValueHandle == 0L) { return null; } else { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java index 1d386114e..8b31b1875 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java @@ -1,5 +1,6 @@ package org.vivecraft.client_vr.provider.openvr_lwjgl; +import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.TextureUtil; import com.mojang.blaze3d.systems.RenderSystem; @@ -14,7 +15,8 @@ import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; import org.vivecraft.client.utils.Utils; -import org.vivecraft.client_vr.provider.MCVR; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRTextureTarget; import org.vivecraft.client_vr.provider.VRRenderer; import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.render.RenderPass; @@ -26,10 +28,14 @@ public class OpenVRStereoRenderer extends VRRenderer { private final HiddenAreaMesh[] hiddenMeshes = new HiddenAreaMesh[2]; private final MCOpenVR openvr; + protected int LeftEyeTextureId = -1; + protected int RightEyeTextureId = -1; + public RenderTarget framebufferEye0; + public RenderTarget framebufferEye1; - public OpenVRStereoRenderer(MCVR vr) { + public OpenVRStereoRenderer(MCOpenVR vr) { super(vr); - this.openvr = (MCOpenVR) vr; + this.openvr = vr; hiddenMeshes[0] = HiddenAreaMesh.calloc(); hiddenMeshes[1] = HiddenAreaMesh.calloc(); } @@ -85,7 +91,7 @@ public String getLastError() { return ""; } - public void createRenderTexture(int lwidth, int lheight) { + public void createRenderTexture(int lwidth, int lheight) throws RenderConfigException { this.LeftEyeTextureId = GlStateManager._genTexture(); int i = GlStateManager._getInteger(GL11.GL_TEXTURE_BINDING_2D); RenderSystem.bindTexture(this.LeftEyeTextureId); @@ -107,6 +113,25 @@ public void createRenderTexture(int lwidth, int lheight) { this.openvr.texType1.handle(this.RightEyeTextureId); this.openvr.texType1.eColorSpace(VR.EColorSpace_ColorSpace_Gamma); this.openvr.texType1.eType(VR.ETextureType_TextureType_OpenGL); + + ClientDataHolderVR dataholder = ClientDataHolderVR.getInstance(); + if (this.LeftEyeTextureId == -1) { + throw new RenderConfigException("Failed to initialise stereo rendering plugin: " + this.getName(), Component.literal(this.getLastError())); + } + + this.checkGLError("Render Texture setup"); + + if (this.framebufferEye0 == null) { + this.framebufferEye0 = new VRTextureTarget("L Eye", lwidth, lheight, false, false, this.LeftEyeTextureId, false, true, false); + dataholder.print(this.framebufferEye0.toString()); + this.checkGLError("Left Eye framebuffer setup"); + } + + if (this.framebufferEye1 == null) { + this.framebufferEye1 = new VRTextureTarget("R Eye", lwidth, lheight, false, false, this.RightEyeTextureId, false, true, false); + dataholder.print(this.framebufferEye1.toString()); + this.checkGLError("Right Eye framebuffer setup"); + } } public boolean endFrame(RenderPass eye) { @@ -169,6 +194,16 @@ public boolean providesStencilMask() { return true; } + @Override + public RenderTarget getLeftEyeTarget() { + return framebufferEye0; + } + + @Override + public RenderTarget getRightEyeTarget() { + return framebufferEye1; + } + public float[] getStencilMask(RenderPass eye) { if (this.hiddenMesheVertecies != null && (eye == RenderPass.LEFT || eye == RenderPass.RIGHT)) { return eye == RenderPass.LEFT ? this.hiddenMesheVertecies[0] : this.hiddenMesheVertecies[1]; @@ -192,6 +227,15 @@ public String getinitError() { @Override public void destroy() { super.destroy(); + if (this.framebufferEye0 != null) { + this.framebufferEye0.destroyBuffers(); + this.framebufferEye0 = null; + } + + if (this.framebufferEye1 != null) { + this.framebufferEye1.destroyBuffers(); + this.framebufferEye1 = null; + } if (this.LeftEyeTextureId > -1) { TextureUtil.releaseTextureId(this.LeftEyeTextureId); this.LeftEyeTextureId = -1; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/VivecraftMovementInput.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/VivecraftMovementInput.java deleted file mode 100644 index e61de8da0..000000000 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/control/VivecraftMovementInput.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.vivecraft.client_vr.provider.openvr_lwjgl.control; - -import net.minecraft.client.KeyMapping; -import org.vivecraft.client_vr.provider.MCVR; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; - -public class VivecraftMovementInput { - public static float getMovementAxisValue(KeyMapping keyBinding) { - VRInputAction vrinputaction = MCVR.get().getInputAction(keyBinding); - return Math.abs(vrinputaction.getAxis1DUseTracked()); - } -} diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java new file mode 100644 index 000000000..90444000a --- /dev/null +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -0,0 +1,1494 @@ +package org.vivecraft.client_vr.provider.openxr; + +import com.mojang.blaze3d.platform.Window; +import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec3; +import org.apache.commons.lang3.tuple.Pair; +import org.joml.Vector2f; +import org.lwjgl.PointerBuffer; +import org.lwjgl.glfw.*; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL21; +import org.lwjgl.opengl.GL30; +import org.lwjgl.opengl.GL31; +import org.lwjgl.openxr.*; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.Platform; +import org.lwjgl.system.Struct; +import org.lwjgl.system.linux.X11; +import org.lwjgl.system.windows.User32; +import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client.utils.Utils; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; +import org.vivecraft.client_vr.gameplay.screenhandlers.RadialHandler; +import org.vivecraft.client_vr.provider.ControllerType; +import org.vivecraft.client_vr.provider.InputSimulator; +import org.vivecraft.client_vr.provider.MCVR; +import org.vivecraft.client_vr.provider.VRRenderer; +import org.vivecraft.client_vr.provider.control.VRInputAction; +import org.vivecraft.client_vr.provider.control.VRInputActionSet; +import org.vivecraft.client_vr.render.RenderConfigException; +import org.vivecraft.client_vr.render.RenderPass; +import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.client_xr.render_pass.RenderPassManager; +import org.vivecraft.common.utils.lwjgl.Vector3f; +import org.vivecraft.common.utils.math.Matrix4f; +import org.vivecraft.common.utils.math.Vector3; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; +import java.util.*; + +import static org.lwjgl.opengl.GLX13.*; +import static org.lwjgl.system.MemoryStack.*; +import static org.lwjgl.system.MemoryUtil.*; + +public class MCOpenXR extends MCVR { + + private static MCOpenXR ome; + public XrInstance instance; + public XrSession session; + public XrSpace xrAppSpace; + public XrSpace xrViewSpace; + public XrSwapchain swapchain; + public final XrEventDataBuffer eventDataBuffer = XrEventDataBuffer.calloc(); + public long time; + private boolean tried; + private long systemID; + public XrView.Buffer viewBuffer; + public int width; + public int height; + //TODO either move to MCVR, Or make special for OpenXR holding the instance itself. + private final Map actionSetHandles = new EnumMap<>(VRInputActionSet.class); + //TODO Move to MCVR + private XrActiveActionSet.Buffer activeActionSetsBuffer; + private boolean isActive; + private final HashMap paths = new HashMap<>(); + private final long[] grip = new long[2]; + private final long[] aim = new long[2]; + private final XrSpace[] gripSpace = new XrSpace[2]; + private final XrSpace[] aimSpace = new XrSpace[2]; + public static final XrPosef POSE_IDENTITY = XrPosef.calloc().set( + XrQuaternionf.calloc().set(0, 0, 0, 1), + XrVector3f.calloc() + ); + public boolean shouldRender = true; + public long[] haptics = new long[2]; + public String systemName; + + + public MCOpenXR(Minecraft mc, ClientDataHolderVR dh) { + super(mc, dh, VivecraftVRMod.INSTANCE); + ome = this; + this.hapticScheduler = new OpenXRHapticSchedular(); + + } + + @Override + public String getName() { + return "OpenXR"; + } + + @Override + public String getID() { + return "openxr"; + } + + @Override + public void destroy() { + int error; + //Not sure if we need the action sets one here, as we are shutting down + for (Long inputActionSet : actionSetHandles.values()){ + error = XR10.xrDestroyActionSet(new XrActionSet(inputActionSet, instance)); + logError(error, "xrDestroyActionSet", ""); + } + if (swapchain != null) { + error = XR10.xrDestroySwapchain(swapchain); + logError(error, "xrDestroySwapchain", ""); + } + if (viewBuffer != null) { + viewBuffer.close(); + } + if (xrAppSpace != null) { + error = XR10.xrDestroySpace(xrAppSpace); + logError(error, "xrDestroySpace", "xrAppSpace"); + } + if (xrViewSpace != null) { + error = XR10.xrDestroySpace(xrViewSpace); + logError(error, "xrDestroySpace", "xrViewSpace"); + } + if (session != null){ + error = XR10.xrDestroySession(session); + logError(error, "xrDestroySession", ""); + } + if (instance != null){ + error = XR10.xrDestroyInstance(instance); + logError(error, "xrDestroyInstance", ""); + } + eventDataBuffer.close(); + } + + @Override + protected void triggerBindingHapticPulse(KeyMapping binding, int duration) { + ControllerType controllertype = this.findActiveBindingControllerType(binding); + + if (controllertype != null) { + this.triggerHapticPulse(controllertype, duration); + } + } + + @Override + protected ControllerType findActiveBindingControllerType(KeyMapping binding) { + if (!this.inputInitialized) { + return null; + } else { + long path = this.getInputAction(binding).getLastOrigin(); + try (MemoryStack stack = MemoryStack.stackPush()) { + IntBuffer buf = stack.callocInt(1); + int error = XR10.xrPathToString(instance, path, buf, null); + logError(error, "xrPathToString", "get string length for", binding.getName()); + + int size = buf.get(); + if (size <= 0) { + return null; + } + + buf = stack.callocInt(size); + ByteBuffer byteBuffer = stack.calloc(size); + error = XR10.xrPathToString(instance, path, buf, byteBuffer); + logError(error, "xrPathToString", "get string for", binding.getName()); + byte[] bytes = new byte[byteBuffer.remaining()]; + byteBuffer.get(bytes); + String name = new String(bytes); + if (name.contains("right")) { + return ControllerType.RIGHT; + } + return ControllerType.LEFT; + } + } + } + + @Override + public void poll(long var1) { + if (this.initialized) { + this.mc.getProfiler().push("events"); + //pollVREvents(); + + if (!this.dh.vrSettings.seated) { + this.mc.getProfiler().popPush("controllers"); + this.mc.getProfiler().push("gui"); + + if (this.mc.screen == null && this.dh.vrSettings.vrTouchHotbar) { + + if (this.dh.vrSettings.vrHudLockMode != VRSettings.HUDLock.HEAD && this.hudPopup) { + this.processHotbar(); + } + } + + this.mc.getProfiler().pop(); + } + this.mc.getProfiler().popPush("updatePose/Vsync"); + this.updatePose(); + this.mc.getProfiler().popPush("processInputs"); + this.processInputs(); + this.mc.getProfiler().popPush("hmdSampling"); + this.hmdSampling(); + this.mc.getProfiler().pop(); + } + } + + private void updatePose() { + RenderPassManager.setGUIRenderPass(); + + if (mc == null) { + return; + } + try (MemoryStack stack = MemoryStack.stackPush()) { + XrFrameState frameState = XrFrameState.calloc(stack).type(XR10.XR_TYPE_FRAME_STATE); + + int error = XR10.xrWaitFrame( + session, + XrFrameWaitInfo.calloc(stack).type(XR10.XR_TYPE_FRAME_WAIT_INFO), + frameState); + logError(error, "xrWaitFrame", ""); + + time = frameState.predictedDisplayTime(); + this.shouldRender = frameState.shouldRender(); + + error = XR10.xrBeginFrame( + session, + XrFrameBeginInfo.calloc(stack).type(XR10.XR_TYPE_FRAME_BEGIN_INFO)); + logError(error, "xrBeginFrame", ""); + + + XrViewState viewState = XrViewState.calloc(stack).type(XR10.XR_TYPE_VIEW_STATE); + IntBuffer intBuf = stack.callocInt(1); + + XrViewLocateInfo viewLocateInfo = XrViewLocateInfo.calloc(stack); + viewLocateInfo.set(XR10.XR_TYPE_VIEW_LOCATE_INFO, + 0, + XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, + frameState.predictedDisplayTime(), + xrAppSpace + ); + + error = XR10.xrLocateViews(session, viewLocateInfo, viewState, intBuf, viewBuffer); + logError(error, "xrLocateViews", ""); + + XrSpaceLocation space_location = XrSpaceLocation.calloc(stack).type(XR10.XR_TYPE_SPACE_LOCATION); + + //HMD pose + error = XR10.xrLocateSpace(xrViewSpace, xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "xrViewSpace"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.hmdPose); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.hmdRotation); + + Vec3 vec3 = new Vec3(space_location.pose().position$().x(), space_location.pose().position$().y(), space_location.pose().position$().z()); + this.hmdHistory.add(vec3); + Vector3 vector3 = this.hmdRotation.transform(new Vector3(0.0F, -0.1F, 0.1F)); + this.hmdPivotHistory.add(new Vec3((double) vector3.getX() + vec3.x, (double) vector3.getY() + vec3.y, (double) vector3.getZ() + vec3.z)); + headIsTracking = true; + } else { + headIsTracking = false; + } + + //Eye positions + OpenXRUtil.openXRPoseToMarix(viewBuffer.get(0).pose(), this.hmdPoseLeftEye); + OpenXRUtil.openXRPoseToMarix(viewBuffer.get(1).pose(), this.hmdPoseRightEye); + + //reverse + if (this.dh.vrSettings.reverseHands) { + XrSpace temp = gripSpace[0]; + gripSpace[0] = gripSpace[1]; + gripSpace[1] = temp; + temp = aimSpace[0]; + aimSpace[0] = aimSpace[1]; + aimSpace[1] = temp; + } + + //Controller aim and grip poses + error = XR10.xrLocateSpace(gripSpace[0], xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "gripSpace[0]"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.handRotation[0]); + } + + error = XR10.xrLocateSpace(gripSpace[1], xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "gripSpace[1]"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.handRotation[1]); + } + + error = XR10.xrLocateSpace(aimSpace[0], xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "aimSpace[0]"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.controllerPose[0]); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.controllerRotation[0]); + this.aimSource[0] = new Vec3(space_location.pose().position$().x(), space_location.pose().position$().y(), space_location.pose().position$().z()); + this.controllerHistory[0].add(this.getAimSource(0)); + this.controllerForwardHistory[0].add(this.getAimSource(0)); + Vec3 vec33 = this.controllerRotation[0].transform(this.up).toVector3d(); + this.controllerUpHistory[0].add(vec33); + this.controllerTracking[0] = true; + } else { + this.controllerTracking[0] = false; + } + + error = XR10.xrLocateSpace(aimSpace[1], xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "aimSpace[1]"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.controllerPose[1]); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.controllerRotation[1]); + this.aimSource[1] = new Vec3(space_location.pose().position$().x(), space_location.pose().position$().y(), space_location.pose().position$().z()); + this.controllerHistory[1].add(this.getAimSource(1)); + this.controllerForwardHistory[1].add(this.getAimSource(1)); + Vec3 vec32 = this.controllerRotation[1].transform(this.up).toVector3d(); + this.controllerUpHistory[1].add(vec32); + this.controllerTracking[1] = true; + } else { + this.controllerTracking[1] = false; + } + + //TODO merge with updateAim so it's one method + if (this.dh.vrSettings.seated) { + this.controllerPose[0] = this.hmdPose.inverted().inverted(); + this.controllerPose[1] = this.hmdPose.inverted().inverted(); + this.handRotation[0] = hmdRotation; + this.handRotation[1] = hmdRotation; + this.controllerRotation[0] = hmdRotation; + this.controllerRotation[1] = hmdRotation; + this.aimSource[1] = this.getCenterEyePosition(); + this.aimSource[0] = this.getCenterEyePosition(); + + if (this.mc.screen == null) { + Vec3 vec31 = this.getAimVector(1); + org.vivecraft.common.utils.lwjgl.Matrix4f matrix4f = new org.vivecraft.common.utils.lwjgl.Matrix4f(); + float f = 110.0F; + float f1 = 180.0F; + double d0 = this.mc.mouseHandler.xpos() / (double) this.mc.getWindow().getScreenWidth() * (double) f - (double) (f / 2.0F); + int i = this.mc.getWindow().getScreenHeight(); + + if (i % 2 != 0) { + --i; + } + + double d1 = -this.mc.mouseHandler.ypos() / (double) i * (double) f1 + (double) (f1 / 2.0F); + double d2 = -d1; + + if (this.mc.isWindowActive()) { + float f2 = this.dh.vrSettings.keyholeX; + float f3 = 20.0F * this.dh.vrSettings.xSensitivity; + int j = (int) ((double) (-f2 + f / 2.0F) * (double) this.mc.getWindow().getScreenWidth() / (double) f) + 1; + int k = (int) ((double) (f2 + f / 2.0F) * (double) this.mc.getWindow().getScreenWidth() / (double) f) - 1; + float f4 = ((float) Math.abs(d0) - f2) / (f / 2.0F - f2); + double d3 = this.mc.mouseHandler.xpos(); + + if (d0 < (double) (-f2)) { + this.seatedRot += f3 * f4; + this.seatedRot %= 360.0F; + this.hmdForwardYaw = (float) Math.toDegrees(Math.atan2(vec31.x, vec31.z)); + d3 = j; + d0 = -f2; + } else if (d0 > (double) f2) { + this.seatedRot -= f3 * f4; + this.seatedRot %= 360.0F; + this.hmdForwardYaw = (float) Math.toDegrees(Math.atan2(vec31.x, vec31.z)); + d3 = k; + d0 = f2; + } + + double d4 = 0.5D * (double) this.dh.vrSettings.ySensitivity; + d2 = (double) this.aimPitch + d1 * d4; + d2 = Mth.clamp(d2, -89.9D, 89.9D); + InputSimulator.setMousePos(d3, i / 2); + GLFW.glfwSetCursorPos(this.mc.getWindow().getWindow(), d3, i / 2); + matrix4f.rotate((float) Math.toRadians(-d2), new Vector3f(1.0F, 0.0F, 0.0F)); + matrix4f.rotate((float) Math.toRadians(-180.0D + d0 - (double) this.hmdForwardYaw), new Vector3f(0.0F, 1.0F, 0.0F)); + } + + this.controllerRotation[0].M[0][0] = matrix4f.m00; + this.controllerRotation[0].M[0][1] = matrix4f.m01; + this.controllerRotation[0].M[0][2] = matrix4f.m02; + this.controllerRotation[0].M[1][0] = matrix4f.m10; + this.controllerRotation[0].M[1][1] = matrix4f.m11; + this.controllerRotation[0].M[1][2] = matrix4f.m12; + this.controllerRotation[0].M[2][0] = matrix4f.m20; + this.controllerRotation[0].M[2][1] = matrix4f.m21; + this.controllerRotation[0].M[2][2] = matrix4f.m22; + + this.handRotation[0].M[0][0] = matrix4f.m00; + this.handRotation[0].M[0][1] = matrix4f.m01; + this.handRotation[0].M[0][2] = matrix4f.m02; + this.handRotation[0].M[1][0] = matrix4f.m10; + this.handRotation[0].M[1][1] = matrix4f.m11; + this.handRotation[0].M[1][2] = matrix4f.m12; + this.handRotation[0].M[2][0] = matrix4f.m20; + this.handRotation[0].M[2][1] = matrix4f.m21; + this.handRotation[0].M[2][2] = matrix4f.m22; + } + } + Vec3 vec32 = this.getAimVector(0); + this.aimPitch = (float) Math.toDegrees(Math.asin(vec32.y / vec32.length())); + + if (this.inputInitialized) { + this.mc.getProfiler().push("updateActionState"); + + if (this.updateActiveActionSets()) { + XrActionsSyncInfo syncInfo = XrActionsSyncInfo.calloc(stack) + .type(XR10.XR_TYPE_ACTIONS_SYNC_INFO) + .activeActionSets(activeActionSetsBuffer); + error = XR10.xrSyncActions(session, syncInfo); + logError(error, "xrSyncActions", ""); + } + + this.inputActions.values().forEach(this::readNewData); + + //TODO Not needed it seems? Poses come from the action space + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); + this.readPoseData(this.grip[0], actionSet); + this.readPoseData(this.grip[1], actionSet); + this.readPoseData(this.aim[0], actionSet); + this.readPoseData(this.aim[1], actionSet); + + this.mc.getProfiler().pop(); + } + } + } + + @Override + public Vec3 getEyePosition(RenderPass eye) { + org.vivecraft.common.utils.math.Matrix4f matrix4f = null; + + if (eye == RenderPass.LEFT) { + matrix4f = this.hmdPoseLeftEye; + } else if (eye == RenderPass.RIGHT) { + matrix4f = this.hmdPoseRightEye; + } + + if (matrix4f == null) { + org.vivecraft.common.utils.math.Matrix4f matrix4f2 = this.hmdPose; + Vector3 vector31 = Utils.convertMatrix4ftoTranslationVector(matrix4f2); + + if (this.dh.vrSettings.seated || this.dh.vrSettings.allowStandingOriginOffset) { + if (this.dh.vr.isHMDTracking()) { + vector31 = vector31.add(this.dh.vrSettings.originOffset); + } + } + + return vector31.toVector3d(); + } else { + Vector3 vector3 = Utils.convertMatrix4ftoTranslationVector(matrix4f); + + if (this.dh.vrSettings.seated || this.dh.vrSettings.allowStandingOriginOffset) { + if (this.dh.vr.isHMDTracking()) { + vector3 = vector3.add(this.dh.vrSettings.originOffset); + } + } + + return vector3.toVector3d(); + } + } + + @Override + public org.vivecraft.common.utils.math.Matrix4f getEyeRotation(RenderPass eye) { + org.vivecraft.common.utils.math.Matrix4f matrix4f; + + if (eye == RenderPass.LEFT) { + matrix4f = this.hmdPoseLeftEye; + } else if (eye == RenderPass.RIGHT) { + matrix4f = this.hmdPoseRightEye; + } else { + matrix4f = null; + } + + if (matrix4f != null) { + org.vivecraft.common.utils.math.Matrix4f matrix4f1 = new org.vivecraft.common.utils.math.Matrix4f(); + matrix4f1.M[0][0] = matrix4f.M[0][0]; + matrix4f1.M[0][1] = matrix4f.M[0][1]; + matrix4f1.M[0][2] = matrix4f.M[0][2]; + matrix4f1.M[0][3] = 0.0F; + matrix4f1.M[1][0] = matrix4f.M[1][0]; + matrix4f1.M[1][1] = matrix4f.M[1][1]; + matrix4f1.M[1][2] = matrix4f.M[1][2]; + matrix4f1.M[1][3] = 0.0F; + matrix4f1.M[2][0] = matrix4f.M[2][0]; + matrix4f1.M[2][1] = matrix4f.M[2][1]; + matrix4f1.M[2][2] = matrix4f.M[2][2]; + matrix4f1.M[2][3] = 0.0F; + matrix4f1.M[3][0] = 0.0F; + matrix4f1.M[3][1] = 0.0F; + matrix4f1.M[3][2] = 0.0F; + matrix4f1.M[3][3] = 1.0F; + return matrix4f1; + } else { + return this.hmdRotation; + } + } + + public void readNewData(VRInputAction action) { + String s = action.type; + + switch (s) { + case "boolean": + if (action.isHanded()) { + for (ControllerType controllertype1 : ControllerType.values()) { + this.readBoolean(action, controllertype1); + } + } else { + this.readBoolean(action, null); + } + + break; + + case "vector1": + if (action.isHanded()) { + for (ControllerType controllertype : ControllerType.values()) { + this.readFloat(action, controllertype); + } + } else { + this.readFloat(action, null); + } + break; + + case "vector2": + if (action.isHanded()) { + for (ControllerType controllertype : ControllerType.values()) { + this.readVecData(action, controllertype); + } + } else { + this.readVecData(action, null); + } + break; + + case "vector3": + + } + } + + private void readBoolean(VRInputAction action, ControllerType hand) { + int i = 0; + + if (hand != null) { + i = hand.ordinal(); + } + try (MemoryStack stack = MemoryStack.stackPush()){ + XrActionStateGetInfo info = XrActionStateGetInfo.calloc(stack); + info.type(XR10.XR_TYPE_ACTION_STATE_GET_INFO); + info.action(new XrAction(action.handle, new XrActionSet(actionSetHandles.get(action.actionSet), instance))); + XrActionStateBoolean state = XrActionStateBoolean.calloc(stack).type(XR10.XR_TYPE_ACTION_STATE_BOOLEAN); + int error = XR10.xrGetActionStateBoolean(session, info, state); + logError(error, "xrGetActionStateBoolean", action.name); + + action.digitalData[i].state = state.currentState(); + action.digitalData[i].isActive = state.isActive(); + action.digitalData[i].isChanged = state.changedSinceLastSync(); + action.digitalData[i].activeOrigin = getOrigins(action).get(0); + } + } + + private void readFloat(VRInputAction action, ControllerType hand) { + int i = 0; + + if (hand != null) { + i = hand.ordinal(); + } + try (MemoryStack stack = MemoryStack.stackPush()){ + XrActionStateGetInfo info = XrActionStateGetInfo.calloc(stack); + info.type(XR10.XR_TYPE_ACTION_STATE_GET_INFO); + info.action(new XrAction(action.handle, new XrActionSet(actionSetHandles.get(action.actionSet), instance))); + XrActionStateFloat state = XrActionStateFloat.calloc(stack).type(XR10.XR_TYPE_ACTION_STATE_FLOAT); + int error = XR10.xrGetActionStateFloat(session, info, state); + logError(error, "xrGetActionStateFloat", action.name); + + action.analogData[i].deltaX = action.analogData[i].x - state.currentState(); + action.analogData[i].x = state.currentState(); + action.analogData[i].activeOrigin = getOrigins(action).get(0); + action.analogData[i].isActive = state.isActive(); + action.analogData[i].isChanged = state.changedSinceLastSync(); + } + } + + private void readVecData(VRInputAction action, ControllerType hand) { + int i = 0; + + if (hand != null) { + i = hand.ordinal(); + } + try (MemoryStack stack = MemoryStack.stackPush()){ + XrActionStateGetInfo info = XrActionStateGetInfo.calloc(stack); + info.type(XR10.XR_TYPE_ACTION_STATE_GET_INFO); + info.action(new XrAction(action.handle, new XrActionSet(actionSetHandles.get(action.actionSet), instance))); + XrActionStateVector2f state = XrActionStateVector2f.calloc(stack).type(XR10.XR_TYPE_ACTION_STATE_VECTOR2F); + int error = XR10.xrGetActionStateVector2f(session, info, state); + logError(error, "xrGetActionStateVector2f", action.name); + + action.analogData[i].deltaX = action.analogData[i].x - state.currentState().x(); + action.analogData[i].deltaY = action.analogData[i].y - state.currentState().y(); + action.analogData[i].x = state.currentState().x(); + action.analogData[i].y = state.currentState().y(); + action.analogData[i].activeOrigin = getOrigins(action).get(0); + action.analogData[i].isActive = state.isActive(); + action.analogData[i].isChanged = state.changedSinceLastSync(); + } + } + + private void readPoseData(Long action, XrActionSet set) { + try (MemoryStack stack = MemoryStack.stackPush()){ + XrActionStateGetInfo info = XrActionStateGetInfo.calloc(stack); + info.type(XR10.XR_TYPE_ACTION_STATE_GET_INFO); + info.action(new XrAction(action, set)); + XrActionStatePose state = XrActionStatePose.calloc(stack).type(XR10.XR_TYPE_ACTION_STATE_POSE); + int error = XR10.xrGetActionStatePose(session, info, state); + logError(error, "xrGetActionStatePose", ""); + } + } + + private boolean updateActiveActionSets() { + ArrayList arraylist = new ArrayList<>(); + arraylist.add(VRInputActionSet.GLOBAL); + + // we are always modded + arraylist.add(VRInputActionSet.MOD); + + arraylist.add(VRInputActionSet.MIXED_REALITY); + arraylist.add(VRInputActionSet.TECHNICAL); + + if (this.mc.screen == null) { + arraylist.add(VRInputActionSet.INGAME); + arraylist.add(VRInputActionSet.CONTEXTUAL); + } else { + arraylist.add(VRInputActionSet.GUI); + if (ClientDataHolderVR.getInstance().vrSettings.ingameBindingsInGui) { + arraylist.add(VRInputActionSet.INGAME); + } + } + + if (KeyboardHandler.Showing || RadialHandler.isShowing()) { + arraylist.add(VRInputActionSet.KEYBOARD); + } + + if (this.activeActionSetsBuffer == null) { + activeActionSetsBuffer = XrActiveActionSet.calloc(arraylist.size()); + } else if (activeActionSetsBuffer.capacity() != arraylist.size()) { + activeActionSetsBuffer.close(); + activeActionSetsBuffer = XrActiveActionSet.calloc(arraylist.size()); + } + + for (int i = 0; i < arraylist.size(); ++i) { + VRInputActionSet vrinputactionset = arraylist.get(i); + activeActionSetsBuffer.get(i).set(new XrActionSet(this.getActionSetHandle(vrinputactionset), instance), NULL); + } + + return !arraylist.isEmpty(); + } + + private void updateControllerPose(int controller, long actionHandle) { + + } + + long getActionSetHandle(VRInputActionSet actionSet) { + return this.actionSetHandles.get(actionSet); + } + + private void pollVREvents() { + while (true) { + eventDataBuffer.clear(); + eventDataBuffer.type(XR10.XR_TYPE_EVENT_DATA_BUFFER); + int error = XR10.xrPollEvent(instance, eventDataBuffer); + logError(error, "xrPollEvent", ""); + if (error != XR10.XR_SUCCESS) { + break; + } + XrEventDataBaseHeader event = XrEventDataBaseHeader.create(eventDataBuffer.address()); + + switch (event.type()) { + case XR10.XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING -> { + XrEventDataInstanceLossPending instanceLossPending = XrEventDataInstanceLossPending.create(event.address()); + } + case XR10.XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED -> { + this.sessionChanged(XrEventDataSessionStateChanged.create(event.address())); + } + case XR10.XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED -> { + } + case XR10.XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING -> { + } + default -> { + } + } + } + } + + private void sessionChanged(XrEventDataSessionStateChanged xrEventDataSessionStateChanged) { + int state = xrEventDataSessionStateChanged.state(); + + switch (state) { + case XR10.XR_SESSION_STATE_READY: { + try (MemoryStack stack = MemoryStack.stackPush()){ + XrSessionBeginInfo sessionBeginInfo = XrSessionBeginInfo.calloc(stack); + sessionBeginInfo.type(XR10.XR_TYPE_SESSION_BEGIN_INFO); + sessionBeginInfo.next(NULL); + sessionBeginInfo.primaryViewConfigurationType(XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO); + + int error = XR10.xrBeginSession(session, sessionBeginInfo); + logError(error, "xrBeginSession", "XR_SESSION_STATE_READY"); + } + this.isActive = true; + break; + } + case XR10.XR_SESSION_STATE_STOPPING: { + this.isActive = false; + int error = XR10.xrEndSession(session); + logError(error, "xrEndSession", "XR_SESSION_STATE_STOPPING"); + } + case XR10.XR_SESSION_STATE_VISIBLE, XR10.XR_SESSION_STATE_FOCUSED: { + this.isActive = true; + break; + } + case XR10.XR_SESSION_STATE_EXITING, XR10.XR_SESSION_STATE_IDLE, XR10.XR_SESSION_STATE_SYNCHRONIZED: { + this.isActive = false; + break; + } + case XR10.XR_SESSION_STATE_LOSS_PENDING: { + break; + } + default: + break; + } + } + + @Override + public Vector2f getPlayAreaSize() { + try (MemoryStack stack = MemoryStack.stackPush()) { + XrExtent2Df vec = XrExtent2Df.calloc(stack); + int error = XR10.xrGetReferenceSpaceBoundsRect(session, XR10.XR_REFERENCE_SPACE_TYPE_STAGE, vec); + logError(error, "xrGetReferenceSpaceBoundsRect", ""); + return new Vector2f(vec.width(), vec.height()); + } + } + + @Override + public boolean init() { + if (this.initialized) { + return true; + } else if (this.tried) { + return this.initialized; + } else { + tried = true; + this.mc = Minecraft.getInstance(); + try { + this.initializeOpenXRInstance(); + this.initializeOpenXRSession(); + this.initializeOpenXRSpace(); + this.initializeOpenXRSwapChain(); + } catch (Exception e) { + e.printStackTrace(); + this.initSuccess = false; + this.initStatus = e.getLocalizedMessage(); + return false; + } + + //TODO Seated when no controllers + + System.out.println("OpenXR initialized & VR connected."); + this.deviceVelocity = new Vec3[64]; + + for (int i = 0; i < this.poseMatrices.length; ++i) { + this.poseMatrices[i] = new Matrix4f(); + this.deviceVelocity[i] = new Vec3(0.0D, 0.0D, 0.0D); + } + + this.initialized = true; + return true; + } + } + + private void initializeOpenXRInstance() { + try (MemoryStack stack = MemoryStack.stackPush()) { + + //Check extensions + IntBuffer numExtensions = stack.callocInt(1); + int error = XR10.xrEnumerateInstanceExtensionProperties((ByteBuffer) null, numExtensions, null); + logError(error, "xrEnumerateInstanceExtensionProperties", "get count"); + + XrExtensionProperties.Buffer properties = new XrExtensionProperties.Buffer( + bufferStack(numExtensions.get(0), XrExtensionProperties.SIZEOF, XR10.XR_TYPE_EXTENSION_PROPERTIES) + ); + + //Load extensions + error = XR10.xrEnumerateInstanceExtensionProperties((ByteBuffer) null, numExtensions, properties); + logError(error, "xrEnumerateInstanceExtensionProperties", "get extensions"); + + //get needed extensions + boolean missingOpenGL = true; + PointerBuffer extensions = stack.callocPointer(3); + while (properties.hasRemaining()) { + XrExtensionProperties prop = properties.get(); + String extensionName = prop.extensionNameString(); + if (extensionName.equals(KHROpenGLEnable.XR_KHR_OPENGL_ENABLE_EXTENSION_NAME)) { + missingOpenGL = false; + extensions.put(memAddress(stackUTF8(KHROpenGLEnable.XR_KHR_OPENGL_ENABLE_EXTENSION_NAME))); + } + if (extensionName.equals(EXTHPMixedRealityController.XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME)) { + extensions.put(memAddress(stackUTF8(EXTHPMixedRealityController.XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))); + } + if (extensionName.equals(HTCViveCosmosControllerInteraction.XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME)) { + extensions.put(memAddress(stackUTF8(HTCViveCosmosControllerInteraction.XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME))); + } + } + + if (missingOpenGL) { + throw new RuntimeException("OpenXR runtime does not support OpenGL, try using SteamVR instead"); + } + + //Create APP info + XrApplicationInfo applicationInfo = XrApplicationInfo.calloc(stack); + applicationInfo.apiVersion(XR10.XR_CURRENT_API_VERSION); + applicationInfo.applicationName(stack.UTF8("Vivecraft")); + applicationInfo.applicationVersion(1); + + //Create instance info + XrInstanceCreateInfo createInfo = XrInstanceCreateInfo.calloc(stack); + createInfo.type(XR10.XR_TYPE_INSTANCE_CREATE_INFO); + createInfo.next(NULL); + createInfo.createFlags(0); + createInfo.applicationInfo(applicationInfo); + createInfo.enabledApiLayerNames(null); + createInfo.enabledExtensionNames(extensions.flip()); + + //Create XR instance + PointerBuffer instancePtr = stack.callocPointer(1); + int xrResult = XR10.xrCreateInstance(createInfo, instancePtr); + if (xrResult == XR10.XR_ERROR_RUNTIME_FAILURE) { + throw new RuntimeException("Failed to create xrInstance, are you sure your headset is plugged in?"); + } else if (xrResult == XR10.XR_ERROR_INSTANCE_LOST) { + throw new RuntimeException("Failed to create xrInstance due to runtime updating"); + } else if (xrResult < 0) { + throw new RuntimeException("XR method returned " + xrResult); + } + instance = new XrInstance(instancePtr.get(0), createInfo); + + this.poseMatrices = new Matrix4f[64]; + + for (int i = 0; i < this.poseMatrices.length; ++i) { + this.poseMatrices[i] = new Matrix4f(); + } + + this.initSuccess = true; + } + } + + public static MCOpenXR get() { + return ome; + } + + private void initializeOpenXRSession() { + try (MemoryStack stack = MemoryStack.stackPush()) { + //Create system + XrSystemGetInfo system = XrSystemGetInfo.calloc(stack); + system.type(XR10.XR_TYPE_SYSTEM_GET_INFO); + system.next(NULL); + system.formFactor(XR10.XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY); + + LongBuffer longBuffer = stack.callocLong(1); + int error = XR10.xrGetSystem(instance, system, longBuffer); + logError(error, "xrGetSystem", ""); + this.systemID = longBuffer.get(0); + + if (systemID == 0) { + throw new RuntimeException("No compatible headset detected"); + } + + //Bind graphics + Struct graphics = this.getGraphicsAPI(stack); + + //Create session + XrSessionCreateInfo info = XrSessionCreateInfo.calloc(stack); + info.type(XR10.XR_TYPE_SESSION_CREATE_INFO); + info.next(graphics.address()); + info.createFlags(0); + info.systemId(systemID); + + PointerBuffer sessionPtr = stack.callocPointer(1); + error = XR10.xrCreateSession(instance, info, sessionPtr); + logError(error, "xrCreateSession", ""); + + session = new XrSession(sessionPtr.get(0), instance); + + XrSessionBeginInfo sessionBeginInfo = XrSessionBeginInfo.calloc(stack); + sessionBeginInfo.type(XR10.XR_TYPE_SESSION_BEGIN_INFO); + sessionBeginInfo.next(NULL); + sessionBeginInfo.primaryViewConfigurationType(XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO); + + error = XR10.xrBeginSession(session, sessionBeginInfo); + logError(error, "xrBeginSession", ""); + this.isActive = true; + + } + } + + private void initializeOpenXRSpace() { + try (MemoryStack stack = MemoryStack.stackPush()){ + XrPosef identityPose = XrPosef.calloc(stack); + identityPose.set( + XrQuaternionf.calloc(stack).set(0, 0, 0, 1), + XrVector3f.calloc(stack) + ); + + XrReferenceSpaceCreateInfo referenceSpaceCreateInfo = XrReferenceSpaceCreateInfo.calloc(stack); + referenceSpaceCreateInfo.type(XR10.XR_TYPE_REFERENCE_SPACE_CREATE_INFO); + referenceSpaceCreateInfo.next(NULL); + referenceSpaceCreateInfo.referenceSpaceType(XR10.XR_REFERENCE_SPACE_TYPE_STAGE); + referenceSpaceCreateInfo.poseInReferenceSpace(identityPose); + + PointerBuffer pp = stack.callocPointer(1); + int error = XR10.xrCreateReferenceSpace(session, referenceSpaceCreateInfo, pp); + xrAppSpace = new XrSpace(pp.get(0), session); + logError(error, "xrCreateReferenceSpace", "XR_REFERENCE_SPACE_TYPE_STAGE"); + + referenceSpaceCreateInfo.referenceSpaceType(XR10.XR_REFERENCE_SPACE_TYPE_VIEW); + error = XR10.xrCreateReferenceSpace(session, referenceSpaceCreateInfo, pp); + logError(error, "xrCreateReferenceSpace", "XR_REFERENCE_SPACE_TYPE_VIEW"); + xrViewSpace = new XrSpace(pp.get(0), session); + } + } + + private void initializeOpenXRSwapChain() { + try (MemoryStack stack = stackPush()) { + //Check amount of views + IntBuffer intBuf = stack.callocInt(1); + int error = XR10.xrEnumerateViewConfigurationViews(instance, systemID, XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, intBuf, null); + logError(error, "xrEnumerateViewConfigurationViews", "get count"); + + //Get all views + ByteBuffer viewConfBuffer = bufferStack(intBuf.get(0), XrViewConfigurationView.SIZEOF, XR10.XR_TYPE_VIEW_CONFIGURATION_VIEW); + XrViewConfigurationView.Buffer views = new XrViewConfigurationView.Buffer(viewConfBuffer); + error = XR10.xrEnumerateViewConfigurationViews(instance, systemID, XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, intBuf, views); + logError(error, "xrEnumerateViewConfigurationViews", "get views"); + int viewCountNumber = intBuf.get(0); + + this.viewBuffer = new XrView.Buffer( + bufferHeap(viewCountNumber, XrView.SIZEOF, XR10.XR_TYPE_VIEW) + ); + //Check swapchain formats + error = XR10.xrEnumerateSwapchainFormats(session, intBuf, null); + logError(error, "xrEnumerateSwapchainFormats", "get count"); + + //Get swapchain formats + LongBuffer swapchainFormats = stack.callocLong(intBuf.get(0)); + error = XR10.xrEnumerateSwapchainFormats(session, intBuf, swapchainFormats); + logError(error, "xrEnumerateSwapchainFormats", "get formats"); + + long[] desiredSwapchainFormats = { + //SRGB formats + GL21.GL_SRGB8_ALPHA8, + GL21.GL_SRGB8, + //others + GL11.GL_RGB10_A2, + GL30.GL_RGBA16F, + GL30.GL_RGB16F, + + // The two below should only be used as a fallback, as they are linear color formats without enough bits for color + // depth, thus leading to banding. + GL11.GL_RGBA8, + GL31.GL_RGBA8_SNORM, + }; + + //Choose format + long chosenFormat = 0; + for (long glFormatIter : desiredSwapchainFormats) { + swapchainFormats.rewind(); + while (swapchainFormats.hasRemaining()) { + if (glFormatIter == swapchainFormats.get()) { + chosenFormat = glFormatIter; + break; + } + } + if (chosenFormat != 0) { + break; + } + } + + if (chosenFormat == 0) { + var formats = new ArrayList(); + swapchainFormats.rewind(); + while (swapchainFormats.hasRemaining()) { + formats.add(swapchainFormats.get()); + } + throw new RuntimeException("No compatible swapchain / framebuffer format available: " + formats); + } + + //Make swapchain + XrViewConfigurationView viewConfig = views.get(0); + XrSwapchainCreateInfo swapchainCreateInfo = XrSwapchainCreateInfo.calloc(stack); + swapchainCreateInfo.type(XR10.XR_TYPE_SWAPCHAIN_CREATE_INFO); + swapchainCreateInfo.next(NULL); + swapchainCreateInfo.createFlags(0); + swapchainCreateInfo.usageFlags(XR10.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT); + swapchainCreateInfo.format(chosenFormat); + swapchainCreateInfo.sampleCount(1); + swapchainCreateInfo.width(viewConfig.recommendedImageRectWidth()); + swapchainCreateInfo.height(viewConfig.recommendedImageRectHeight()); + swapchainCreateInfo.faceCount(1); + swapchainCreateInfo.arraySize(2); + swapchainCreateInfo.mipCount(1); + + PointerBuffer handlePointer = stack.callocPointer(1); + error = XR10.xrCreateSwapchain(session, swapchainCreateInfo, handlePointer); + logError(error, "xrCreateSwapchain", "format: " + chosenFormat); + swapchain = new XrSwapchain(handlePointer.get(0), session); + this.width = swapchainCreateInfo.width(); + this.height = swapchainCreateInfo.height(); + } + } + + private Struct getGraphicsAPI(MemoryStack stack) { + XrGraphicsRequirementsOpenGLKHR graphicsRequirements = XrGraphicsRequirementsOpenGLKHR.calloc(stack).type(KHROpenGLEnable.XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR); + KHROpenGLEnable.xrGetOpenGLGraphicsRequirementsKHR(instance, systemID, graphicsRequirements); + + XrSystemProperties systemProperties = XrSystemProperties.calloc(stack).type(XR10.XR_TYPE_SYSTEM_PROPERTIES); + int error = XR10.xrGetSystemProperties(instance, systemID, systemProperties); + logError(error, "xrGetSystemProperties", ""); + XrSystemTrackingProperties trackingProperties = systemProperties.trackingProperties(); + XrSystemGraphicsProperties graphicsProperties = systemProperties.graphicsProperties(); + + this.systemName = memUTF8(memAddress(systemProperties.systemName())); + int vendor = systemProperties.vendorId(); + boolean orientationTracking = trackingProperties.orientationTracking(); + boolean positionTracking = trackingProperties.positionTracking(); + int maxWidth = graphicsProperties.maxSwapchainImageWidth(); + int maxHeight = graphicsProperties.maxSwapchainImageHeight(); + int maxLayerCount = graphicsProperties.maxLayerCount(); + + VRSettings.logger.info("Found device with id: {}", systemID); + VRSettings.logger.info("Headset Name: {}, Vendor: {}", systemName, vendor); + VRSettings.logger.info("Headset Orientation Tracking: {}, Position Tracking: {}", orientationTracking, positionTracking); + VRSettings.logger.info("Headset Max Width: {}, Max Height: {}, Max Layer Count: {}", maxWidth, maxHeight, maxLayerCount); + + //Bind the OpenGL context to the OpenXR instance and create the session + Window window = mc.getWindow(); + long windowHandle = window.getWindow(); + if (Platform.get() == Platform.WINDOWS) { + return XrGraphicsBindingOpenGLWin32KHR.calloc(stack).set( + KHROpenGLEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, + NULL, + User32.GetDC(GLFWNativeWin32.glfwGetWin32Window(windowHandle)), + GLFWNativeWGL.glfwGetWGLContext(windowHandle) + ); + } else if (Platform.get() == Platform.LINUX) { + long xDisplay = GLFWNativeX11.glfwGetX11Display(); + + long glXContext = GLFWNativeGLX.glfwGetGLXContext(windowHandle); + long glXWindowHandle = GLFWNativeGLX.glfwGetGLXWindow(windowHandle); + + int fbXID = glXQueryDrawable(xDisplay, glXWindowHandle, GLX_FBCONFIG_ID); + PointerBuffer fbConfigBuf = glXChooseFBConfig(xDisplay, X11.XDefaultScreen(xDisplay), stackInts(GLX_FBCONFIG_ID, fbXID, 0)); + if(fbConfigBuf == null) { + throw new IllegalStateException("Your framebuffer config was null, make a github issue"); + } + long fbConfig = fbConfigBuf.get(); + + return XrGraphicsBindingOpenGLXlibKHR.calloc(stack).set( + KHROpenGLEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, + NULL, + xDisplay, + (int) Objects.requireNonNull(glXGetVisualFromFBConfig(xDisplay, fbConfig)).visualid(), + fbConfig, + glXWindowHandle, + glXContext + ); + } else { + throw new IllegalStateException("Macos not supported"); + } + } + + /** + * Creates an array of XrStructs with their types pre set to @param type + */ + static ByteBuffer bufferStack(int capacity, int sizeof, int type) { + ByteBuffer b = stackCalloc(capacity * sizeof); + + for (int i = 0; i < capacity; i++) { + b.position(i * sizeof); + b.putInt(type); + } + b.rewind(); + return b; + } + + + @Override + public boolean postinit() throws RenderConfigException { + this.initInputAndApplication(); + return inputInitialized; + } + + private void initInputAndApplication() { + this.populateInputActions(); + + //this.generateActionManifest(); + //this.loadActionManifest(); + this.loadActionHandles(); + this.loadDefaultBindings(); + //this.installApplicationManifest(false); + this.inputInitialized = true; + + } + + @Override + public Matrix4f getControllerComponentTransform(int var1, String var2) { + return Utils.Matrix4fSetIdentity(new Matrix4f()); + } + + @Override + public boolean hasThirdController() { + return false; + } + + @Override + public List getOrigins(VRInputAction var1) { + try (MemoryStack stack = MemoryStack.stackPush()){ + XrBoundSourcesForActionEnumerateInfo info = XrBoundSourcesForActionEnumerateInfo.calloc(stack); + info.type(XR10.XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO); + info.next(NULL); + info.action(new XrAction(var1.handle, new XrActionSet(actionSetHandles.get(var1.actionSet), instance))); + IntBuffer buf = stack.callocInt(1); + int error = XR10.xrEnumerateBoundSourcesForAction(session, info, buf, null); + logError(error, "xrEnumerateBoundSourcesForAction", var1.name); + + int size = buf.get(); + if (size <= 0) { + return List.of(0L); + } + + buf = stack.callocInt(size); + LongBuffer longbuf = stack.callocLong(size); + error = XR10.xrEnumerateBoundSourcesForAction(session, info, buf, longbuf); + logError(error, "xrEnumerateBoundSourcesForAction", var1.name); + long[] array; + if (longbuf.hasArray()) { //TODO really? + array = longbuf.array(); + } else { + longbuf.rewind(); + array = new long[longbuf.remaining()]; + int index = 0; + while (longbuf.hasRemaining()) { + array[index++] = longbuf.get(); + } + } + return Arrays.stream(array).boxed().toList(); + } + } + + @Override + public String getOriginName(long l) { + try (MemoryStack stack = MemoryStack.stackPush()){ + XrInputSourceLocalizedNameGetInfo info = XrInputSourceLocalizedNameGetInfo.calloc(stack); + info.type(XR10.XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO); + info.next(0); + info.sourcePath(l); + info.whichComponents(XR10.XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT); + + IntBuffer buf = stack.callocInt(1); + int error = XR10.xrGetInputSourceLocalizedName(session, info, buf, null); + logError(error, "xrGetInputSourceLocalizedName", "get length"); + + int size = buf.get(); + if (size <= 0) { + return ""; + } + + buf = stack.callocInt(size); + ByteBuffer byteBuffer = stack.calloc(size); + error = XR10.xrGetInputSourceLocalizedName(session, info, buf, byteBuffer); + logError(error, "xrGetInputSourceLocalizedName", "get String"); + return new String(byteBuffer.array()); + } + } + + @Override + public VRRenderer createVRRenderer() { + return new OpenXRStereoRenderer(this); + } + + @Override + public boolean isActive() { + this.pollVREvents(); + return isActive; + } + + @Override + public ControllerType getOriginControllerType(long i) { + if (i == aim[0]) { + return ControllerType.RIGHT; + } + return ControllerType.LEFT; + } + + @Override + public float getIPD() { + return (float) (this.getEyePosition(RenderPass.RIGHT).x - this.getEyePosition(RenderPass.LEFT).x); + } + + @Override + public String getRuntimeName() { + return "OpenXR"; + } + + //TODO Collect and register all actions + private void loadActionHandles() { + for (VRInputActionSet vrinputactionset : VRInputActionSet.values()) { + long actionSet = makeActionSet(instance, vrinputactionset.name, vrinputactionset.localizedName, 0); + this.actionSetHandles.put(vrinputactionset, actionSet); + } + + for (VRInputAction vrinputaction : this.inputActions.values()) { + long action = createAction(vrinputaction.name, vrinputaction.name, vrinputaction.type, new XrActionSet(this.actionSetHandles.get(vrinputaction.actionSet), instance)); + vrinputaction.setHandle(action); + } + + setupControllers(); + + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); + this.haptics[0] = createAction("/actions/global/out/righthaptic", "/actions/global/out/righthaptic", "haptic", actionSet); + this.haptics[1] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", "haptic", actionSet); + + } + + private void setupControllers() { + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); + this.grip[0] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", "pose", actionSet); + this.grip[1] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", actionSet); + this.aim[0] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", "pose", actionSet); + this.aim[1] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", "pose", actionSet); + } + + private void loadDefaultBindings() { + try (MemoryStack stack = MemoryStack.stackPush()) { + int error; + for (String headset: XRBindings.supportedHeadsets()) { + VRSettings.logger.info("loading defaults for {}", headset); + Pair[] defaultBindings = XRBindings.getBinding(headset).toArray(new Pair[0]); + XrActionSuggestedBinding.Buffer bindings = XrActionSuggestedBinding.calloc(defaultBindings.length + 6, stack); //TODO different way of adding controller poses + + for (int i = 0; i < defaultBindings.length; i++) { + Pair pair = defaultBindings[i]; + VRInputAction binding = this.getInputActionByName(pair.getLeft()); + if (binding.handle == 0L) { + VRSettings.logger.error("Handle for '{}'/'{}' is null", pair.getLeft(), pair.getRight()); + continue; + } + bindings.get(i).set( + new XrAction(binding.handle, new XrActionSet(actionSetHandles.get(binding.actionSet), instance)), + getPath(pair.getRight()) + ); + } + + //TODO make this also changeable? + XrActionSet actionSet = new XrActionSet(actionSetHandles.get(VRInputActionSet.GLOBAL), instance); + bindings.get(defaultBindings.length).set( + new XrAction(this.grip[0], actionSet), + getPath("/user/hand/right/input/grip/pose") + ); + bindings.get(defaultBindings.length + 1).set( + new XrAction(this.grip[1], actionSet), + getPath("/user/hand/left/input/grip/pose") + ); + bindings.get(defaultBindings.length + 2).set( + new XrAction(this.aim[0], actionSet), + getPath("/user/hand/right/input/aim/pose") + ); + bindings.get(defaultBindings.length + 3).set( + new XrAction(this.aim[1], actionSet), + getPath("/user/hand/left/input/aim/pose") + ); + + bindings.get(defaultBindings.length + 4).set( + new XrAction(this.haptics[0], actionSet), + getPath("/user/hand/right/output/haptic") + ); + + bindings.get(defaultBindings.length + 5).set( + new XrAction(this.haptics[1], actionSet), + getPath("/user/hand/left/output/haptic") + ); + + XrInteractionProfileSuggestedBinding suggested_binds = XrInteractionProfileSuggestedBinding.calloc(stack); + suggested_binds.type(XR10.XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING); + suggested_binds.next(NULL); + suggested_binds.interactionProfile(getPath(headset)); + suggested_binds.suggestedBindings(bindings); + + error = XR10.xrSuggestInteractionProfileBindings(instance, suggested_binds); + logError(error, "xrSuggestInteractionProfileBindings", headset); + } + + + XrSessionActionSetsAttachInfo attach_info = XrSessionActionSetsAttachInfo.calloc(stack); + attach_info.type(XR10.XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO); + attach_info.next(NULL); + attach_info.actionSets(stackPointers(actionSetHandles.values().stream().mapToLong(value -> value).toArray())); + + error = XR10.xrAttachSessionActionSets(session, attach_info); + logError(error, "xrAttachSessionActionSets", ""); + + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); + XrActionSpaceCreateInfo grip_left = XrActionSpaceCreateInfo.calloc(stack); + grip_left.type(XR10.XR_TYPE_ACTION_SPACE_CREATE_INFO); + grip_left.next(NULL); + grip_left.action(new XrAction(grip[0], actionSet)); + grip_left.subactionPath(getPath("/user/hand/right")); + grip_left.poseInActionSpace(POSE_IDENTITY); + PointerBuffer pp = stackCallocPointer(1); + error = XR10.xrCreateActionSpace(session, grip_left, pp); + logError(error, "xrCreateActionSpace", "grip: /user/hand/right"); + this.gripSpace[0] = new XrSpace(pp.get(0), session); + + grip_left.action(new XrAction(grip[1], actionSet)); + grip_left.subactionPath(getPath("/user/hand/left")); + error = XR10.xrCreateActionSpace(session, grip_left, pp); + logError(error, "xrCreateActionSpace", "grip: /user/hand/left"); + this.gripSpace[1] = new XrSpace(pp.get(0), session); + + grip_left.action(new XrAction(aim[0], actionSet)); + grip_left.subactionPath(getPath("/user/hand/right")); + error = XR10.xrCreateActionSpace(session, grip_left, pp); + logError(error, "xrCreateActionSpace", "aim: /user/hand/right"); + this.aimSpace[0] = new XrSpace(pp.get(0), session); + + grip_left.action(new XrAction(aim[1], actionSet)); + grip_left.subactionPath(getPath("/user/hand/left")); + error = XR10.xrCreateActionSpace(session, grip_left, pp); + logError(error, "xrCreateActionSpace", "aim: /user/hand/left"); + this.aimSpace[1] = new XrSpace(pp.get(0), session); + + } + } + + public long getPath(String pathString) { + return this.paths.computeIfAbsent(pathString, s -> { + try (MemoryStack ignored = stackPush()) { + LongBuffer buf = stackCallocLong(1); + int error = XR10.xrStringToPath(instance, pathString, buf); + logError(error, "getPath", pathString); + return buf.get(); + } + }); + } + + private long createAction(String name, String localisedName, String type, XrActionSet actionSet) { + try (MemoryStack stack = MemoryStack.stackPush()){ + String s = name.split("/")[name.split("/").length -1].toLowerCase(); + XrActionCreateInfo hands = XrActionCreateInfo.calloc(stack); + hands.type(XR10.XR_TYPE_ACTION_CREATE_INFO); + hands.next(NULL); + hands.actionName(memUTF8(s)); + switch (type) { + case "boolean" -> hands.actionType(XR10.XR_ACTION_TYPE_BOOLEAN_INPUT); + case "vector1" -> hands.actionType(XR10.XR_ACTION_TYPE_FLOAT_INPUT); + case "vector2" -> hands.actionType(XR10.XR_ACTION_TYPE_VECTOR2F_INPUT); + case "pose" -> hands.actionType(XR10.XR_ACTION_TYPE_POSE_INPUT); + case "haptic" -> hands.actionType(XR10.XR_ACTION_TYPE_VIBRATION_OUTPUT); + } + hands.countSubactionPaths(0); + hands.subactionPaths(null); + hands.localizedActionName(memUTF8(s)); + PointerBuffer buffer = stackCallocPointer(1); + + int error = XR10.xrCreateAction(actionSet, hands, buffer); + logError(error, "xrCreateAction", "name:", name, "type:", type); + return buffer.get(0); + } + } + + private long makeActionSet(XrInstance instance, String name, String localisedName, int priority) { + try (MemoryStack stack = MemoryStack.stackPush()){ + XrActionSetCreateInfo info = XrActionSetCreateInfo.calloc(stack); + info.type(XR10.XR_TYPE_ACTION_SET_CREATE_INFO); + info.next(NULL); + info.actionSetName(memUTF8(localisedName.toLowerCase())); + info.localizedActionSetName(memUTF8(localisedName.toLowerCase())); + info.priority(priority); + PointerBuffer buffer = stack.callocPointer(1); + + int error = XR10.xrCreateActionSet(instance, info, buffer); + logError(error, "makeActionSet", localisedName.toLowerCase()); + return buffer.get(0); + } + } + + static ByteBuffer bufferHeap(int capacity, int sizeof, int type) { + ByteBuffer b = memCalloc(capacity * sizeof); + + for (int i = 0; i < capacity; i++) { + b.position(i * sizeof); + b.putInt(type); + } + b.rewind(); + return b; + } + + /** + * gets the String for the given xrResult + */ + private String getResultName(int xrResult) { + String resultString = switch (xrResult) { + case 1 -> "XR_TIMEOUT_EXPIRED"; + case 3 -> "XR_SESSION_LOSS_PENDING"; + case 4 -> "XR_EVENT_UNAVAILABLE"; + case 7 -> "XR_SPACE_BOUNDS_UNAVAILABLE"; + case 8 -> "XR_SESSION_NOT_FOCUSED"; + case 9 -> "XR_FRAME_DISCARDED"; + case -1 -> "XR_ERROR_VALIDATION_FAILURE"; + case -2 -> "XR_ERROR_RUNTIME_FAILURE"; + case -3 -> "XR_ERROR_OUT_OF_MEMORY"; + case -4 -> "XR_ERROR_API_VERSION_UNSUPPORTED"; + case -6 -> "XR_ERROR_INITIALIZATION_FAILED"; + case -7 -> "XR_ERROR_FUNCTION_UNSUPPORTED"; + case -8 -> "XR_ERROR_FEATURE_UNSUPPORTED"; + case -9 -> "XR_ERROR_EXTENSION_NOT_PRESENT"; + case -10 -> "XR_ERROR_LIMIT_REACHED"; + case -11 -> "XR_ERROR_SIZE_INSUFFICIENT"; + case -12 -> "XR_ERROR_HANDLE_INVALID"; + case -13 -> "XR_ERROR_INSTANCE_LOST"; + case -14 -> "XR_ERROR_SESSION_RUNNING"; + case -16 -> "XR_ERROR_SESSION_NOT_RUNNING"; + case -17 -> "XR_ERROR_SESSION_LOST"; + case -18 -> "XR_ERROR_SYSTEM_INVALID"; + case -19 -> "XR_ERROR_PATH_INVALID"; + case -20 -> "XR_ERROR_PATH_COUNT_EXCEEDED"; + case -21 -> "XR_ERROR_PATH_FORMAT_INVALID"; + case -22 -> "XR_ERROR_PATH_UNSUPPORTED"; + case -23 -> "XR_ERROR_LAYER_INVALID"; + case -24 -> "XR_ERROR_LAYER_LIMIT_EXCEEDED"; + case -25 -> "XR_ERROR_SWAPCHAIN_RECT_INVALID"; + case -26 -> "XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED"; + case -27 -> "XR_ERROR_ACTION_TYPE_MISMATCH"; + case -28 -> "XR_ERROR_SESSION_NOT_READY"; + case -29 -> "XR_ERROR_SESSION_NOT_STOPPING"; + case -30 -> "XR_ERROR_TIME_INVALID"; + case -31 -> "XR_ERROR_REFERENCE_SPACE_UNSUPPORTED"; + case -32 -> "XR_ERROR_FILE_ACCESS_ERROR"; + case -33 -> "XR_ERROR_FILE_CONTENTS_INVALID"; + case -34 -> "XR_ERROR_FORM_FACTOR_UNSUPPORTED"; + case -35 -> "XR_ERROR_FORM_FACTOR_UNAVAILABLE"; + case -36 -> "XR_ERROR_API_LAYER_NOT_PRESENT"; + case -37 -> "XR_ERROR_CALL_ORDER_INVALID"; + case -38 -> "XR_ERROR_GRAPHICS_DEVICE_INVALID"; + case -39 -> "XR_ERROR_POSE_INVALID"; + case -40 -> "XR_ERROR_INDEX_OUT_OF_RANGE"; + case -41 -> "XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED"; + case -42 -> "XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED"; + case -44 -> "XR_ERROR_NAME_DUPLICATED"; + case -45 -> "XR_ERROR_NAME_INVALID"; + case -46 -> "XR_ERROR_ACTIONSET_NOT_ATTACHED"; + case -47 -> "XR_ERROR_ACTIONSETS_ALREADY_ATTACHED"; + case -48 -> "XR_ERROR_LOCALIZED_NAME_DUPLICATED"; + case -49 -> "XR_ERROR_LOCALIZED_NAME_INVALID"; + case -50 -> "XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING"; + case -51 -> "XR_ERROR_RUNTIME_UNAVAILABLE"; + default -> null; + }; + if (resultString == null) { + // ask the runtime for the xrResult name + try (MemoryStack stack = MemoryStack.stackPush()) { + ByteBuffer str = stack.calloc(XR10.XR_MAX_RESULT_STRING_SIZE); + + if (XR10.xrResultToString(instance, xrResult, str) == XR10.XR_SUCCESS) { + resultString = (memUTF8(memAddress(str))); + } else { + resultString = "Unknown Error: " + xrResult; + } + } + } + return resultString; + } + + /** + * logs only errors + * @param xrResult result to check + * @param caller where the xrResult came from + * @param args arguments may be helpful in locating the error + */ + protected void logError(int xrResult, String caller, String... args) { + if (xrResult < 0) { + VRSettings.logger.error("{} for {} errored: {}", caller, String.join(" ", args), getResultName(xrResult)); + } + } + + /** + * logs all results except XR_SUCCESS + * @param xrResult result to check + * @param caller where the xrResult came from + * @param args arguments may be helpful in locating the error + */ + protected void logAll(int xrResult, String caller, String... args) { + if (xrResult != XR10.XR_SUCCESS) { + VRSettings.logger.error("{} for {} errored: {}", caller, String.join(" ", args), getResultName(xrResult)); + } + } +} diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java new file mode 100644 index 000000000..ae39e4f3a --- /dev/null +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java @@ -0,0 +1,47 @@ +package org.vivecraft.client_vr.provider.openxr; + +import org.lwjgl.openxr.*; +import org.lwjgl.system.MemoryStack; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.provider.ControllerType; +import org.vivecraft.client_vr.provider.HapticScheduler; +import org.vivecraft.client_vr.provider.control.VRInputActionSet; + +import java.util.concurrent.TimeUnit; + +import static java.sql.Types.NULL; + +public class OpenXRHapticSchedular extends HapticScheduler { + + private void triggerHapticPulse(ControllerType controller, float durationSeconds, float frequency, float amplitude) { + try (MemoryStack stack = MemoryStack.stackPush()){ + int i = controller == ControllerType.RIGHT ? 0 : 1; + if (ClientDataHolderVR.getInstance().vrSettings.reverseHands) { + i = controller == ControllerType.RIGHT ? 1 : 0; + } + XrActionSet actionSet = new XrActionSet(MCOpenXR.get().getActionSetHandle(VRInputActionSet.GLOBAL), MCOpenXR.get().instance); + XrHapticActionInfo info = XrHapticActionInfo.calloc(stack); + info.type(XR10.XR_TYPE_HAPTIC_ACTION_INFO); + info.next(NULL); + info.action(new XrAction(MCOpenXR.get().haptics[i], actionSet)); + + XrHapticVibration vibration = XrHapticVibration.calloc(stack); + vibration.type(XR10.XR_ACTION_TYPE_VIBRATION_OUTPUT); + vibration.next(NULL); + vibration.duration((long) (durationSeconds * 1_000_000_000)); + vibration.frequency(frequency); + vibration.amplitude(amplitude); + + int error = XR10.xrApplyHapticFeedback(MCOpenXR.get().session, info, XrHapticBaseHeader.create(vibration)); + MCOpenXR.get().logError(error, "xrApplyHapticFeedback", ""); + } + } + + @Override + public void queueHapticPulse(ControllerType controller, float durationSeconds, float frequency, float amplitude, float delaySeconds) { + this.executor.schedule(() -> + { + this.triggerHapticPulse(controller, durationSeconds, frequency, amplitude); + }, (long) (delaySeconds * 1000000.0F), TimeUnit.MICROSECONDS); + } +} diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java new file mode 100644 index 000000000..aa787582f --- /dev/null +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -0,0 +1,182 @@ +package org.vivecraft.client_vr.provider.openxr; + +import com.mojang.blaze3d.pipeline.RenderTarget; +import net.minecraft.util.Tuple; +import org.joml.Matrix4f; +import org.lwjgl.PointerBuffer; +import org.lwjgl.opengl.GL31; +import org.lwjgl.openxr.*; +import org.lwjgl.system.MemoryStack; +import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRTextureTarget; +import org.vivecraft.client_vr.provider.VRRenderer; +import org.vivecraft.client_vr.render.RenderConfigException; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import static org.lwjgl.system.MemoryUtil.memAddress; +import static org.lwjgl.system.MemoryUtil.memUTF8; + +public class OpenXRStereoRenderer extends VRRenderer { + private final MCOpenXR openxr; + private int swapIndex; + private VRTextureTarget[] leftFramebuffers; + private VRTextureTarget[] rightFramebuffers; + private boolean render; + private XrCompositionLayerProjectionView.Buffer projectionLayerViews; + private VRTextureTarget rightFramebuffer; + private VRTextureTarget leftFramebuffer; + + + public OpenXRStereoRenderer(MCOpenXR vr) { + super(vr); + this.openxr = vr; + } + + @Override + public void createRenderTexture(int width, int height) throws RenderConfigException{ + try (MemoryStack stack = MemoryStack.stackPush()) { + + //Get amount of views in the swapchain + IntBuffer intBuffer = stack.ints(0); //Set value to 0 + int error = XR10.xrEnumerateSwapchainImages(openxr.swapchain, intBuffer, null); + this.openxr.logError(error, "xrEnumerateSwapchainImages", "get count"); + + //Now we know the amount, create the image buffer + int imageCount = intBuffer.get(0); + XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = XrSwapchainImageOpenGLKHR.calloc(imageCount, stack); + for (XrSwapchainImageOpenGLKHR image : swapchainImageBuffer) { + image.type(KHROpenGLEnable.XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR); + } + + error = XR10.xrEnumerateSwapchainImages(openxr.swapchain, intBuffer, XrSwapchainImageBaseHeader.create(swapchainImageBuffer.address(), swapchainImageBuffer.capacity())); + this.openxr.logError(error, "xrEnumerateSwapchainImages", "get images"); + + this.leftFramebuffers = new VRTextureTarget[imageCount]; + this.rightFramebuffers = new VRTextureTarget[imageCount]; + + for (int i = 0; i < imageCount; i++) { + XrSwapchainImageOpenGLKHR openxrImage = swapchainImageBuffer.get(i); + leftFramebuffers[i] = new VRTextureTarget("L Eye " + i, width, height, openxrImage.image(), 0); + this.checkGLError("Left Eye framebuffer setup"); + rightFramebuffers[i] = new VRTextureTarget("R Eye " + i, width, height, openxrImage.image(), 1); + this.checkGLError("Right Eye framebuffer setup"); + } + + this.rightFramebuffer = new VRTextureTarget("R Eye mirror", width, height, true, false, -1, true, true, ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); + this.leftFramebuffer = new VRTextureTarget("L Eye mirror", width, height, true, false, -1, true, true, ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); + } + } + + @Override + public void setupRenderConfiguration(boolean render) throws Exception { + super.setupRenderConfiguration(render); + + if (!render) { + return; + } + this.projectionLayerViews = XrCompositionLayerProjectionView.calloc(2); + try (MemoryStack stack = MemoryStack.stackPush()){ + + IntBuffer intBuf2 = stack.callocInt(1); + + int error = XR10.xrAcquireSwapchainImage( + openxr.swapchain, + XrSwapchainImageAcquireInfo.calloc(stack).type(XR10.XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO), + intBuf2); + this.openxr.logError(error, "xrAcquireSwapchainImage", ""); + + error = XR10.xrWaitSwapchainImage(openxr.swapchain, + XrSwapchainImageWaitInfo.calloc(stack) + .type(XR10.XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO) + .timeout(XR10.XR_INFINITE_DURATION)); + this.openxr.logError(error, "xrWaitSwapchainImage", ""); + + this.swapIndex = intBuf2.get(0); + + // Render view to the appropriate part of the swapchain image. + for (int viewIndex = 0; viewIndex < 2; viewIndex++) { + + var subImage = projectionLayerViews.get(viewIndex) + .type(XR10.XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) + .pose(openxr.viewBuffer.get(viewIndex).pose()) + .fov(openxr.viewBuffer.get(viewIndex).fov()) + .subImage(); + subImage.swapchain(openxr.swapchain); + subImage.imageRect().offset().set(0, 0); + subImage.imageRect().extent().set(openxr.width, openxr.height); + subImage.imageArrayIndex(viewIndex); + + } + } + } + + @Override + public Matrix4f getProjectionMatrix(int eyeType, float nearClip, float farClip) { + XrFovf fov = openxr.viewBuffer.get(eyeType).fov(); + return new Matrix4f().setPerspectiveOffCenterFov(fov.angleLeft(), fov.angleRight(), fov.angleDown(), fov.angleUp(), nearClip, farClip); + } + + @Override + public void endFrame() throws RenderConfigException { + GL31.glBindFramebuffer(GL31.GL_READ_FRAMEBUFFER, getLeftEyeTarget().frameBufferId); + GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, leftFramebuffers[swapIndex].frameBufferId); + GL31.glBlitFramebuffer(0,0, getLeftEyeTarget().viewWidth, getLeftEyeTarget().viewHeight, 0,0, leftFramebuffers[swapIndex].viewWidth, leftFramebuffers[swapIndex].viewHeight, GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); + + GL31.glBindFramebuffer(GL31.GL_READ_FRAMEBUFFER, getRightEyeTarget().frameBufferId); + GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, rightFramebuffers[swapIndex].frameBufferId); + GL31.glBlitFramebuffer(0,0, getRightEyeTarget().viewWidth, getRightEyeTarget().viewHeight, 0,0, rightFramebuffers[swapIndex].viewWidth, rightFramebuffers[swapIndex].viewHeight, GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); + + try (MemoryStack stack = MemoryStack.stackPush()){ + PointerBuffer layers = stack.callocPointer(1); + int error; + if (this.openxr.shouldRender) { + error = XR10.xrReleaseSwapchainImage( + openxr.swapchain, + XrSwapchainImageReleaseInfo.calloc(stack) + .type(XR10.XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO)); + this.openxr.logError(error, "xrReleaseSwapchainImage", ""); + + XrCompositionLayerProjection compositionLayerProjection = XrCompositionLayerProjection.calloc(stack) + .type(XR10.XR_TYPE_COMPOSITION_LAYER_PROJECTION) + .space(openxr.xrAppSpace) + .views(projectionLayerViews); + + layers.put(compositionLayerProjection); + } + layers.flip(); + + error = XR10.xrEndFrame( + openxr.session, + XrFrameEndInfo.calloc(stack) + .type(XR10.XR_TYPE_FRAME_END_INFO) + .displayTime(openxr.time) + .environmentBlendMode(XR10.XR_ENVIRONMENT_BLEND_MODE_OPAQUE) + .layers(layers)); + this.openxr.logAll(error, "xrEndFrame", ""); + + projectionLayerViews.close(); + } + } + + @Override + public boolean providesStencilMask() { + return false; + } + + @Override + public RenderTarget getLeftEyeTarget() { + return leftFramebuffer; + } + + @Override + public RenderTarget getRightEyeTarget() { + return rightFramebuffer; + } + + @Override + public Tuple getRenderTextureSizes() { + return new Tuple<>(openxr.width, openxr.height); + } +} diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java new file mode 100644 index 000000000..7ce805b55 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java @@ -0,0 +1,50 @@ +package org.vivecraft.client_vr.provider.openxr; + +import org.joml.Matrix3f; +import org.joml.Quaternionf; +import org.lwjgl.openxr.XrPosef; +import org.lwjgl.openxr.XrQuaternionf; +import org.vivecraft.common.utils.math.Matrix4f; + +public class OpenXRUtil { + + public static void openXRPoseToMarix(XrPosef pose, Matrix4f mat) { + Matrix3f matrix3f = new Matrix3f().set(new Quaternionf(pose.orientation().x(), pose.orientation().y(), pose.orientation().z(), pose.orientation().w())); + mat.M[0][0] = matrix3f.m00; + mat.M[0][1] = matrix3f.m10; + mat.M[0][2] = matrix3f.m20; + mat.M[0][3] = pose.position$().x(); + mat.M[1][0] = matrix3f.m01; + mat.M[1][1] = matrix3f.m11; + mat.M[1][2] = matrix3f.m21; + mat.M[1][3] = pose.position$().y(); + mat.M[2][0] = matrix3f.m02; + mat.M[2][1] = matrix3f.m12; + mat.M[2][2] = matrix3f.m22; + mat.M[2][3] = pose.position$().z(); + mat.M[3][0] = 0; + mat.M[3][1] = 0; + mat.M[3][2] = 0; + mat.M[3][3] = 1; + } + + public static void openXRPoseToMarix(XrQuaternionf quat, Matrix4f mat) { + Matrix3f matrix3f = new Matrix3f().set(new Quaternionf(quat.x(), quat.y(), quat.z(), quat.w())); + mat.M[0][0] = matrix3f.m00; + mat.M[0][1] = matrix3f.m10; + mat.M[0][2] = matrix3f.m20; + mat.M[0][3] = 0; + mat.M[1][0] = matrix3f.m01; + mat.M[1][1] = matrix3f.m11; + mat.M[1][2] = matrix3f.m21; + mat.M[1][3] = 0; + mat.M[2][0] = matrix3f.m02; + mat.M[2][1] = matrix3f.m12; + mat.M[2][2] = matrix3f.m22; + mat.M[2][3] = 0; + mat.M[3][0] = 0; + mat.M[3][1] = 0; + mat.M[3][2] = 0; + mat.M[3][3] = 1; + } +} diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java new file mode 100644 index 000000000..8a3a684a6 --- /dev/null +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java @@ -0,0 +1,137 @@ +package org.vivecraft.client_vr.provider.openxr; + +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.HashSet; + +public class XRBindings { + + public static HashSet supportedHeadsets() { + HashSet set = new HashSet<>(); + if (MCOpenXR.get().systemName.toLowerCase().contains("oculus") || MCOpenXR.get().systemName.toLowerCase().contains("meta")) { + set.add("/interaction_profiles/oculus/touch_controller"); + return set; + } + if (MCOpenXR.get().session.getCapabilities().XR_HTC_vive_cosmos_controller_interaction) { + set.add("/interaction_profiles/htc/vive_cosmos_controller"); + } + set.add("/interaction_profiles/htc/vive_controller"); + return set; + } + + private static HashSet> quest2Bindings() { + HashSet> set = new HashSet<>(); + + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/y/click")); + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.toggleKeyboard", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/left/input/x/click")); + + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiMiddleClick", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiLeftClick", "/user/hand/right/input/trigger")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiRightClick", "/user/hand/right/input/a/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiScrollAxis", "/user/hand/right/input/thumbstick/y")); + + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarPrev", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarNext", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/ingame/in/key.attack", "/user/hand/right/input/trigger")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleport", "/user/hand/left/input/trigger")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.radialMenu", "/user/hand/right/input/b/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.use", "/user/hand/right/input/a/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleportFallback", "/user/hand/left/input/trigger/value")); + set.add(new MutablePair<>("/actions/ingame/in/key.jump", "/user/hand/left/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.freeMoveStrafe", "/user/hand/left/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/key.sneak", "/user/hand/right/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.rotateAxis", "/user/hand/right/input/thumbstick")); + + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/left/input/trigger")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/right/input/trigger")); + return set; + } + + private static HashSet> viveBindings() { + HashSet> set = new HashSet<>(); + + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/menu/click")); + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.toggleKeyboard", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/right/input/trackpad/click")); + + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiMiddleClick", "/user/hand/right/input/squeeze/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiLeftClick", "/user/hand/right/input/trigger/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiRightClick", "/user/hand/right/input/trackpad/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiScrollAxis", "/user/hand/right/input/trackpad/y")); + + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarPrev", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarNext", "/user/hand/right/input/squeeze/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.attack", "/user/hand/right/input/trigger/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleport", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.radialMenu", "/user/hand/right/input/menu/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.use", "/user/hand/right/input/trackpad/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleportFallback", "/user/hand/left/input/trigger/value")); + set.add(new MutablePair<>("/actions/ingame/in/key.jump", "/user/hand/left/input/trackpad/x")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.freeMoveStrafe", "/user/hand/left/input/trackpad")); + set.add(new MutablePair<>("/actions/ingame/in/key.sneak", "/user/hand/left/input/trackpad/y")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.rotateAxis", "/user/hand/right/input/trackpad")); + + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/right/input/trigger/click")); + + set.add(new MutablePair<>("/actions/technical/in/vivecraft.key.trackpadTouch", "/user/hand/left/input/trackpad/click")); + set.add(new MutablePair<>("/actions/technical/in/vivecraft.key.trackpadTouch", "/user/hand/right/input/trackpad/touch")); + + return set; + } + + private static HashSet> cosmosBindings() { + HashSet> set = new HashSet<>(); + + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/y/click")); + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.toggleKeyboard", "/user/hand/left/input/y/long")); + set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/left/input/x/click")); + + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/grip/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiMiddleClick", "/user/hand/right/input/grip/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiLeftClick", "/user/hand/right/input/trigger/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiRightClick", "/user/hand/right/input/a/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiScrollAxis", "/user/hand/right/input/joystick/scroll")); + + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarPrev", "/user/hand/left/input/grip/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarNext", "/user/hand/right/input/grip/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.attack", "/user/hand/right/input/trigger/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleport", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.radialMenu", "/user/hand/right/input/b/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.use", "/user/hand/right/input/a/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.freeMoveStrafe", "/user/hand/left/input/joystick/position")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.rotateAxis", "/user/hand/right/input/joystick/position")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleportFallback", "/user/hand/left/input/trigger/pull")); + set.add(new MutablePair<>("/actions/ingame/in/key.jump", "/user/hand/left/input/bumper/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.sneak", "/user/hand/right/input/bumper/click")); + + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/left/input/grip/click")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/right/input/trigger/click")); + return set; + } + + public static HashSet> getBinding(String Headset){ + switch (Headset) { + case "/interaction_profiles/htc/vive_cosmos_controller" -> { + return cosmosBindings(); + } + case "/interaction_profiles/htc/vive_controller" -> { + return viveBindings(); + } + case "/interaction_profiles/oculus/touch_controller" -> { + return quest2Bindings(); + } + default -> { + return viveBindings(); + } + } + } +} diff --git a/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRPassHelper.java b/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRPassHelper.java index 5bb494aee..5fffb77cb 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRPassHelper.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRPassHelper.java @@ -53,9 +53,9 @@ public static void renderSingleView(RenderPass eye, float partialTicks, long nan if (dataHolder.vrSettings.useFsaa) { RenderSystem.clearColor(RenderSystem.getShaderFogColor()[0], RenderSystem.getShaderFogColor()[1], RenderSystem.getShaderFogColor()[2], RenderSystem.getShaderFogColor()[3]); if (eye == RenderPass.LEFT) { - dataHolder.vrRenderer.framebufferEye0.bindWrite(true); + dataHolder.vrRenderer.getLeftEyeTarget().bindWrite(true); } else { - dataHolder.vrRenderer.framebufferEye1.bindWrite(true); + dataHolder.vrRenderer.getRightEyeTarget().bindWrite(true); } RenderSystem.clear(16384, Minecraft.ON_OSX); mc.getProfiler().push("fsaa"); @@ -66,9 +66,9 @@ public static void renderSingleView(RenderPass eye, float partialTicks, long nan } if (eye == RenderPass.LEFT) { - dataHolder.vrRenderer.framebufferEye0.bindWrite(true); + dataHolder.vrRenderer.getLeftEyeTarget().bindWrite(true); } else { - dataHolder.vrRenderer.framebufferEye1.bindWrite(true); + dataHolder.vrRenderer.getRightEyeTarget().bindWrite(true); } if (dataHolder.vrSettings.useFOVReduction @@ -195,7 +195,8 @@ public static void renderSingleView(RenderPass eye, float partialTicks, long nan VRShaders._Overlay_pumpkinAmplitutde.set(dataHolder.pumpkineffect); VRShaders._Overlay_eye.set(dataHolder.currentPass == RenderPass.LEFT ? 1 : -1); - ((RenderTargetExtension) rendertarget).vivecraft$blitFovReduction(VRShaders.fovReductionShader, dataHolder.vrRenderer.framebufferEye0.viewWidth, dataHolder.vrRenderer.framebufferEye0.viewHeight); + + ((RenderTargetExtension) rendertarget).vivecraft$blitFovReduction(VRShaders.fovReductionShader, dataHolder.vrRenderer.getLeftEyeTarget().viewWidth, dataHolder.vrRenderer.getLeftEyeTarget().viewHeight); ProgramManager.glUseProgram(0); checkGLError("post overlay" + eye); mc.getProfiler().pop(); diff --git a/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java b/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java index 42e0d3eee..0b68f623e 100644 --- a/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java +++ b/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java @@ -144,6 +144,7 @@ public enum ShaderGUIRender implements OptionEnum { public enum VRProvider implements OptionEnum { OPENVR, + OPENXR, NULLVR } @@ -1063,7 +1064,15 @@ record ConfigEntry(Field field, VrOptions vrOptions, String configName, boolean public enum VrOptions { DUMMY(false, true), // Dummy - VR_PLUGIN(false, true), // vr plugin to use + VR_PLUGIN(false, true) { // vr plugin to use + @Override + void onOptionChange() { + if (VRState.vrRunning) { + VRState.destroyVR(false); + VRState.vrEnabled = true; + } + } + }, VR_ENABLED(false, true) { // vr or nonvr @Override @@ -1568,7 +1577,7 @@ void onOptionChange() { @Override String getDisplayString(String prefix, Object value) { if (VRState.vrEnabled) { - RenderTarget eye0 = ClientDataHolderVR.getInstance().vrRenderer.framebufferEye0; + RenderTarget eye0 = ClientDataHolderVR.getInstance().vrRenderer.getLeftEyeTarget(); return prefix + Math.round((float) value * 100) + "% (" + (int) Math.ceil(eye0.viewWidth * Math.sqrt((float) value)) + "x" + (int) Math.ceil(eye0.viewHeight * Math.sqrt((float) value)) + ")"; } else { return prefix + Math.round((float) value * 100) + "%"; @@ -1760,6 +1769,7 @@ String getDisplayString(String prefix, Object value) { } }, INGAME_BINDINGS_IN_GUI(false, true), + RADIAL_NUMBER(false, false,4, 14, 2, 0), RIGHT_CLICK_DELAY(false, false); // Right Click Repeat // ANISOTROPIC_FILTERING("options.anisotropicFiltering", true, false, 1.0F, 16.0F, 0.0F) diff --git a/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java b/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java index 2fe6f2e3c..a2f006803 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java @@ -56,6 +56,11 @@ public abstract class RenderTargetMixin implements RenderTargetExtension { this.vivecraft$texid = texid; } + @Override + public void vivecraft$setColorid(int colorid) { + this.colorTextureId = colorid; + } + @Override public void vivecraft$isLinearFilter(boolean linearFilter) { this.vivecraft$linearFilter = linearFilter; diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java index 96d79eeff..0e05162d6 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java @@ -16,10 +16,10 @@ import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; +import org.vivecraft.client_vr.provider.control.VRInputAction; import org.vivecraft.common.utils.math.Vector2; -import static org.vivecraft.client_vr.provider.openvr_lwjgl.control.VivecraftMovementInput.getMovementAxisValue; +import static org.vivecraft.client_vr.provider.control.VivecraftMovementInput.getMovementAxisValue; @Mixin(KeyboardInput.class) public class KeyboardInputVRMixin extends Input { diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java index 112dafb2f..8497cb5d8 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java @@ -65,7 +65,7 @@ import org.vivecraft.client_vr.gameplay.trackers.TelescopeTracker; import org.vivecraft.client_vr.menuworlds.MenuWorldDownloader; import org.vivecraft.client_vr.menuworlds.MenuWorldExporter; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; +import org.vivecraft.client_vr.provider.control.VRInputAction; import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.render.VRFirstPersonArmSwing; @@ -295,7 +295,7 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { if (!VRState.vrInitialized) { return; } - boolean vrActive = !ClientDataHolderVR.getInstance().vrSettings.vrHotswitchingEnabled || ClientDataHolderVR.getInstance().vr.isActive(); + boolean vrActive = ClientDataHolderVR.getInstance().vr.isActive() || !ClientDataHolderVR.getInstance().vrSettings.vrHotswitchingEnabled; if (VRState.vrRunning != vrActive && (ClientNetworking.serverAllowsVrSwitching || player == null)) { vivecraft$switchVRState(vrActive); } @@ -355,7 +355,7 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { this.profiler.push("setupRenderConfiguration"); try { this.vivecraft$checkGLError("pre render setup "); - ClientDataHolderVR.getInstance().vrRenderer.setupRenderConfiguration(); + ClientDataHolderVR.getInstance().vrRenderer.setupRenderConfiguration(true); this.vivecraft$checkGLError("post render setup "); } catch (RenderConfigException renderConfigException) { vivecraft$switchVRState(false); @@ -860,8 +860,8 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { this.vivecraft$notifyMirror("Shader compile failed, see log", true, 10000); } } else if (ClientDataHolderVR.getInstance().vrSettings.displayMirrorMode == VRSettings.MirrorMode.DUAL) { - RenderTarget rendertarget = ClientDataHolderVR.getInstance().vrRenderer.framebufferEye0; - RenderTarget rendertarget1 = ClientDataHolderVR.getInstance().vrRenderer.framebufferEye1; + RenderTarget rendertarget = ClientDataHolderVR.getInstance().vrRenderer.getLeftEyeTarget(); + RenderTarget rendertarget1 = ClientDataHolderVR.getInstance().vrRenderer.getRightEyeTarget(); int screenWidth = ((WindowExtension) (Object) this.window).vivecraft$getActualScreenWidth() / 2; int screenHeight = ((WindowExtension) (Object) this.window).vivecraft$getActualScreenHeight(); @@ -878,7 +878,7 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { float xcrop = 0.0F; float ycrop = 0.0F; boolean ar = false; - RenderTarget source = ClientDataHolderVR.getInstance().vrRenderer.framebufferEye0; + RenderTarget source = ClientDataHolderVR.getInstance().vrRenderer.getLeftEyeTarget(); if (ClientDataHolderVR.getInstance().vrSettings.displayMirrorMode == VRSettings.MirrorMode.FIRST_PERSON) { source = ClientDataHolderVR.getInstance().vrRenderer.framebufferUndistorted; @@ -889,11 +889,11 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { } else if (ClientDataHolderVR.getInstance().vrSettings.displayMirrorMode == VRSettings.MirrorMode.SINGLE || ClientDataHolderVR.getInstance().vrSettings.displayMirrorMode == VRSettings.MirrorMode.OFF) { if (!ClientDataHolderVR.getInstance().vrSettings.displayMirrorLeftEye) { - source = ClientDataHolderVR.getInstance().vrRenderer.framebufferEye1; + source = ClientDataHolderVR.getInstance().vrRenderer.getRightEyeTarget(); } } else if (ClientDataHolderVR.getInstance().vrSettings.displayMirrorMode == VRSettings.MirrorMode.CROPPED) { if (!ClientDataHolderVR.getInstance().vrSettings.displayMirrorLeftEye) { - source = ClientDataHolderVR.getInstance().vrRenderer.framebufferEye1; + source = ClientDataHolderVR.getInstance().vrRenderer.getRightEyeTarget(); } xcrop = ClientDataHolderVR.getInstance().vrSettings.mirrorCrop; @@ -961,10 +961,10 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { } else { if (ClientDataHolderVR.getInstance().vrSettings.displayMirrorLeftEye) { RenderSystem.setShaderTexture(2, - ClientDataHolderVR.getInstance().vrRenderer.framebufferEye0.getColorTextureId()); + ClientDataHolderVR.getInstance().vrRenderer.getLeftEyeTarget().getColorTextureId()); } else { RenderSystem.setShaderTexture(2, - ClientDataHolderVR.getInstance().vrRenderer.framebufferEye1.getColorTextureId()); + ClientDataHolderVR.getInstance().vrRenderer.getRightEyeTarget().getColorTextureId()); } } VRShaders.depthMaskShader.setSampler("firstPersonColor", RenderSystem.getShaderTexture(2)); diff --git a/common/src/main/resources/assets/vivecraft/lang/en_us.json b/common/src/main/resources/assets/vivecraft/lang/en_us.json index 358d93e64..30880f940 100644 --- a/common/src/main/resources/assets/vivecraft/lang/en_us.json +++ b/common/src/main/resources/assets/vivecraft/lang/en_us.json @@ -190,6 +190,7 @@ "vivecraft.options.MIXED_REALITY_RENDER_CAMERA_MODEL": "Show Camera Model", "vivecraft.options.PHYSICAL_KEYBOARD_THEME": "Keyboard Theme", "vivecraft.options.KEYBOARD_PRESS_BINDS": "Keyboard Presses Bindings", + "vivecraft.options.STEREOPLUGIN": "Stereo Plugin", "_comment6": "Option tooltips", "vivecraft.options.HUD_SCALE.tooltip": "Relative size HUD takes up in field-of-view.\nThe units are just relative, not in degrees or a fraction of FOV or anything.", "vivecraft.options.HUD_DISTANCE.tooltip": "Distance the floating HUD is drawn in front of your body.\nThe relative size of the HUD is unchanged by this.\nDistance is in meters (though isn't obstructed by blocks).", @@ -358,6 +359,9 @@ "vivecraft.options.keyboardtheme.aesthetic": "§bA§de§bs§dt§bh§de§bt§di§bc", "vivecraft.options.keyboardtheme.dose": "Medicine", "vivecraft.options.keyboardtheme.custom": "Custom", + "vivecraft.options.vrprovider.openvr": "OpenVR", + "vivecraft.options.vrprovider.openxr": "OpenXR", + "vivecraft.options.vrprovider.nullvr": "NullVR", "_comment8": "Button text", "vivecraft.gui.ok": "OK", "vivecraft.gui.clear": "Clear", diff --git a/fabric/build.gradle b/fabric/build.gradle index 530e818c2..f830d1050 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -67,6 +67,10 @@ dependencies { include(implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos")) include(implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows")) + include(implementation("org.lwjgl:lwjgl-openxr:3.3.1")) + include(implementation("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux")) + include(implementation("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows")) + } processResources { diff --git a/forge/build.gradle b/forge/build.gradle index 0631b1176..4cc790820 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -60,11 +60,19 @@ dependencies { forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows") + // shadow the natives bundle("org.lwjgl:lwjgl-openvr:3.3.2") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-linux") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") { transitive = false } + + bundle("org.lwjgl:lwjgl-openxr:3.3.1") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows") { transitive = false } } processResources { diff --git a/neoforge/build.gradle b/neoforge/build.gradle index a477d77cc..31afcfa1c 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -35,11 +35,19 @@ dependencies { forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows") + // shadow the natives bundle("org.lwjgl:lwjgl-openvr:3.3.2") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-linux") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") { transitive = false } + + bundle("org.lwjgl:lwjgl-openxr:3.3.1") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows") { transitive = false } } processResources { From d51fea36a7c89bc4ab282c2e120b33e117a350c4 Mon Sep 17 00:00:00 2001 From: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Date: Fri, 1 Nov 2024 13:38:43 +0100 Subject: [PATCH 02/27] add subactionPaths and XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT Co-Authored-By: The Judge <53906078+thejudge156@users.noreply.github.com> --- .../client_vr/provider/openxr/MCOpenXR.java | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 90444000a..41d7a0852 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -38,6 +38,7 @@ import org.vivecraft.common.utils.math.Matrix4f; import org.vivecraft.common.utils.math.Vector3; +import javax.annotation.Nullable; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; @@ -987,7 +988,7 @@ private void initializeOpenXRSwapChain() { XrSwapchainCreateInfo swapchainCreateInfo = XrSwapchainCreateInfo.calloc(stack); swapchainCreateInfo.type(XR10.XR_TYPE_SWAPCHAIN_CREATE_INFO); swapchainCreateInfo.next(NULL); - swapchainCreateInfo.createFlags(0); + swapchainCreateInfo.createFlags(XR10.XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT); swapchainCreateInfo.usageFlags(XR10.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT); swapchainCreateInfo.format(chosenFormat); swapchainCreateInfo.sampleCount(1); @@ -1207,24 +1208,24 @@ private void loadActionHandles() { } for (VRInputAction vrinputaction : this.inputActions.values()) { - long action = createAction(vrinputaction.name, vrinputaction.name, vrinputaction.type, new XrActionSet(this.actionSetHandles.get(vrinputaction.actionSet), instance)); + long action = createAction(vrinputaction.name, vrinputaction.name, vrinputaction.type, new XrActionSet(this.actionSetHandles.get(vrinputaction.actionSet), instance), null); vrinputaction.setHandle(action); } setupControllers(); XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.haptics[0] = createAction("/actions/global/out/righthaptic", "/actions/global/out/righthaptic", "haptic", actionSet); - this.haptics[1] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", "haptic", actionSet); + this.haptics[0] = createAction("/actions/global/out/righthaptic", "/actions/global/out/righthaptic", "haptic", actionSet, null); + this.haptics[1] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", "haptic", actionSet, null); } private void setupControllers() { XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.grip[0] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", "pose", actionSet); - this.grip[1] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", actionSet); - this.aim[0] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", "pose", actionSet); - this.aim[1] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", "pose", actionSet); + this.grip[0] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", "pose", actionSet, null); + this.grip[1] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", actionSet, null); + this.aim[0] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", "pose", actionSet, null); + this.aim[1] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", "pose", actionSet, null); } private void loadDefaultBindings() { @@ -1340,7 +1341,7 @@ public long getPath(String pathString) { }); } - private long createAction(String name, String localisedName, String type, XrActionSet actionSet) { + private long createAction(String name, String localisedName, String type, XrActionSet actionSet, @Nullable String[] subactionPaths) { try (MemoryStack stack = MemoryStack.stackPush()){ String s = name.split("/")[name.split("/").length -1].toLowerCase(); XrActionCreateInfo hands = XrActionCreateInfo.calloc(stack); @@ -1355,7 +1356,17 @@ private long createAction(String name, String localisedName, String type, XrActi case "haptic" -> hands.actionType(XR10.XR_ACTION_TYPE_VIBRATION_OUTPUT); } hands.countSubactionPaths(0); - hands.subactionPaths(null); + if(subactionPaths != null) { + LongBuffer buffer = stackCallocLong(subactionPaths.length); + for(String path : subactionPaths) { + buffer.put(getPath(path)); + } + hands.countSubactionPaths(subactionPaths.length); + hands.subactionPaths(buffer.rewind()); + } else { + hands.countSubactionPaths(0); + hands.subactionPaths(null); + } hands.localizedActionName(memUTF8(s)); PointerBuffer buffer = stackCallocPointer(1); From 2b97efb3e081438025b43bee4c9ceb06129082a9 Mon Sep 17 00:00:00 2001 From: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Date: Tue, 19 Nov 2024 19:05:59 +0100 Subject: [PATCH 03/27] test oculus openxr env --- .../client_vr/provider/openxr/MCOpenXR.java | 14 +++------ .../openxr/OpenXRHapticSchedular.java | 2 +- .../provider/openxr/OpenXRStereoRenderer.java | 30 +++++++++---------- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 41d7a0852..2cd42904a 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -880,14 +880,9 @@ private void initializeOpenXRSession() { session = new XrSession(sessionPtr.get(0), instance); - XrSessionBeginInfo sessionBeginInfo = XrSessionBeginInfo.calloc(stack); - sessionBeginInfo.type(XR10.XR_TYPE_SESSION_BEGIN_INFO); - sessionBeginInfo.next(NULL); - sessionBeginInfo.primaryViewConfigurationType(XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO); - - error = XR10.xrBeginSession(session, sessionBeginInfo); - logError(error, "xrBeginSession", ""); - this.isActive = true; + while (!this.isActive) { + pollVREvents(); + } } } @@ -988,7 +983,7 @@ private void initializeOpenXRSwapChain() { XrSwapchainCreateInfo swapchainCreateInfo = XrSwapchainCreateInfo.calloc(stack); swapchainCreateInfo.type(XR10.XR_TYPE_SWAPCHAIN_CREATE_INFO); swapchainCreateInfo.next(NULL); - swapchainCreateInfo.createFlags(XR10.XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT); + swapchainCreateInfo.createFlags(0); swapchainCreateInfo.usageFlags(XR10.XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT); swapchainCreateInfo.format(chosenFormat); swapchainCreateInfo.sampleCount(1); @@ -1355,7 +1350,6 @@ private long createAction(String name, String localisedName, String type, XrActi case "pose" -> hands.actionType(XR10.XR_ACTION_TYPE_POSE_INPUT); case "haptic" -> hands.actionType(XR10.XR_ACTION_TYPE_VIBRATION_OUTPUT); } - hands.countSubactionPaths(0); if(subactionPaths != null) { LongBuffer buffer = stackCallocLong(subactionPaths.length); for(String path : subactionPaths) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java index ae39e4f3a..819a355e8 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java @@ -26,7 +26,7 @@ private void triggerHapticPulse(ControllerType controller, float durationSeconds info.action(new XrAction(MCOpenXR.get().haptics[i], actionSet)); XrHapticVibration vibration = XrHapticVibration.calloc(stack); - vibration.type(XR10.XR_ACTION_TYPE_VIBRATION_OUTPUT); + vibration.type(XR10.XR_TYPE_HAPTIC_VIBRATION); vibration.next(NULL); vibration.duration((long) (durationSeconds * 1_000_000_000)); vibration.frequency(frequency); diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index aa787582f..5ae95cb22 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -12,12 +12,8 @@ import org.vivecraft.client_vr.provider.VRRenderer; import org.vivecraft.client_vr.render.RenderConfigException; -import java.nio.ByteBuffer; import java.nio.IntBuffer; -import static org.lwjgl.system.MemoryUtil.memAddress; -import static org.lwjgl.system.MemoryUtil.memUTF8; - public class OpenXRStereoRenderer extends VRRenderer { private final MCOpenXR openxr; private int swapIndex; @@ -129,9 +125,10 @@ public void endFrame() throws RenderConfigException { GL31.glBlitFramebuffer(0,0, getRightEyeTarget().viewWidth, getRightEyeTarget().viewHeight, 0,0, rightFramebuffers[swapIndex].viewWidth, rightFramebuffers[swapIndex].viewHeight, GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); try (MemoryStack stack = MemoryStack.stackPush()){ - PointerBuffer layers = stack.callocPointer(1); - int error; if (this.openxr.shouldRender) { + PointerBuffer layers = stack.callocPointer(1); + int error; + error = XR10.xrReleaseSwapchainImage( openxr.swapchain, XrSwapchainImageReleaseInfo.calloc(stack) @@ -144,17 +141,18 @@ public void endFrame() throws RenderConfigException { .views(projectionLayerViews); layers.put(compositionLayerProjection); + + layers.flip(); + + error = XR10.xrEndFrame( + openxr.session, + XrFrameEndInfo.calloc(stack) + .type(XR10.XR_TYPE_FRAME_END_INFO) + .displayTime(openxr.time) + .environmentBlendMode(XR10.XR_ENVIRONMENT_BLEND_MODE_OPAQUE) + .layers(layers)); + this.openxr.logAll(error, "xrEndFrame", ""); } - layers.flip(); - - error = XR10.xrEndFrame( - openxr.session, - XrFrameEndInfo.calloc(stack) - .type(XR10.XR_TYPE_FRAME_END_INFO) - .displayTime(openxr.time) - .environmentBlendMode(XR10.XR_ENVIRONMENT_BLEND_MODE_OPAQUE) - .layers(layers)); - this.openxr.logAll(error, "xrEndFrame", ""); projectionLayerViews.close(); } From 344dbb7b6fe81f51f0a4800c1fb7a69bdae5f540 Mon Sep 17 00:00:00 2001 From: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Date: Tue, 19 Nov 2024 19:32:37 +0100 Subject: [PATCH 04/27] now for real, not with steamVR as default... --- .../client_vr/provider/openxr/OpenXRStereoRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index 5ae95cb22..b90501845 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -70,7 +70,7 @@ public void setupRenderConfiguration(boolean render) throws Exception { super.setupRenderConfiguration(render); if (!render) { - return; + //return; } this.projectionLayerViews = XrCompositionLayerProjectionView.calloc(2); try (MemoryStack stack = MemoryStack.stackPush()){ @@ -125,7 +125,7 @@ public void endFrame() throws RenderConfigException { GL31.glBlitFramebuffer(0,0, getRightEyeTarget().viewWidth, getRightEyeTarget().viewHeight, 0,0, rightFramebuffers[swapIndex].viewWidth, rightFramebuffers[swapIndex].viewHeight, GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); try (MemoryStack stack = MemoryStack.stackPush()){ - if (this.openxr.shouldRender) { + if (true) { PointerBuffer layers = stack.callocPointer(1); int error; From 99969802915311601d7d5631d2224d75e7c963fb Mon Sep 17 00:00:00 2001 From: fayer3 Date: Thu, 21 Nov 2024 02:07:05 +0100 Subject: [PATCH 05/27] fix lwjgl openxr version --- fabric/build.gradle | 6 +++--- forge/build.gradle | 12 ++++++------ neoforge/build.gradle | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/fabric/build.gradle b/fabric/build.gradle index f830d1050..37623b624 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -67,9 +67,9 @@ dependencies { include(implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos")) include(implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows")) - include(implementation("org.lwjgl:lwjgl-openxr:3.3.1")) - include(implementation("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux")) - include(implementation("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows")) + include(implementation("org.lwjgl:lwjgl-openxr:3.3.2")) + include(implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux")) + include(implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows")) } diff --git a/forge/build.gradle b/forge/build.gradle index 4cc790820..787a4ecbf 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -60,9 +60,9 @@ dependencies { forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") // shadow the natives bundle("org.lwjgl:lwjgl-openvr:3.3.2") { transitive = false } @@ -70,9 +70,9 @@ dependencies { bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.1") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.2") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") { transitive = false } } processResources { diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 31afcfa1c..1151f4272 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -35,9 +35,9 @@ dependencies { forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") // shadow the natives bundle("org.lwjgl:lwjgl-openvr:3.3.2") { transitive = false } @@ -45,9 +45,9 @@ dependencies { bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.1") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.1:natives-linux") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.1:natives-windows") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.2") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") { transitive = false } } processResources { From f09afdd80e2f6ec5e05630901b10b1502f3c76eb Mon Sep 17 00:00:00 2001 From: Darien Johnson <84008186+CADIndie@users.noreply.github.com> Date: Sat, 23 Nov 2024 16:02:28 -0600 Subject: [PATCH 06/27] Fix Conformance Issues (#315) Co-authored-by: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Co-authored-by: The Judge <53906078+thejudge156@users.noreply.github.com> --- .../client_vr/provider/openxr/MCOpenXR.java | 16 +++++++++------- .../provider/openxr/OpenXRStereoRenderer.java | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 2cd42904a..c3d2393cf 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -1195,6 +1195,8 @@ public String getRuntimeName() { return "OpenXR"; } + private static final String[] BOTH_HANDS = new String[] {"/user/hand/left", "/user/hand/right"}; + //TODO Collect and register all actions private void loadActionHandles() { for (VRInputActionSet vrinputactionset : VRInputActionSet.values()) { @@ -1203,24 +1205,24 @@ private void loadActionHandles() { } for (VRInputAction vrinputaction : this.inputActions.values()) { - long action = createAction(vrinputaction.name, vrinputaction.name, vrinputaction.type, new XrActionSet(this.actionSetHandles.get(vrinputaction.actionSet), instance), null); + long action = createAction(vrinputaction.name, vrinputaction.name, vrinputaction.type, new XrActionSet(this.actionSetHandles.get(vrinputaction.actionSet), instance), BOTH_HANDS); vrinputaction.setHandle(action); } setupControllers(); XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.haptics[0] = createAction("/actions/global/out/righthaptic", "/actions/global/out/righthaptic", "haptic", actionSet, null); - this.haptics[1] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", "haptic", actionSet, null); + this.haptics[0] = createAction("/actions/global/out/righthaptic", "/actions/global/out/righthaptic", "haptic", actionSet, BOTH_HANDS); + this.haptics[1] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", "haptic", actionSet, BOTH_HANDS); } private void setupControllers() { XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.grip[0] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", "pose", actionSet, null); - this.grip[1] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", actionSet, null); - this.aim[0] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", "pose", actionSet, null); - this.aim[1] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", "pose", actionSet, null); + this.grip[0] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", "pose", actionSet, BOTH_HANDS); + this.grip[1] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", actionSet, BOTH_HANDS); + this.aim[0] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", "pose", actionSet, BOTH_HANDS); + this.aim[1] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", "pose", actionSet, BOTH_HANDS); } private void loadDefaultBindings() { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index b90501845..191e36397 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -70,7 +70,7 @@ public void setupRenderConfiguration(boolean render) throws Exception { super.setupRenderConfiguration(render); if (!render) { - //return; + return; } this.projectionLayerViews = XrCompositionLayerProjectionView.calloc(2); try (MemoryStack stack = MemoryStack.stackPush()){ @@ -151,7 +151,7 @@ public void endFrame() throws RenderConfigException { .displayTime(openxr.time) .environmentBlendMode(XR10.XR_ENVIRONMENT_BLEND_MODE_OPAQUE) .layers(layers)); - this.openxr.logAll(error, "xrEndFrame", ""); + this.openxr.logError(error, "xrEndFrame", ""); } projectionLayerViews.close(); From 68d7d90837e0f13d1e0ac6ac9143ee7e127a7824 Mon Sep 17 00:00:00 2001 From: Darien Johnson <84008186+CADIndie@users.noreply.github.com> Date: Sun, 24 Nov 2024 17:19:38 -0600 Subject: [PATCH 07/27] Create DeviceCompat for QuestCraft (#317) * Fix Conformance Issues Co-Authored-By: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Co-Authored-By: The Judge <53906078+thejudge156@users.noreply.github.com> * Create DeviceCompat for QuestCraft Co-Authored-By: The Judge <53906078+thejudge156@users.noreply.github.com> * fix lwjgl openxr version * Use Custom OpenXR Library * Switch to OpenXR 1.0.40 * Log Device Platform * Remove Discord from repo list --------- Co-authored-by: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Co-authored-by: The Judge <53906078+thejudge156@users.noreply.github.com> Co-authored-by: fayer3 --- build.gradle | 15 +- common/build.gradle | 2 +- .../vivecraft/client_vr/provider/MCVR.java | 3 + .../provider/openxr/DeviceCompat.java | 160 ++++++++++++++++++ .../client_vr/provider/openxr/MCOpenXR.java | 118 ++++--------- .../provider/openxr/OpenXRStereoRenderer.java | 63 ++++--- .../main/java/org/vivecraft/util/VLoader.java | 14 ++ fabric/build.gradle | 8 +- forge/build.gradle | 7 +- neoforge/build.gradle | 7 +- 10 files changed, 256 insertions(+), 141 deletions(-) create mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java create mode 100644 common/src/main/java/org/vivecraft/util/VLoader.java diff --git a/build.gradle b/build.gradle index 83ac7389a..7dfde6972 100644 --- a/build.gradle +++ b/build.gradle @@ -32,10 +32,11 @@ subprojects { implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") - implementation("org.lwjgl:lwjgl-openxr:3.3.2") + // Use custom OpenXR lib for Android and GLES bindings + implementation("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") - //implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-macos") implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") + } tasks.withType(JavaCompile) { @@ -124,7 +125,6 @@ allprojects { maven { url = "https://storage.googleapis.com/devan-maven/" } maven { url = "https://maven.shedaniel.me/" } maven { url = "https://aperlambda.github.io/maven" } - maven { url = "https://maven.kotlindiscord.com/repository/terraformers/" } maven { url = "https://mvn.devos.one/releases/" } maven { url = "https://mvn.devos.one/snapshots/" } maven { url = "https://maven.terraformersmc.com/" } @@ -146,17 +146,16 @@ allprojects { exclusiveContent { forRepository { ivy { - name = "Discord" - url = "https://cdn.discordapp.com/attachments/" + name = "GitHub" + url = "https://github.com/" patternLayout { - artifact '/[organisation]/[module]/[revision].[ext]' + artifact '/[organisation]/[module]/releases/download/[revision]/[classifier].jar' } metadataSources { artifact() } } } filter { - // discords are always just numbers - includeGroupByRegex "^\\d*\$" + } } } diff --git a/common/build.gradle b/common/build.gradle index d47d4b937..36714d62f 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -45,7 +45,7 @@ dependencies { compileOnly('com.electronwill.night-config:toml:3.6.6') //LaunchPopup - implementation 'com.github.fayer3:LaunchPopup:master-SNAPSHOT' + implementation 'fayer3:LaunchPopup:1.1.1:LaunchPopup-1.1.1' } // extract the LaunchPopup classes jar { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java index 74e11f821..63b9bc57a 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java @@ -30,6 +30,7 @@ import org.vivecraft.client_vr.provider.control.VRInputAction; import org.vivecraft.client_vr.provider.control.VRInputActionSet; import org.vivecraft.client_vr.provider.control.VivecraftMovementInput; +import org.vivecraft.client_vr.provider.openxr.DeviceCompat; import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.settings.VRHotkeys; @@ -115,11 +116,13 @@ public abstract class MCVR { protected Map inputActionsByKeyBinding = new HashMap<>(); protected final Map trackpadSwipeSamplers = new HashMap<>(); protected boolean inputInitialized; + public final DeviceCompat device; public MCVR(Minecraft mc, ClientDataHolderVR dh, VivecraftVRMod vrMod) { this.mc = mc; this.dh = dh; mod = vrMod; + this.device = DeviceCompat.detectDevice(); me = this; for (int i = 0; i < 3; ++i) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java new file mode 100644 index 000000000..ecb9987db --- /dev/null +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java @@ -0,0 +1,160 @@ +package org.vivecraft.client_vr.provider.openxr; + +import com.mojang.blaze3d.platform.Window; +import com.sun.jna.Platform; +import net.minecraft.client.Minecraft; +import org.lwjgl.PointerBuffer; +import org.lwjgl.glfw.GLFWNativeGLX; +import org.lwjgl.glfw.GLFWNativeWGL; +import org.lwjgl.glfw.GLFWNativeWin32; +import org.lwjgl.glfw.GLFWNativeX11; +import org.lwjgl.openxr.*; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.Struct; +import org.lwjgl.system.linux.X11; +import org.lwjgl.system.windows.User32; +import org.vivecraft.client_vr.settings.VRSettings; +import org.vivecraft.util.VLoader; + +import java.util.Objects; + +import static org.lwjgl.opengl.GLX13.*; +import static org.lwjgl.system.MemoryStack.stackInts; +import static org.lwjgl.system.MemoryUtil.NULL; + +//TODO: VulkanMod Support +public interface DeviceCompat { + long getPlatformInfo(MemoryStack stack); + void initOpenXRLoader(MemoryStack stack); + String getGraphicsExtension(); + XrSwapchainImageOpenGLKHR.Buffer createImageBuffers(int imageCount, MemoryStack stack); + Struct checkGraphics(MemoryStack stack, XrInstance instance, long systemID); + static DeviceCompat detectDevice() { + return System.getProperty("os.version").contains("Android") ? new Mobile() : new Desktop(); + } + + class Desktop implements DeviceCompat { + @Override + public long getPlatformInfo(MemoryStack stack) { + return NULL; + } + + @Override + public void initOpenXRLoader(MemoryStack stack) { + VRSettings.logger.info("Platform: {}", System.getProperty("os.version")); + } + + @Override + public String getGraphicsExtension() { + return KHROpenGLEnable.XR_KHR_OPENGL_ENABLE_EXTENSION_NAME; + } + + @Override + public XrSwapchainImageOpenGLKHR.Buffer createImageBuffers(int imageCount, MemoryStack stack) { + XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = XrSwapchainImageOpenGLKHR.calloc(imageCount, stack); + for (XrSwapchainImageOpenGLKHR image : swapchainImageBuffer) { + image.type(KHROpenGLEnable.XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR); + } + + return swapchainImageBuffer; + } + + @Override + public Struct checkGraphics(MemoryStack stack, XrInstance instance, long systemID) { + XrGraphicsRequirementsOpenGLKHR graphicsRequirements = XrGraphicsRequirementsOpenGLKHR.calloc(stack).type(KHROpenGLEnable.XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR); + KHROpenGLEnable.xrGetOpenGLGraphicsRequirementsKHR(instance, systemID, graphicsRequirements); + //Bind the OpenGL context to the OpenXR instance and create the session + Window window = Minecraft.getInstance().getWindow(); + long windowHandle = window.getWindow(); + if (Platform.getOSType() == Platform.WINDOWS) { + return XrGraphicsBindingOpenGLWin32KHR.calloc(stack).set( + KHROpenGLEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, + NULL, + User32.GetDC(GLFWNativeWin32.glfwGetWin32Window(windowHandle)), + GLFWNativeWGL.glfwGetWGLContext(windowHandle) + ); + } else if (Platform.getOSType() == Platform.LINUX) { + long xDisplay = GLFWNativeX11.glfwGetX11Display(); + + long glXContext = GLFWNativeGLX.glfwGetGLXContext(windowHandle); + long glXWindowHandle = GLFWNativeGLX.glfwGetGLXWindow(windowHandle); + + int fbXID = glXQueryDrawable(xDisplay, glXWindowHandle, GLX_FBCONFIG_ID); + PointerBuffer fbConfigBuf = glXChooseFBConfig(xDisplay, X11.XDefaultScreen(xDisplay), stackInts(GLX_FBCONFIG_ID, fbXID, 0)); + if (fbConfigBuf == null) { + throw new IllegalStateException("Your framebuffer config was null, make a github issue"); + } + long fbConfig = fbConfigBuf.get(); + + return XrGraphicsBindingOpenGLXlibKHR.calloc(stack).set( + KHROpenGLEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, + NULL, + xDisplay, + (int) Objects.requireNonNull(glXGetVisualFromFBConfig(xDisplay, fbConfig)).visualid(), + fbConfig, + glXWindowHandle, + glXContext + ); + } else { + throw new IllegalStateException("Macos not supported"); + } + } + } + + class Mobile implements DeviceCompat { + @Override + public long getPlatformInfo(MemoryStack stack) { + return XrInstanceCreateInfoAndroidKHR.calloc(stack).set( + KHRAndroidCreateInstance.XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, + NULL, + VLoader.getDalvikVM(), + VLoader.getDalvikActivity() + ).address(); + } + + @Override + public void initOpenXRLoader(MemoryStack stack) { + VRSettings.logger.info("Platform: {}", System.getProperty("os.version")); + VLoader.setupAndroid(); + XrLoaderInitInfoAndroidKHR initInfo = XrLoaderInitInfoAndroidKHR.calloc(stack).set( + KHRLoaderInitAndroid.XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR, + NULL, + VLoader.getDalvikVM(), + VLoader.getDalvikActivity() + ); + + KHRLoaderInit.xrInitializeLoaderKHR(XrLoaderInitInfoBaseHeaderKHR.create(initInfo.address())); + } + + @Override + public String getGraphicsExtension() { + return KHROpenGLESEnable.XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME; + } + + @Override + public XrSwapchainImageOpenGLKHR.Buffer createImageBuffers(int imageCount, MemoryStack stack) { + XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = XrSwapchainImageOpenGLKHR.calloc(imageCount, stack); + for (XrSwapchainImageOpenGLKHR image : swapchainImageBuffer) { + image.type(KHROpenGLESEnable.XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR); + } + + return swapchainImageBuffer; + } + + @Override + public Struct checkGraphics(MemoryStack stack, XrInstance instance, long systemID) { + XrGraphicsRequirementsOpenGLESKHR graphicsRequirements = XrGraphicsRequirementsOpenGLESKHR.calloc(stack).type(KHROpenGLESEnable.XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR); + KHROpenGLESEnable.xrGetOpenGLESGraphicsRequirementsKHR(instance, systemID, graphicsRequirements); + XrGraphicsBindingOpenGLESAndroidKHR graphicsBinding = XrGraphicsBindingOpenGLESAndroidKHR.calloc(stack); + graphicsBinding.set( + KHROpenGLESEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR, + NULL, + VLoader.getEGLDisplay(), + VLoader.getEGLConfig(), + VLoader.getEGLContext() + ); + + return graphicsBinding; + } + } +} diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index c3d2393cf..3340d5f57 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -1,6 +1,5 @@ package org.vivecraft.client_vr.provider.openxr; -import com.mojang.blaze3d.platform.Window; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.util.Mth; @@ -15,10 +14,6 @@ import org.lwjgl.opengl.GL31; import org.lwjgl.openxr.*; import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.Platform; -import org.lwjgl.system.Struct; -import org.lwjgl.system.linux.X11; -import org.lwjgl.system.windows.User32; import org.vivecraft.client.VivecraftVRMod; import org.vivecraft.client.utils.Utils; import org.vivecraft.client_vr.ClientDataHolderVR; @@ -44,7 +39,6 @@ import java.nio.LongBuffer; import java.util.*; -import static org.lwjgl.opengl.GLX13.*; import static org.lwjgl.system.MemoryStack.*; import static org.lwjgl.system.MemoryUtil.*; @@ -770,6 +764,7 @@ public boolean init() { private void initializeOpenXRInstance() { try (MemoryStack stack = MemoryStack.stackPush()) { + device.initOpenXRLoader(stack); //Check extensions IntBuffer numExtensions = stack.callocInt(1); @@ -785,14 +780,15 @@ private void initializeOpenXRInstance() { logError(error, "xrEnumerateInstanceExtensionProperties", "get extensions"); //get needed extensions - boolean missingOpenGL = true; + String graphicsExtension = device.getGraphicsExtension(); + boolean missingGraphics = true; PointerBuffer extensions = stack.callocPointer(3); while (properties.hasRemaining()) { XrExtensionProperties prop = properties.get(); String extensionName = prop.extensionNameString(); - if (extensionName.equals(KHROpenGLEnable.XR_KHR_OPENGL_ENABLE_EXTENSION_NAME)) { - missingOpenGL = false; - extensions.put(memAddress(stackUTF8(KHROpenGLEnable.XR_KHR_OPENGL_ENABLE_EXTENSION_NAME))); + if (extensionName.equals(graphicsExtension)) { + missingGraphics = false; + extensions.put(memAddress(stackUTF8(graphicsExtension))); } if (extensionName.equals(EXTHPMixedRealityController.XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME)) { extensions.put(memAddress(stackUTF8(EXTHPMixedRealityController.XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))); @@ -802,20 +798,20 @@ private void initializeOpenXRInstance() { } } - if (missingOpenGL) { - throw new RuntimeException("OpenXR runtime does not support OpenGL, try using SteamVR instead"); + if (missingGraphics) { + throw new RuntimeException("OpenXR runtime is missing a supported graphics extension."); } //Create APP info XrApplicationInfo applicationInfo = XrApplicationInfo.calloc(stack); - applicationInfo.apiVersion(XR10.XR_CURRENT_API_VERSION); + applicationInfo.apiVersion(XR10.XR_MAKE_VERSION(1, 0, 40)); applicationInfo.applicationName(stack.UTF8("Vivecraft")); applicationInfo.applicationVersion(1); //Create instance info XrInstanceCreateInfo createInfo = XrInstanceCreateInfo.calloc(stack); createInfo.type(XR10.XR_TYPE_INSTANCE_CREATE_INFO); - createInfo.next(NULL); + createInfo.next(device.getPlatformInfo(stack)); createInfo.createFlags(0); createInfo.applicationInfo(applicationInfo); createInfo.enabledApiLayerNames(null); @@ -864,13 +860,29 @@ private void initializeOpenXRSession() { throw new RuntimeException("No compatible headset detected"); } - //Bind graphics - Struct graphics = this.getGraphicsAPI(stack); + XrSystemProperties systemProperties = XrSystemProperties.calloc(stack).type(XR10.XR_TYPE_SYSTEM_PROPERTIES); + error = XR10.xrGetSystemProperties(instance, systemID, systemProperties); + MCOpenXR.get().logError(error, "xrGetSystemProperties", ""); + XrSystemTrackingProperties trackingProperties = systemProperties.trackingProperties(); + XrSystemGraphicsProperties graphicsProperties = systemProperties.graphicsProperties(); + + MCOpenXR.get().systemName = memUTF8(memAddress(systemProperties.systemName())); + int vendor = systemProperties.vendorId(); + boolean orientationTracking = trackingProperties.orientationTracking(); + boolean positionTracking = trackingProperties.positionTracking(); + int maxWidth = graphicsProperties.maxSwapchainImageWidth(); + int maxHeight = graphicsProperties.maxSwapchainImageHeight(); + int maxLayerCount = graphicsProperties.maxLayerCount(); + + VRSettings.logger.info("Found device with id: {}", systemID); + VRSettings.logger.info("Headset Name: {}, Vendor: {}", MCOpenXR.get().systemName, vendor); + VRSettings.logger.info("Headset Orientation Tracking: {}, Position Tracking: {}", orientationTracking, positionTracking); + VRSettings.logger.info("Headset Max Width: {}, Max Height: {}, Max Layer Count: {}", maxWidth, maxHeight, maxLayerCount); //Create session XrSessionCreateInfo info = XrSessionCreateInfo.calloc(stack); info.type(XR10.XR_TYPE_SESSION_CREATE_INFO); - info.next(graphics.address()); + info.next(device.checkGraphics(stack, instance, systemID).address()); info.createFlags(0); info.systemId(systemID); @@ -1002,66 +1014,6 @@ private void initializeOpenXRSwapChain() { } } - private Struct getGraphicsAPI(MemoryStack stack) { - XrGraphicsRequirementsOpenGLKHR graphicsRequirements = XrGraphicsRequirementsOpenGLKHR.calloc(stack).type(KHROpenGLEnable.XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR); - KHROpenGLEnable.xrGetOpenGLGraphicsRequirementsKHR(instance, systemID, graphicsRequirements); - - XrSystemProperties systemProperties = XrSystemProperties.calloc(stack).type(XR10.XR_TYPE_SYSTEM_PROPERTIES); - int error = XR10.xrGetSystemProperties(instance, systemID, systemProperties); - logError(error, "xrGetSystemProperties", ""); - XrSystemTrackingProperties trackingProperties = systemProperties.trackingProperties(); - XrSystemGraphicsProperties graphicsProperties = systemProperties.graphicsProperties(); - - this.systemName = memUTF8(memAddress(systemProperties.systemName())); - int vendor = systemProperties.vendorId(); - boolean orientationTracking = trackingProperties.orientationTracking(); - boolean positionTracking = trackingProperties.positionTracking(); - int maxWidth = graphicsProperties.maxSwapchainImageWidth(); - int maxHeight = graphicsProperties.maxSwapchainImageHeight(); - int maxLayerCount = graphicsProperties.maxLayerCount(); - - VRSettings.logger.info("Found device with id: {}", systemID); - VRSettings.logger.info("Headset Name: {}, Vendor: {}", systemName, vendor); - VRSettings.logger.info("Headset Orientation Tracking: {}, Position Tracking: {}", orientationTracking, positionTracking); - VRSettings.logger.info("Headset Max Width: {}, Max Height: {}, Max Layer Count: {}", maxWidth, maxHeight, maxLayerCount); - - //Bind the OpenGL context to the OpenXR instance and create the session - Window window = mc.getWindow(); - long windowHandle = window.getWindow(); - if (Platform.get() == Platform.WINDOWS) { - return XrGraphicsBindingOpenGLWin32KHR.calloc(stack).set( - KHROpenGLEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, - NULL, - User32.GetDC(GLFWNativeWin32.glfwGetWin32Window(windowHandle)), - GLFWNativeWGL.glfwGetWGLContext(windowHandle) - ); - } else if (Platform.get() == Platform.LINUX) { - long xDisplay = GLFWNativeX11.glfwGetX11Display(); - - long glXContext = GLFWNativeGLX.glfwGetGLXContext(windowHandle); - long glXWindowHandle = GLFWNativeGLX.glfwGetGLXWindow(windowHandle); - - int fbXID = glXQueryDrawable(xDisplay, glXWindowHandle, GLX_FBCONFIG_ID); - PointerBuffer fbConfigBuf = glXChooseFBConfig(xDisplay, X11.XDefaultScreen(xDisplay), stackInts(GLX_FBCONFIG_ID, fbXID, 0)); - if(fbConfigBuf == null) { - throw new IllegalStateException("Your framebuffer config was null, make a github issue"); - } - long fbConfig = fbConfigBuf.get(); - - return XrGraphicsBindingOpenGLXlibKHR.calloc(stack).set( - KHROpenGLEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, - NULL, - xDisplay, - (int) Objects.requireNonNull(glXGetVisualFromFBConfig(xDisplay, fbConfig)).visualid(), - fbConfig, - glXWindowHandle, - glXContext - ); - } else { - throw new IllegalStateException("Macos not supported"); - } - } - /** * Creates an array of XrStructs with their types pre set to @param type */ @@ -1486,16 +1438,4 @@ protected void logError(int xrResult, String caller, String... args) { VRSettings.logger.error("{} for {} errored: {}", caller, String.join(" ", args), getResultName(xrResult)); } } - - /** - * logs all results except XR_SUCCESS - * @param xrResult result to check - * @param caller where the xrResult came from - * @param args arguments may be helpful in locating the error - */ - protected void logAll(int xrResult, String caller, String... args) { - if (xrResult != XR10.XR_SUCCESS) { - VRSettings.logger.error("{} for {} errored: {}", caller, String.join(" ", args), getResultName(xrResult)); - } - } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index 191e36397..aa8352b38 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -41,10 +41,7 @@ public void createRenderTexture(int width, int height) throws RenderConfigExcept //Now we know the amount, create the image buffer int imageCount = intBuffer.get(0); - XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = XrSwapchainImageOpenGLKHR.calloc(imageCount, stack); - for (XrSwapchainImageOpenGLKHR image : swapchainImageBuffer) { - image.type(KHROpenGLEnable.XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR); - } + XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = this.openxr.device.createImageBuffers(imageCount, stack); error = XR10.xrEnumerateSwapchainImages(openxr.swapchain, intBuffer, XrSwapchainImageBaseHeader.create(swapchainImageBuffer.address(), swapchainImageBuffer.capacity())); this.openxr.logError(error, "xrEnumerateSwapchainImages", "get images"); @@ -116,6 +113,7 @@ public Matrix4f getProjectionMatrix(int eyeType, float nearClip, float farClip) @Override public void endFrame() throws RenderConfigException { + GL31.glBindFramebuffer(GL31.GL_READ_FRAMEBUFFER, getLeftEyeTarget().frameBufferId); GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, leftFramebuffers[swapIndex].frameBufferId); GL31.glBlitFramebuffer(0,0, getLeftEyeTarget().viewWidth, getLeftEyeTarget().viewHeight, 0,0, leftFramebuffers[swapIndex].viewWidth, leftFramebuffers[swapIndex].viewHeight, GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); @@ -124,35 +122,34 @@ public void endFrame() throws RenderConfigException { GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, rightFramebuffers[swapIndex].frameBufferId); GL31.glBlitFramebuffer(0,0, getRightEyeTarget().viewWidth, getRightEyeTarget().viewHeight, 0,0, rightFramebuffers[swapIndex].viewWidth, rightFramebuffers[swapIndex].viewHeight, GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); + try (MemoryStack stack = MemoryStack.stackPush()){ - if (true) { - PointerBuffer layers = stack.callocPointer(1); - int error; - - error = XR10.xrReleaseSwapchainImage( - openxr.swapchain, - XrSwapchainImageReleaseInfo.calloc(stack) - .type(XR10.XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO)); - this.openxr.logError(error, "xrReleaseSwapchainImage", ""); - - XrCompositionLayerProjection compositionLayerProjection = XrCompositionLayerProjection.calloc(stack) - .type(XR10.XR_TYPE_COMPOSITION_LAYER_PROJECTION) - .space(openxr.xrAppSpace) - .views(projectionLayerViews); - - layers.put(compositionLayerProjection); - - layers.flip(); - - error = XR10.xrEndFrame( - openxr.session, - XrFrameEndInfo.calloc(stack) - .type(XR10.XR_TYPE_FRAME_END_INFO) - .displayTime(openxr.time) - .environmentBlendMode(XR10.XR_ENVIRONMENT_BLEND_MODE_OPAQUE) - .layers(layers)); - this.openxr.logError(error, "xrEndFrame", ""); - } + PointerBuffer layers = stack.callocPointer(1); + int error; + + error = XR10.xrReleaseSwapchainImage( + openxr.swapchain, + XrSwapchainImageReleaseInfo.calloc(stack) + .type(XR10.XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO)); + this.openxr.logError(error, "xrReleaseSwapchainImage", ""); + + XrCompositionLayerProjection compositionLayerProjection = XrCompositionLayerProjection.calloc(stack) + .type(XR10.XR_TYPE_COMPOSITION_LAYER_PROJECTION) + .space(openxr.xrAppSpace) + .views(projectionLayerViews); + + layers.put(compositionLayerProjection); + + layers.flip(); + + error = XR10.xrEndFrame( + openxr.session, + XrFrameEndInfo.calloc(stack) + .type(XR10.XR_TYPE_FRAME_END_INFO) + .displayTime(openxr.time) + .environmentBlendMode(XR10.XR_ENVIRONMENT_BLEND_MODE_OPAQUE) + .layers(layers)); + this.openxr.logError(error, "xrEndFrame", ""); projectionLayerViews.close(); } @@ -177,4 +174,4 @@ public RenderTarget getRightEyeTarget() { public Tuple getRenderTextureSizes() { return new Tuple<>(openxr.width, openxr.height); } -} +} \ No newline at end of file diff --git a/common/src/main/java/org/vivecraft/util/VLoader.java b/common/src/main/java/org/vivecraft/util/VLoader.java new file mode 100644 index 000000000..cecdd9a10 --- /dev/null +++ b/common/src/main/java/org/vivecraft/util/VLoader.java @@ -0,0 +1,14 @@ +package org.vivecraft.util; + +public class VLoader { + static { + System.loadLibrary("vloader"); + } + + public static native long getEGLContext(); + public static native long getEGLConfig(); + public static native long getEGLDisplay(); + public static native long getDalvikVM(); + public static native long getDalvikActivity(); + public static native void setupAndroid(); +} diff --git a/fabric/build.gradle b/fabric/build.gradle index 37623b624..36378cb5d 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -67,10 +67,10 @@ dependencies { include(implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos")) include(implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows")) - include(implementation("org.lwjgl:lwjgl-openxr:3.3.2")) - include(implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux")) + // Use custom OpenXR lib for Android and GLES bindings + include(implementation("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2")) include(implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows")) - + include(implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux")) } processResources { @@ -128,4 +128,4 @@ publishing { repositories { // Add repositories to publish to here. } -} +} \ No newline at end of file diff --git a/forge/build.gradle b/forge/build.gradle index 787a4ecbf..1557fdbd5 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -60,7 +60,8 @@ dependencies { forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2") + // Use custom OpenXR lib for Android and GLES bindings + forgeRuntimeLibrary("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") @@ -70,7 +71,7 @@ dependencies { bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.2") { transitive = false } + bundle("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") { transitive = false } bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") { transitive = false } bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") { transitive = false } } @@ -133,4 +134,4 @@ publishing { repositories { // Add repositories to publish to here. } -} +} \ No newline at end of file diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 1151f4272..f88cb0e37 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -35,7 +35,8 @@ dependencies { forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2") + // Use custom OpenXR lib for Android and GLES bindings + forgeRuntimeLibrary("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") @@ -45,7 +46,7 @@ dependencies { bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") { transitive = false } bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.2") { transitive = false } + bundle("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") { transitive = false } bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") { transitive = false } bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") { transitive = false } } @@ -109,4 +110,4 @@ publishing { repositories { // Add repositories to publish to here. } -} +} \ No newline at end of file From c154b9dd8bad5102d5e923745e232e505b907b8a Mon Sep 17 00:00:00 2001 From: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Date: Tue, 3 Dec 2024 20:19:52 +0100 Subject: [PATCH 08/27] update after cleanup --- .../provider/openxr/DeviceCompat.java | 4 +- .../client_vr/provider/openxr/MCOpenXR.java | 54 ++++++++----------- .../provider/openxr/OpenXRStereoRenderer.java | 19 ++++--- .../render/helpers/ShaderHelper.java | 14 ++--- .../client_vr/settings/VRSettings.java | 3 +- 5 files changed, 45 insertions(+), 49 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java index ecb9987db..c3cff1fc4 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java @@ -41,7 +41,7 @@ public long getPlatformInfo(MemoryStack stack) { @Override public void initOpenXRLoader(MemoryStack stack) { - VRSettings.logger.info("Platform: {}", System.getProperty("os.version")); + VRSettings.LOGGER.info("Platform: {}", System.getProperty("os.version")); } @Override @@ -114,7 +114,7 @@ public long getPlatformInfo(MemoryStack stack) { @Override public void initOpenXRLoader(MemoryStack stack) { - VRSettings.logger.info("Platform: {}", System.getProperty("os.version")); + VRSettings.LOGGER.info("Platform: {}", System.getProperty("os.version")); VLoader.setupAndroid(); XrLoaderInitInfoAndroidKHR initInfo = XrLoaderInitInfoAndroidKHR.calloc(stack).set( KHRLoaderInitAndroid.XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR, diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 3340d5f57..ee1e01e2b 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -15,7 +15,7 @@ import org.lwjgl.openxr.*; import org.lwjgl.system.MemoryStack; import org.vivecraft.client.VivecraftVRMod; -import org.vivecraft.client.utils.Utils; +import org.vivecraft.client.utils.MathUtils; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.RadialHandler; @@ -25,7 +25,6 @@ import org.vivecraft.client_vr.provider.VRRenderer; import org.vivecraft.client_vr.provider.control.VRInputAction; import org.vivecraft.client_vr.provider.control.VRInputActionSet; -import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.client_xr.render_pass.RenderPassManager; @@ -44,7 +43,7 @@ public class MCOpenXR extends MCVR { - private static MCOpenXR ome; + private static MCOpenXR OME; public XrInstance instance; public XrSession session; public XrSpace xrAppSpace; @@ -78,7 +77,7 @@ public class MCOpenXR extends MCVR { public MCOpenXR(Minecraft mc, ClientDataHolderVR dh) { super(mc, dh, VivecraftVRMod.INSTANCE); - ome = this; + OME = this; this.hapticScheduler = new OpenXRHapticSchedular(); } @@ -88,11 +87,6 @@ public String getName() { return "OpenXR"; } - @Override - public String getID() { - return "openxr"; - } - @Override public void destroy() { int error; @@ -287,7 +281,7 @@ private void updatePose() { this.aimSource[0] = new Vec3(space_location.pose().position$().x(), space_location.pose().position$().y(), space_location.pose().position$().z()); this.controllerHistory[0].add(this.getAimSource(0)); this.controllerForwardHistory[0].add(this.getAimSource(0)); - Vec3 vec33 = this.controllerRotation[0].transform(this.up).toVector3d(); + Vec3 vec33 = this.controllerRotation[0].transform(UP).toVector3d(); this.controllerUpHistory[0].add(vec33); this.controllerTracking[0] = true; } else { @@ -302,7 +296,7 @@ private void updatePose() { this.aimSource[1] = new Vec3(space_location.pose().position$().x(), space_location.pose().position$().y(), space_location.pose().position$().z()); this.controllerHistory[1].add(this.getAimSource(1)); this.controllerForwardHistory[1].add(this.getAimSource(1)); - Vec3 vec32 = this.controllerRotation[1].transform(this.up).toVector3d(); + Vec3 vec32 = this.controllerRotation[1].transform(UP).toVector3d(); this.controllerUpHistory[1].add(vec32); this.controllerTracking[1] = true; } else { @@ -317,8 +311,8 @@ private void updatePose() { this.handRotation[1] = hmdRotation; this.controllerRotation[0] = hmdRotation; this.controllerRotation[1] = hmdRotation; - this.aimSource[1] = this.getCenterEyePosition(); - this.aimSource[0] = this.getCenterEyePosition(); + this.aimSource[1] = this.getEyePosition(RenderPass.CENTER); + this.aimSource[0] = this.getEyePosition(RenderPass.CENTER); if (this.mc.screen == null) { Vec3 vec31 = this.getAimVector(1); @@ -427,7 +421,7 @@ public Vec3 getEyePosition(RenderPass eye) { if (matrix4f == null) { org.vivecraft.common.utils.math.Matrix4f matrix4f2 = this.hmdPose; - Vector3 vector31 = Utils.convertMatrix4ftoTranslationVector(matrix4f2); + Vector3 vector31 = MathUtils.convertMatrix4ftoTranslationVector(matrix4f2); if (this.dh.vrSettings.seated || this.dh.vrSettings.allowStandingOriginOffset) { if (this.dh.vr.isHMDTracking()) { @@ -437,7 +431,7 @@ public Vec3 getEyePosition(RenderPass eye) { return vector31.toVector3d(); } else { - Vector3 vector3 = Utils.convertMatrix4ftoTranslationVector(matrix4f); + Vector3 vector3 = MathUtils.convertMatrix4ftoTranslationVector(matrix4f); if (this.dh.vrSettings.seated || this.dh.vrSettings.allowStandingOriginOffset) { if (this.dh.vr.isHMDTracking()) { @@ -623,7 +617,7 @@ private boolean updateActiveActionSets() { } } - if (KeyboardHandler.Showing || RadialHandler.isShowing()) { + if (KeyboardHandler.SHOWING || RadialHandler.isShowing()) { arraylist.add(VRInputActionSet.KEYBOARD); } @@ -740,6 +734,7 @@ public boolean init() { this.initializeOpenXRSession(); this.initializeOpenXRSpace(); this.initializeOpenXRSwapChain(); + this.initInputAndApplication(); } catch (Exception e) { e.printStackTrace(); this.initSuccess = false; @@ -840,7 +835,7 @@ private void initializeOpenXRInstance() { } public static MCOpenXR get() { - return ome; + return OME; } private void initializeOpenXRSession() { @@ -874,10 +869,10 @@ private void initializeOpenXRSession() { int maxHeight = graphicsProperties.maxSwapchainImageHeight(); int maxLayerCount = graphicsProperties.maxLayerCount(); - VRSettings.logger.info("Found device with id: {}", systemID); - VRSettings.logger.info("Headset Name: {}, Vendor: {}", MCOpenXR.get().systemName, vendor); - VRSettings.logger.info("Headset Orientation Tracking: {}, Position Tracking: {}", orientationTracking, positionTracking); - VRSettings.logger.info("Headset Max Width: {}, Max Height: {}, Max Layer Count: {}", maxWidth, maxHeight, maxLayerCount); + VRSettings.LOGGER.info("Found device with id: {}", systemID); + VRSettings.LOGGER.info("Headset Name: {}, Vendor: {}", MCOpenXR.get().systemName, vendor); + VRSettings.LOGGER.info("Headset Orientation Tracking: {}, Position Tracking: {}", orientationTracking, positionTracking); + VRSettings.LOGGER.info("Headset Max Width: {}, Max Height: {}, Max Layer Count: {}", maxWidth, maxHeight, maxLayerCount); //Create session XrSessionCreateInfo info = XrSessionCreateInfo.calloc(stack); @@ -1028,13 +1023,6 @@ static ByteBuffer bufferStack(int capacity, int sizeof, int type) { return b; } - - @Override - public boolean postinit() throws RenderConfigException { - this.initInputAndApplication(); - return inputInitialized; - } - private void initInputAndApplication() { this.populateInputActions(); @@ -1049,11 +1037,11 @@ private void initInputAndApplication() { @Override public Matrix4f getControllerComponentTransform(int var1, String var2) { - return Utils.Matrix4fSetIdentity(new Matrix4f()); + return new Matrix4f(); } @Override - public boolean hasThirdController() { + public boolean hasCameraTracker() { return false; } @@ -1181,7 +1169,7 @@ private void loadDefaultBindings() { try (MemoryStack stack = MemoryStack.stackPush()) { int error; for (String headset: XRBindings.supportedHeadsets()) { - VRSettings.logger.info("loading defaults for {}", headset); + VRSettings.LOGGER.info("loading defaults for {}", headset); Pair[] defaultBindings = XRBindings.getBinding(headset).toArray(new Pair[0]); XrActionSuggestedBinding.Buffer bindings = XrActionSuggestedBinding.calloc(defaultBindings.length + 6, stack); //TODO different way of adding controller poses @@ -1189,7 +1177,7 @@ private void loadDefaultBindings() { Pair pair = defaultBindings[i]; VRInputAction binding = this.getInputActionByName(pair.getLeft()); if (binding.handle == 0L) { - VRSettings.logger.error("Handle for '{}'/'{}' is null", pair.getLeft(), pair.getRight()); + VRSettings.LOGGER.error("Handle for '{}'/'{}' is null", pair.getLeft(), pair.getRight()); continue; } bindings.get(i).set( @@ -1435,7 +1423,7 @@ private String getResultName(int xrResult) { */ protected void logError(int xrResult, String caller, String... args) { if (xrResult < 0) { - VRSettings.logger.error("{} for {} errored: {}", caller, String.join(" ", args), getResultName(xrResult)); + VRSettings.LOGGER.error("{} for {} errored: {}", caller, String.join(" ", args), getResultName(xrResult)); } } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index aa8352b38..3cebe96cc 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -11,7 +11,9 @@ import org.vivecraft.client_vr.VRTextureTarget; import org.vivecraft.client_vr.provider.VRRenderer; import org.vivecraft.client_vr.render.RenderConfigException; +import org.vivecraft.client_vr.render.helpers.RenderHelper; +import java.io.IOException; import java.nio.IntBuffer; public class OpenXRStereoRenderer extends VRRenderer { @@ -52,18 +54,18 @@ public void createRenderTexture(int width, int height) throws RenderConfigExcept for (int i = 0; i < imageCount; i++) { XrSwapchainImageOpenGLKHR openxrImage = swapchainImageBuffer.get(i); leftFramebuffers[i] = new VRTextureTarget("L Eye " + i, width, height, openxrImage.image(), 0); - this.checkGLError("Left Eye framebuffer setup"); + RenderHelper.checkGLError("Left Eye framebuffer setup"); rightFramebuffers[i] = new VRTextureTarget("R Eye " + i, width, height, openxrImage.image(), 1); - this.checkGLError("Right Eye framebuffer setup"); + RenderHelper.checkGLError("Right Eye framebuffer setup"); } - this.rightFramebuffer = new VRTextureTarget("R Eye mirror", width, height, true, false, -1, true, true, ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); - this.leftFramebuffer = new VRTextureTarget("L Eye mirror", width, height, true, false, -1, true, true, ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); + this.rightFramebuffer = new VRTextureTarget("R Eye mirror", width, height, true, -1, true, true, ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); + this.leftFramebuffer = new VRTextureTarget("L Eye mirror", width, height, true, -1, true, true, ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); } } @Override - public void setupRenderConfiguration(boolean render) throws Exception { + public void setupRenderConfiguration(boolean render) throws IOException, RenderConfigException { super.setupRenderConfiguration(render); if (!render) { @@ -170,8 +172,13 @@ public RenderTarget getRightEyeTarget() { return rightFramebuffer; } + @Override + public String getName() { + return "OpenXR"; + } + @Override public Tuple getRenderTextureSizes() { return new Tuple<>(openxr.width, openxr.height); } -} \ No newline at end of file +} diff --git a/common/src/main/java/org/vivecraft/client_vr/render/helpers/ShaderHelper.java b/common/src/main/java/org/vivecraft/client_vr/render/helpers/ShaderHelper.java index f74b94efc..3396a2d6a 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/helpers/ShaderHelper.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/helpers/ShaderHelper.java @@ -253,8 +253,8 @@ public static void drawMirror() { )) { // show both eyes side by side - RenderTarget leftEye = DATA_HOLDER.vrRenderer.framebufferEye0; - RenderTarget rightEye = DATA_HOLDER.vrRenderer.framebufferEye1; + RenderTarget leftEye = DATA_HOLDER.vrRenderer.getLeftEyeTarget(); + RenderTarget rightEye = DATA_HOLDER.vrRenderer.getRightEyeTarget(); int screenWidth = ((WindowExtension) (Object) MC.getWindow()).vivecraft$getActualScreenWidth() / 2; int screenHeight = ((WindowExtension) (Object) MC.getWindow()).vivecraft$getActualScreenHeight(); @@ -271,7 +271,7 @@ public static void drawMirror() { float xCrop = 0.0F; float yCrop = 0.0F; boolean keepAspect = false; - RenderTarget source = DATA_HOLDER.vrRenderer.framebufferEye0; + RenderTarget source = DATA_HOLDER.vrRenderer.getLeftEyeTarget(); if (DATA_HOLDER.vrSettings.displayMirrorUseScreenshotCamera && DATA_HOLDER.cameraTracker.isVisible()) @@ -288,11 +288,11 @@ public static void drawMirror() { DATA_HOLDER.vrSettings.displayMirrorMode == VRSettings.MirrorMode.OFF) { if (!DATA_HOLDER.vrSettings.displayMirrorLeftEye) { - source = DATA_HOLDER.vrRenderer.framebufferEye1; + source = DATA_HOLDER.vrRenderer.getRightEyeTarget(); } } else if (DATA_HOLDER.vrSettings.displayMirrorMode == VRSettings.MirrorMode.CROPPED) { if (!DATA_HOLDER.vrSettings.displayMirrorLeftEye) { - source = DATA_HOLDER.vrRenderer.framebufferEye1; + source = DATA_HOLDER.vrRenderer.getRightEyeTarget(); } xCrop = DATA_HOLDER.vrSettings.mirrorCrop; @@ -363,9 +363,9 @@ public static void doMixedRealityMirror() { source = DATA_HOLDER.vrRenderer.framebufferUndistorted; } else { if (DATA_HOLDER.vrSettings.displayMirrorLeftEye) { - source = DATA_HOLDER.vrRenderer.framebufferEye0; + source = DATA_HOLDER.vrRenderer.getLeftEyeTarget(); } else { - source = DATA_HOLDER.vrRenderer.framebufferEye1; + source = DATA_HOLDER.vrRenderer.getRightEyeTarget(); } } VRShaders.MIXED_REALITY_SHADER.setSampler("firstPersonColor", source.getColorTextureId()); diff --git a/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java b/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java index 8f3e26190..c95a477eb 100644 --- a/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java +++ b/common/src/main/java/org/vivecraft/client_vr/settings/VRSettings.java @@ -142,6 +142,7 @@ public enum ShaderGUIRender implements OptionEnum { public enum VRProvider implements OptionEnum { OPENVR, + OPENXR, NULLVR } @@ -1724,7 +1725,7 @@ void onOptionChange() { @Override String getDisplayString(String prefix, Object value) { if (VRState.VR_ENABLED) { - RenderTarget eye0 = ClientDataHolderVR.getInstance().vrRenderer.framebufferEye0; + RenderTarget eye0 = ClientDataHolderVR.getInstance().vrRenderer.getLeftEyeTarget(); return prefix + Math.round((float) value * 100) + "% (" + (int) Math.ceil(eye0.viewWidth * Math.sqrt((float) value)) + "x" + (int) Math.ceil(eye0.viewHeight * Math.sqrt((float) value)) + ")"; From 7264eed0898a4e78e09d80f7287859ab5bcf02ae Mon Sep 17 00:00:00 2001 From: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:22:19 +0100 Subject: [PATCH 09/27] update + cleanup currently, it seems some HMD position is wrong --- .../vivecraft/client_vr/provider/MCVR.java | 13 +- .../control/TrackpadSwipeSampler.java | 1 - .../provider/control/VRInputAction.java | 2 - .../provider/openvr_lwjgl/MCOpenVR.java | 103 ----- .../client_vr/provider/openxr/MCOpenXR.java | 370 +++++------------- .../client_vr/provider/openxr/OpenXRUtil.java | 41 +- .../mixin/client_vr/KeyboardInputVRMixin.java | 3 +- 7 files changed, 103 insertions(+), 430 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java index a2468e245..1cce767f8 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java @@ -44,9 +44,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.lwjgl.openvr.VR.k_ulInvalidInputValueHandle; - public abstract class MCVR { + public static final int LEFT_CONTROLLER = 1; + public static final int RIGHT_CONTROLLER = 0; + public static final int CAMERA_TRACKER = 2; protected Minecraft mc; protected ClientDataHolderVR dh; protected static MCVR ME; @@ -1240,8 +1241,8 @@ private void processInputAction(VRInputAction action) { private void processScrollInput(KeyMapping keyMapping, Runnable upCallback, Runnable downCallback) { VRInputAction action = this.getInputAction(keyMapping); - if (action.isEnabled() && action.getLastOrigin() != k_ulInvalidInputValueHandle) { - float value = action.getAxis2D(false).getY(); + if (action.isEnabled() && action.getLastOrigin() != 0L) { /** {@link org.lwjgl.openvr.VR.k_ulInvalidInputValueHandle} and {@link org.lwjgl.system.MemoryUtil.NULL} are both 0 */ + float value = action.getAxis2D(false).y(); if (value != 0.0F) { if (value > 0.0F) { upCallback.run(); @@ -1263,7 +1264,7 @@ private void processScrollInput(KeyMapping keyMapping, Runnable upCallback, Runn private void processSwipeInput(KeyMapping keyMapping, Runnable leftCallback, Runnable rightCallback, Runnable upCallback, Runnable downCallback) { VRInputAction action = this.getInputAction(keyMapping); - if (action.isEnabled() && action.getLastOrigin() != k_ulInvalidInputValueHandle) { + if (action.isEnabled() && action.getLastOrigin() != 0L) { /** {@link org.lwjgl.openvr.VR.k_ulInvalidInputValueHandle} and {@link org.lwjgl.system.MemoryUtil.NULL} are both 0 */ ControllerType controller = this.findActiveBindingControllerType(keyMapping); if (controller != null) { @@ -1294,8 +1295,6 @@ private void processSwipeInput(KeyMapping keyMapping, Runnable leftCallback, Run this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); rightCallback.run(); } - - } } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/control/TrackpadSwipeSampler.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/TrackpadSwipeSampler.java index cc2954362..5dfaa3b8f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/control/TrackpadSwipeSampler.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/TrackpadSwipeSampler.java @@ -6,7 +6,6 @@ import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.client_vr.provider.openvr_lwjgl.MCOpenVR; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; public class TrackpadSwipeSampler { private static final int UP = 0; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java index c1e8eace9..b664d57db 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java @@ -12,8 +12,6 @@ import org.vivecraft.client_vr.provider.ControllerType; import org.vivecraft.client_vr.provider.HandedKeyBinding; import org.vivecraft.client_vr.provider.InputSimulator; -import org.vivecraft.client_vr.provider.MCVR; -import org.vivecraft.client_vr.provider.openvr_lwjgl.control.VRInputActionSet; import javax.annotation.Nullable; import java.util.ArrayList; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index 0329233d4..be3d7689c 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -63,10 +63,6 @@ * MCVR implementation to communicate with OpenVR/SteamVR */ public class MCOpenVR extends MCVR { - public static final int LEFT_CONTROLLER = 1; - public static final int RIGHT_CONTROLLER = 0; - public static final int CAMERA_TRACKER = 2; - protected static MCOpenVR OME; // action paths @@ -1076,105 +1072,6 @@ private void loadActionManifest() throws RenderConfigException { } } - /** - * updates the KeyMapping state that is linked to the given VRInputAction - * @param action VRInputAction to process - */ - private void processInputAction(VRInputAction action) { - if (action.isActive() && action.isEnabledRaw() && - // try to prevent double left clicks - (!ClientDataHolderVR.getInstance().vrSettings.ingameBindingsInGui || - !(action.actionSet == VRInputActionSet.INGAME && - action.keyBinding.key.getType() == InputConstants.Type.MOUSE && - action.keyBinding.key.getValue() == GLFW.GLFW_MOUSE_BUTTON_LEFT && this.mc.screen != null - ) - )) - { - if (action.isButtonChanged()) { - if (action.isButtonPressed() && action.isEnabled()) { - // We do this, so shit like closing a GUI by clicking a button won't - // also click in the world immediately after. - if (!this.ignorePressesNextFrame) { - action.pressBinding(); - } - } else { - action.unpressBinding(); - } - } - } else { - action.unpressBinding(); - } - } - - /** - * checks the axis input of the VRInputAction linked to {@code keyMapping} and runs the callbacks when it's non 0 - * @param keyMapping KeyMapping to check - * @param upCallback action to do when the axis input is positive - * @param downCallback action to do when the axis input is negative - */ - private void processScrollInput(KeyMapping keyMapping, Runnable upCallback, Runnable downCallback) { - VRInputAction action = this.getInputAction(keyMapping); - - if (action.isEnabled() && action.getLastOrigin() != k_ulInvalidInputValueHandle) { - float value = action.getAxis2D(false).y(); - if (value != 0.0F) { - if (value > 0.0F) { - upCallback.run(); - } else if (value < 0.0F) { - downCallback.run(); - } - } - } - } - - /** - * checks the trackpad input of the controller the {@code keyMapping} is on - * @param keyMapping KeyMapping to check - * @param leftCallback action to do when swiped to the left - * @param rightCallback action to do when swiped to the right - * @param upCallback action to do when swiped to the up - * @param downCallback action to do when swiped to the down - */ - private void processSwipeInput(KeyMapping keyMapping, Runnable leftCallback, Runnable rightCallback, Runnable upCallback, Runnable downCallback) { - VRInputAction action = this.getInputAction(keyMapping); - - if (action.isEnabled() && action.getLastOrigin() != k_ulInvalidInputValueHandle) { - ControllerType controller = this.findActiveBindingControllerType(keyMapping); - - if (controller != null) { - // if that keyMapping is not tracked yet, create a new sampler - if (!this.trackpadSwipeSamplers.containsKey(keyMapping.getName())) { - this.trackpadSwipeSamplers.put(keyMapping.getName(), new TrackpadSwipeSampler()); - } - - TrackpadSwipeSampler trackpadswipesampler = this.trackpadSwipeSamplers.get(keyMapping.getName()); - trackpadswipesampler.update(controller, action.getAxis2D(false)); - - if (trackpadswipesampler.isSwipedUp() && upCallback != null) { - this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); - upCallback.run(); - } - - if (trackpadswipesampler.isSwipedDown() && downCallback != null) { - this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); - downCallback.run(); - } - - if (trackpadswipesampler.isSwipedLeft() && leftCallback != null) { - this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); - leftCallback.run(); - } - - if (trackpadswipesampler.isSwipedRight() && rightCallback != null) { - this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); - rightCallback.run(); - } - - - } - } - } - /** * fetches all available VREvents from OpenVR */ diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index ee1e01e2b..4d2850832 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -2,12 +2,11 @@ import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; -import net.minecraft.util.Mth; -import net.minecraft.world.phys.Vec3; import org.apache.commons.lang3.tuple.Pair; +import org.joml.Matrix4f; import org.joml.Vector2f; +import org.joml.Vector3f; import org.lwjgl.PointerBuffer; -import org.lwjgl.glfw.*; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL21; import org.lwjgl.opengl.GL30; @@ -15,22 +14,16 @@ import org.lwjgl.openxr.*; import org.lwjgl.system.MemoryStack; import org.vivecraft.client.VivecraftVRMod; -import org.vivecraft.client.utils.MathUtils; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.RadialHandler; import org.vivecraft.client_vr.provider.ControllerType; -import org.vivecraft.client_vr.provider.InputSimulator; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.provider.VRRenderer; import org.vivecraft.client_vr.provider.control.VRInputAction; import org.vivecraft.client_vr.provider.control.VRInputActionSet; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.settings.VRSettings; -import org.vivecraft.client_xr.render_pass.RenderPassManager; -import org.vivecraft.common.utils.lwjgl.Vector3f; -import org.vivecraft.common.utils.math.Matrix4f; -import org.vivecraft.common.utils.math.Vector3; import javax.annotation.Nullable; import java.nio.ByteBuffer; @@ -79,7 +72,6 @@ public MCOpenXR(Minecraft mc, ClientDataHolderVR dh) { super(mc, dh, VivecraftVRMod.INSTANCE); OME = this; this.hapticScheduler = new OpenXRHapticSchedular(); - } @Override @@ -121,15 +113,6 @@ public void destroy() { eventDataBuffer.close(); } - @Override - protected void triggerBindingHapticPulse(KeyMapping binding, int duration) { - ControllerType controllertype = this.findActiveBindingControllerType(binding); - - if (controllertype != null) { - this.triggerHapticPulse(controllertype, duration); - } - } - @Override protected ControllerType findActiveBindingControllerType(KeyMapping binding) { if (!this.inputInitialized) { @@ -165,7 +148,7 @@ protected ControllerType findActiveBindingControllerType(KeyMapping binding) { public void poll(long var1) { if (this.initialized) { this.mc.getProfiler().push("events"); - //pollVREvents(); + this.pollVREvents(); if (!this.dh.vrSettings.seated) { this.mc.getProfiler().popPush("controllers"); @@ -191,11 +174,10 @@ public void poll(long var1) { } private void updatePose() { - RenderPassManager.setGUIRenderPass(); - if (mc == null) { return; } + try (MemoryStack stack = MemoryStack.stackPush()) { XrFrameState frameState = XrFrameState.calloc(stack).type(XR10.XR_TYPE_FRAME_STATE); @@ -236,154 +218,17 @@ private void updatePose() { if (error >= 0) { OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.hmdPose); OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.hmdRotation); - - Vec3 vec3 = new Vec3(space_location.pose().position$().x(), space_location.pose().position$().y(), space_location.pose().position$().z()); - this.hmdHistory.add(vec3); - Vector3 vector3 = this.hmdRotation.transform(new Vector3(0.0F, -0.1F, 0.1F)); - this.hmdPivotHistory.add(new Vec3((double) vector3.getX() + vec3.x, (double) vector3.getY() + vec3.y, (double) vector3.getZ() + vec3.z)); headIsTracking = true; } else { headIsTracking = false; + this.hmdPose.identity(); + this.hmdPose.m31(1.6F); } //Eye positions OpenXRUtil.openXRPoseToMarix(viewBuffer.get(0).pose(), this.hmdPoseLeftEye); OpenXRUtil.openXRPoseToMarix(viewBuffer.get(1).pose(), this.hmdPoseRightEye); - //reverse - if (this.dh.vrSettings.reverseHands) { - XrSpace temp = gripSpace[0]; - gripSpace[0] = gripSpace[1]; - gripSpace[1] = temp; - temp = aimSpace[0]; - aimSpace[0] = aimSpace[1]; - aimSpace[1] = temp; - } - - //Controller aim and grip poses - error = XR10.xrLocateSpace(gripSpace[0], xrAppSpace, time, space_location); - logError(error, "xrLocateSpace", "gripSpace[0]"); - if (error >= 0) { - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.handRotation[0]); - } - - error = XR10.xrLocateSpace(gripSpace[1], xrAppSpace, time, space_location); - logError(error, "xrLocateSpace", "gripSpace[1]"); - if (error >= 0) { - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.handRotation[1]); - } - - error = XR10.xrLocateSpace(aimSpace[0], xrAppSpace, time, space_location); - logError(error, "xrLocateSpace", "aimSpace[0]"); - if (error >= 0) { - OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.controllerPose[0]); - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.controllerRotation[0]); - this.aimSource[0] = new Vec3(space_location.pose().position$().x(), space_location.pose().position$().y(), space_location.pose().position$().z()); - this.controllerHistory[0].add(this.getAimSource(0)); - this.controllerForwardHistory[0].add(this.getAimSource(0)); - Vec3 vec33 = this.controllerRotation[0].transform(UP).toVector3d(); - this.controllerUpHistory[0].add(vec33); - this.controllerTracking[0] = true; - } else { - this.controllerTracking[0] = false; - } - - error = XR10.xrLocateSpace(aimSpace[1], xrAppSpace, time, space_location); - logError(error, "xrLocateSpace", "aimSpace[1]"); - if (error >= 0) { - OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.controllerPose[1]); - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.controllerRotation[1]); - this.aimSource[1] = new Vec3(space_location.pose().position$().x(), space_location.pose().position$().y(), space_location.pose().position$().z()); - this.controllerHistory[1].add(this.getAimSource(1)); - this.controllerForwardHistory[1].add(this.getAimSource(1)); - Vec3 vec32 = this.controllerRotation[1].transform(UP).toVector3d(); - this.controllerUpHistory[1].add(vec32); - this.controllerTracking[1] = true; - } else { - this.controllerTracking[1] = false; - } - - //TODO merge with updateAim so it's one method - if (this.dh.vrSettings.seated) { - this.controllerPose[0] = this.hmdPose.inverted().inverted(); - this.controllerPose[1] = this.hmdPose.inverted().inverted(); - this.handRotation[0] = hmdRotation; - this.handRotation[1] = hmdRotation; - this.controllerRotation[0] = hmdRotation; - this.controllerRotation[1] = hmdRotation; - this.aimSource[1] = this.getEyePosition(RenderPass.CENTER); - this.aimSource[0] = this.getEyePosition(RenderPass.CENTER); - - if (this.mc.screen == null) { - Vec3 vec31 = this.getAimVector(1); - org.vivecraft.common.utils.lwjgl.Matrix4f matrix4f = new org.vivecraft.common.utils.lwjgl.Matrix4f(); - float f = 110.0F; - float f1 = 180.0F; - double d0 = this.mc.mouseHandler.xpos() / (double) this.mc.getWindow().getScreenWidth() * (double) f - (double) (f / 2.0F); - int i = this.mc.getWindow().getScreenHeight(); - - if (i % 2 != 0) { - --i; - } - - double d1 = -this.mc.mouseHandler.ypos() / (double) i * (double) f1 + (double) (f1 / 2.0F); - double d2 = -d1; - - if (this.mc.isWindowActive()) { - float f2 = this.dh.vrSettings.keyholeX; - float f3 = 20.0F * this.dh.vrSettings.xSensitivity; - int j = (int) ((double) (-f2 + f / 2.0F) * (double) this.mc.getWindow().getScreenWidth() / (double) f) + 1; - int k = (int) ((double) (f2 + f / 2.0F) * (double) this.mc.getWindow().getScreenWidth() / (double) f) - 1; - float f4 = ((float) Math.abs(d0) - f2) / (f / 2.0F - f2); - double d3 = this.mc.mouseHandler.xpos(); - - if (d0 < (double) (-f2)) { - this.seatedRot += f3 * f4; - this.seatedRot %= 360.0F; - this.hmdForwardYaw = (float) Math.toDegrees(Math.atan2(vec31.x, vec31.z)); - d3 = j; - d0 = -f2; - } else if (d0 > (double) f2) { - this.seatedRot -= f3 * f4; - this.seatedRot %= 360.0F; - this.hmdForwardYaw = (float) Math.toDegrees(Math.atan2(vec31.x, vec31.z)); - d3 = k; - d0 = f2; - } - - double d4 = 0.5D * (double) this.dh.vrSettings.ySensitivity; - d2 = (double) this.aimPitch + d1 * d4; - d2 = Mth.clamp(d2, -89.9D, 89.9D); - InputSimulator.setMousePos(d3, i / 2); - GLFW.glfwSetCursorPos(this.mc.getWindow().getWindow(), d3, i / 2); - matrix4f.rotate((float) Math.toRadians(-d2), new Vector3f(1.0F, 0.0F, 0.0F)); - matrix4f.rotate((float) Math.toRadians(-180.0D + d0 - (double) this.hmdForwardYaw), new Vector3f(0.0F, 1.0F, 0.0F)); - } - - this.controllerRotation[0].M[0][0] = matrix4f.m00; - this.controllerRotation[0].M[0][1] = matrix4f.m01; - this.controllerRotation[0].M[0][2] = matrix4f.m02; - this.controllerRotation[0].M[1][0] = matrix4f.m10; - this.controllerRotation[0].M[1][1] = matrix4f.m11; - this.controllerRotation[0].M[1][2] = matrix4f.m12; - this.controllerRotation[0].M[2][0] = matrix4f.m20; - this.controllerRotation[0].M[2][1] = matrix4f.m21; - this.controllerRotation[0].M[2][2] = matrix4f.m22; - - this.handRotation[0].M[0][0] = matrix4f.m00; - this.handRotation[0].M[0][1] = matrix4f.m01; - this.handRotation[0].M[0][2] = matrix4f.m02; - this.handRotation[0].M[1][0] = matrix4f.m10; - this.handRotation[0].M[1][1] = matrix4f.m11; - this.handRotation[0].M[1][2] = matrix4f.m12; - this.handRotation[0].M[2][0] = matrix4f.m20; - this.handRotation[0].M[2][1] = matrix4f.m21; - this.handRotation[0].M[2][2] = matrix4f.m22; - } - } - Vec3 vec32 = this.getAimVector(0); - this.aimPitch = (float) Math.toDegrees(Math.asin(vec32.y / vec32.length())); - if (this.inputInitialized) { this.mc.getProfiler().push("updateActionState"); @@ -399,91 +244,64 @@ private void updatePose() { //TODO Not needed it seems? Poses come from the action space XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.readPoseData(this.grip[0], actionSet); - this.readPoseData(this.grip[1], actionSet); - this.readPoseData(this.aim[0], actionSet); - this.readPoseData(this.aim[1], actionSet); + this.readPoseData(this.grip[RIGHT_CONTROLLER], actionSet); + this.readPoseData(this.grip[LEFT_CONTROLLER], actionSet); + this.readPoseData(this.aim[RIGHT_CONTROLLER], actionSet); + this.readPoseData(this.aim[LEFT_CONTROLLER], actionSet); this.mc.getProfiler().pop(); - } - } - } - @Override - public Vec3 getEyePosition(RenderPass eye) { - org.vivecraft.common.utils.math.Matrix4f matrix4f = null; - - if (eye == RenderPass.LEFT) { - matrix4f = this.hmdPoseLeftEye; - } else if (eye == RenderPass.RIGHT) { - matrix4f = this.hmdPoseRightEye; - } + //reverse + if (this.dh.vrSettings.reverseHands) { + XrSpace temp = gripSpace[RIGHT_CONTROLLER]; + gripSpace[RIGHT_CONTROLLER] = gripSpace[LEFT_CONTROLLER]; + gripSpace[LEFT_CONTROLLER] = temp; + temp = aimSpace[RIGHT_CONTROLLER]; + aimSpace[RIGHT_CONTROLLER] = aimSpace[LEFT_CONTROLLER]; + aimSpace[LEFT_CONTROLLER] = temp; + } - if (matrix4f == null) { - org.vivecraft.common.utils.math.Matrix4f matrix4f2 = this.hmdPose; - Vector3 vector31 = MathUtils.convertMatrix4ftoTranslationVector(matrix4f2); + //Controller aim and grip poses + error = XR10.xrLocateSpace(gripSpace[RIGHT_CONTROLLER], xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "gripSpace[0]"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.handRotation[RIGHT_CONTROLLER]); + } - if (this.dh.vrSettings.seated || this.dh.vrSettings.allowStandingOriginOffset) { - if (this.dh.vr.isHMDTracking()) { - vector31 = vector31.add(this.dh.vrSettings.originOffset); + error = XR10.xrLocateSpace(gripSpace[LEFT_CONTROLLER], xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "gripSpace[1]"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.handRotation[LEFT_CONTROLLER]); } - } - return vector31.toVector3d(); - } else { - Vector3 vector3 = MathUtils.convertMatrix4ftoTranslationVector(matrix4f); + error = XR10.xrLocateSpace(aimSpace[RIGHT_CONTROLLER], xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "aimSpace[0]"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.controllerPose[RIGHT_CONTROLLER]); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.controllerRotation[RIGHT_CONTROLLER]); + this.controllerTracking[RIGHT_CONTROLLER] = true; + } else { + this.controllerTracking[RIGHT_CONTROLLER] = false; + } - if (this.dh.vrSettings.seated || this.dh.vrSettings.allowStandingOriginOffset) { - if (this.dh.vr.isHMDTracking()) { - vector3 = vector3.add(this.dh.vrSettings.originOffset); + error = XR10.xrLocateSpace(aimSpace[LEFT_CONTROLLER], xrAppSpace, time, space_location); + logError(error, "xrLocateSpace", "aimSpace[1]"); + if (error >= 0) { + OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.controllerPose[LEFT_CONTROLLER]); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.controllerRotation[LEFT_CONTROLLER]); + this.controllerTracking[LEFT_CONTROLLER] = true; + } else { + this.controllerTracking[LEFT_CONTROLLER] = false; } } - return vector3.toVector3d(); - } - } - - @Override - public org.vivecraft.common.utils.math.Matrix4f getEyeRotation(RenderPass eye) { - org.vivecraft.common.utils.math.Matrix4f matrix4f; - - if (eye == RenderPass.LEFT) { - matrix4f = this.hmdPoseLeftEye; - } else if (eye == RenderPass.RIGHT) { - matrix4f = this.hmdPoseRightEye; - } else { - matrix4f = null; - } - - if (matrix4f != null) { - org.vivecraft.common.utils.math.Matrix4f matrix4f1 = new org.vivecraft.common.utils.math.Matrix4f(); - matrix4f1.M[0][0] = matrix4f.M[0][0]; - matrix4f1.M[0][1] = matrix4f.M[0][1]; - matrix4f1.M[0][2] = matrix4f.M[0][2]; - matrix4f1.M[0][3] = 0.0F; - matrix4f1.M[1][0] = matrix4f.M[1][0]; - matrix4f1.M[1][1] = matrix4f.M[1][1]; - matrix4f1.M[1][2] = matrix4f.M[1][2]; - matrix4f1.M[1][3] = 0.0F; - matrix4f1.M[2][0] = matrix4f.M[2][0]; - matrix4f1.M[2][1] = matrix4f.M[2][1]; - matrix4f1.M[2][2] = matrix4f.M[2][2]; - matrix4f1.M[2][3] = 0.0F; - matrix4f1.M[3][0] = 0.0F; - matrix4f1.M[3][1] = 0.0F; - matrix4f1.M[3][2] = 0.0F; - matrix4f1.M[3][3] = 1.0F; - return matrix4f1; - } else { - return this.hmdRotation; + this.updateAim(); } } public void readNewData(VRInputAction action) { - String s = action.type; - - switch (s) { - case "boolean": + switch (action.type) { + case "boolean" -> { if (action.isHanded()) { for (ControllerType controllertype1 : ControllerType.values()) { this.readBoolean(action, controllertype1); @@ -491,10 +309,9 @@ public void readNewData(VRInputAction action) { } else { this.readBoolean(action, null); } + } - break; - - case "vector1": + case "vector1" -> { if (action.isHanded()) { for (ControllerType controllertype : ControllerType.values()) { this.readFloat(action, controllertype); @@ -502,9 +319,9 @@ public void readNewData(VRInputAction action) { } else { this.readFloat(action, null); } - break; + } - case "vector2": + case "vector2" -> { if (action.isHanded()) { for (ControllerType controllertype : ControllerType.values()) { this.readVecData(action, controllertype); @@ -512,9 +329,7 @@ public void readNewData(VRInputAction action) { } else { this.readVecData(action, null); } - break; - - case "vector3": + } } } @@ -636,10 +451,6 @@ private boolean updateActiveActionSets() { return !arraylist.isEmpty(); } - private void updateControllerPose(int controller, long actionHandle) { - - } - long getActionSetHandle(VRInputActionSet actionSet) { return this.actionSetHandles.get(actionSet); } @@ -745,11 +556,11 @@ public boolean init() { //TODO Seated when no controllers System.out.println("OpenXR initialized & VR connected."); - this.deviceVelocity = new Vec3[64]; + this.deviceVelocity = new Vector3f[64]; for (int i = 0; i < this.poseMatrices.length; ++i) { this.poseMatrices[i] = new Matrix4f(); - this.deviceVelocity[i] = new Vec3(0.0D, 0.0D, 0.0D); + this.deviceVelocity[i] = new Vector3f(); } this.initialized = true; @@ -888,6 +699,7 @@ private void initializeOpenXRSession() { session = new XrSession(sessionPtr.get(0), instance); while (!this.isActive) { + System.out.println("waiting"); pollVREvents(); } @@ -1119,7 +931,7 @@ public boolean isActive() { @Override public ControllerType getOriginControllerType(long i) { - if (i == aim[0]) { + if (i == aim[RIGHT_CONTROLLER]) { return ControllerType.RIGHT; } return ControllerType.LEFT; @@ -1127,7 +939,7 @@ public ControllerType getOriginControllerType(long i) { @Override public float getIPD() { - return (float) (this.getEyePosition(RenderPass.RIGHT).x - this.getEyePosition(RenderPass.LEFT).x); + return this.getEyePosition(RenderPass.RIGHT).x - this.getEyePosition(RenderPass.LEFT).x; } @Override @@ -1152,17 +964,17 @@ private void loadActionHandles() { setupControllers(); XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.haptics[0] = createAction("/actions/global/out/righthaptic", "/actions/global/out/righthaptic", "haptic", actionSet, BOTH_HANDS); - this.haptics[1] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", "haptic", actionSet, BOTH_HANDS); + this.haptics[RIGHT_CONTROLLER] = createAction("/actions/global/out/righthaptic", "/actions/global/out/righthaptic", "haptic", actionSet, BOTH_HANDS); + this.haptics[LEFT_CONTROLLER] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", "haptic", actionSet, BOTH_HANDS); } private void setupControllers() { XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.grip[0] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", "pose", actionSet, BOTH_HANDS); - this.grip[1] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", actionSet, BOTH_HANDS); - this.aim[0] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", "pose", actionSet, BOTH_HANDS); - this.aim[1] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", "pose", actionSet, BOTH_HANDS); + this.grip[RIGHT_CONTROLLER] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", "pose", actionSet, BOTH_HANDS); + this.grip[LEFT_CONTROLLER] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", actionSet, BOTH_HANDS); + this.aim[RIGHT_CONTROLLER] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", "pose", actionSet, BOTH_HANDS); + this.aim[LEFT_CONTROLLER] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", "pose", actionSet, BOTH_HANDS); } private void loadDefaultBindings() { @@ -1189,29 +1001,29 @@ private void loadDefaultBindings() { //TODO make this also changeable? XrActionSet actionSet = new XrActionSet(actionSetHandles.get(VRInputActionSet.GLOBAL), instance); bindings.get(defaultBindings.length).set( - new XrAction(this.grip[0], actionSet), + new XrAction(this.grip[RIGHT_CONTROLLER], actionSet), getPath("/user/hand/right/input/grip/pose") ); bindings.get(defaultBindings.length + 1).set( - new XrAction(this.grip[1], actionSet), + new XrAction(this.grip[LEFT_CONTROLLER], actionSet), getPath("/user/hand/left/input/grip/pose") ); bindings.get(defaultBindings.length + 2).set( - new XrAction(this.aim[0], actionSet), + new XrAction(this.aim[RIGHT_CONTROLLER], actionSet), getPath("/user/hand/right/input/aim/pose") ); bindings.get(defaultBindings.length + 3).set( - new XrAction(this.aim[1], actionSet), + new XrAction(this.aim[LEFT_CONTROLLER], actionSet), getPath("/user/hand/left/input/aim/pose") ); bindings.get(defaultBindings.length + 4).set( - new XrAction(this.haptics[0], actionSet), + new XrAction(this.haptics[RIGHT_CONTROLLER], actionSet), getPath("/user/hand/right/output/haptic") ); bindings.get(defaultBindings.length + 5).set( - new XrAction(this.haptics[1], actionSet), + new XrAction(this.haptics[LEFT_CONTROLLER], actionSet), getPath("/user/hand/left/output/haptic") ); @@ -1235,34 +1047,34 @@ private void loadDefaultBindings() { logError(error, "xrAttachSessionActionSets", ""); XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - XrActionSpaceCreateInfo grip_left = XrActionSpaceCreateInfo.calloc(stack); - grip_left.type(XR10.XR_TYPE_ACTION_SPACE_CREATE_INFO); - grip_left.next(NULL); - grip_left.action(new XrAction(grip[0], actionSet)); - grip_left.subactionPath(getPath("/user/hand/right")); - grip_left.poseInActionSpace(POSE_IDENTITY); + XrActionSpaceCreateInfo actionSpace = XrActionSpaceCreateInfo.calloc(stack); + actionSpace.type(XR10.XR_TYPE_ACTION_SPACE_CREATE_INFO); + actionSpace.next(NULL); + actionSpace.action(new XrAction(grip[RIGHT_CONTROLLER], actionSet)); + actionSpace.subactionPath(getPath("/user/hand/right")); + actionSpace.poseInActionSpace(POSE_IDENTITY); PointerBuffer pp = stackCallocPointer(1); - error = XR10.xrCreateActionSpace(session, grip_left, pp); + error = XR10.xrCreateActionSpace(session, actionSpace, pp); logError(error, "xrCreateActionSpace", "grip: /user/hand/right"); - this.gripSpace[0] = new XrSpace(pp.get(0), session); + this.gripSpace[RIGHT_CONTROLLER] = new XrSpace(pp.get(0), session); - grip_left.action(new XrAction(grip[1], actionSet)); - grip_left.subactionPath(getPath("/user/hand/left")); - error = XR10.xrCreateActionSpace(session, grip_left, pp); + actionSpace.action(new XrAction(grip[LEFT_CONTROLLER], actionSet)); + actionSpace.subactionPath(getPath("/user/hand/left")); + error = XR10.xrCreateActionSpace(session, actionSpace, pp); logError(error, "xrCreateActionSpace", "grip: /user/hand/left"); - this.gripSpace[1] = new XrSpace(pp.get(0), session); + this.gripSpace[LEFT_CONTROLLER] = new XrSpace(pp.get(0), session); - grip_left.action(new XrAction(aim[0], actionSet)); - grip_left.subactionPath(getPath("/user/hand/right")); - error = XR10.xrCreateActionSpace(session, grip_left, pp); + actionSpace.action(new XrAction(aim[RIGHT_CONTROLLER], actionSet)); + actionSpace.subactionPath(getPath("/user/hand/right")); + error = XR10.xrCreateActionSpace(session, actionSpace, pp); logError(error, "xrCreateActionSpace", "aim: /user/hand/right"); - this.aimSpace[0] = new XrSpace(pp.get(0), session); + this.aimSpace[RIGHT_CONTROLLER] = new XrSpace(pp.get(0), session); - grip_left.action(new XrAction(aim[1], actionSet)); - grip_left.subactionPath(getPath("/user/hand/left")); - error = XR10.xrCreateActionSpace(session, grip_left, pp); + actionSpace.action(new XrAction(aim[LEFT_CONTROLLER], actionSet)); + actionSpace.subactionPath(getPath("/user/hand/left")); + error = XR10.xrCreateActionSpace(session, actionSpace, pp); logError(error, "xrCreateActionSpace", "aim: /user/hand/left"); - this.aimSpace[1] = new XrSpace(pp.get(0), session); + this.aimSpace[LEFT_CONTROLLER] = new XrSpace(pp.get(0), session); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java index 7ce805b55..ebc94576f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java @@ -1,50 +1,19 @@ package org.vivecraft.client_vr.provider.openxr; -import org.joml.Matrix3f; +import org.joml.Matrix4f; import org.joml.Quaternionf; import org.lwjgl.openxr.XrPosef; import org.lwjgl.openxr.XrQuaternionf; -import org.vivecraft.common.utils.math.Matrix4f; public class OpenXRUtil { public static void openXRPoseToMarix(XrPosef pose, Matrix4f mat) { - Matrix3f matrix3f = new Matrix3f().set(new Quaternionf(pose.orientation().x(), pose.orientation().y(), pose.orientation().z(), pose.orientation().w())); - mat.M[0][0] = matrix3f.m00; - mat.M[0][1] = matrix3f.m10; - mat.M[0][2] = matrix3f.m20; - mat.M[0][3] = pose.position$().x(); - mat.M[1][0] = matrix3f.m01; - mat.M[1][1] = matrix3f.m11; - mat.M[1][2] = matrix3f.m21; - mat.M[1][3] = pose.position$().y(); - mat.M[2][0] = matrix3f.m02; - mat.M[2][1] = matrix3f.m12; - mat.M[2][2] = matrix3f.m22; - mat.M[2][3] = pose.position$().z(); - mat.M[3][0] = 0; - mat.M[3][1] = 0; - mat.M[3][2] = 0; - mat.M[3][3] = 1; + mat.set(new Quaternionf(pose.orientation().x(), pose.orientation().y(), pose.orientation().z(), pose.orientation().w())) + .setTranslation(pose.position$().x(), pose.position$().y(), pose.position$().z()) + .m33(1); } public static void openXRPoseToMarix(XrQuaternionf quat, Matrix4f mat) { - Matrix3f matrix3f = new Matrix3f().set(new Quaternionf(quat.x(), quat.y(), quat.z(), quat.w())); - mat.M[0][0] = matrix3f.m00; - mat.M[0][1] = matrix3f.m10; - mat.M[0][2] = matrix3f.m20; - mat.M[0][3] = 0; - mat.M[1][0] = matrix3f.m01; - mat.M[1][1] = matrix3f.m11; - mat.M[1][2] = matrix3f.m21; - mat.M[1][3] = 0; - mat.M[2][0] = matrix3f.m02; - mat.M[2][1] = matrix3f.m12; - mat.M[2][2] = matrix3f.m22; - mat.M[2][3] = 0; - mat.M[3][0] = 0; - mat.M[3][1] = 0; - mat.M[3][2] = 0; - mat.M[3][3] = 1; + mat.set(new Quaternionf(quat.x(), quat.y(), quat.z(), quat.w())); } } diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java index 7e6026179..0cd53437e 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java @@ -16,12 +16,11 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.vivecraft.client.VivecraftVRMod; +import org.vivecraft.client_vr.provider.control.VRInputAction; import org.vivecraft.common.utils.MathUtils; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; -import org.vivecraft.client_vr.provider.MCVR; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; @Mixin(KeyboardInput.class) public class KeyboardInputVRMixin extends Input { From faa52633d14598d87e2714b95a92b7beed0b8a18 Mon Sep 17 00:00:00 2001 From: ferriarnus <61201275+ferriarnus@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:56:54 +0100 Subject: [PATCH 10/27] fix eye position --- .../client_vr/provider/openxr/MCOpenXR.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 4d2850832..9a11157f0 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -299,6 +299,30 @@ private void updatePose() { } } + /** + * @param eye LEFT, RIGHT or CENTER eye + * @return position of the given eye, in room space + */ + @Override + public Vector3f getEyePosition(RenderPass eye) { + Matrix4f pose = new Matrix4f(this.hmdPose); + switch (eye) { + case LEFT -> pose = this.hmdPoseLeftEye; //OpenXR includes total + case RIGHT -> pose = this.hmdPoseRightEye; + default -> {} + }; + + Vector3f pos = pose.getTranslation(new Vector3f()); + + if (this.dh.vrSettings.seated || this.dh.vrSettings.allowStandingOriginOffset) { + if (this.dh.vr.isHMDTracking()) { + pos = pos.add(this.dh.vrSettings.originOffset); + } + } + + return pos; + } + public void readNewData(VRInputAction action) { switch (action.type) { case "boolean" -> { From d7651229abe191dd40227b509e59adccdb3c76fc Mon Sep 17 00:00:00 2001 From: fayer3 Date: Tue, 10 Dec 2024 19:30:28 +0100 Subject: [PATCH 11/27] fix openxr head rotation --- .../java/org/vivecraft/client_vr/VRData.java | 2 +- .../gameplay/screenhandlers/GuiHandler.java | 2 +- .../vivecraft/client_vr/provider/MCVR.java | 39 +++++++++---------- .../provider/openvr_lwjgl/MCOpenVR.java | 4 ++ .../client_vr/provider/openxr/MCOpenXR.java | 25 ------------ 5 files changed, 24 insertions(+), 48 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/VRData.java b/common/src/main/java/org/vivecraft/client_vr/VRData.java index f90b37a08..bae767182 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRData.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRData.java @@ -58,7 +58,7 @@ public VRData(Vec3 origin, float walkMul, float worldScale, float rotation) { Vector3f scaleOffset = new Vector3f(scaledPos.x - hmd_raw.x, 0.0F, scaledPos.z - hmd_raw.z); // headset - this.hmd = new VRDevicePose(this, mcVR.hmdRotation, scaledPos, mcVR.getHmdVector()); + this.hmd = new VRDevicePose(this, mcVR.getEyeRotation(RenderPass.CENTER), scaledPos, mcVR.getHmdVector()); this.eye0 = new VRDevicePose(this, mcVR.getEyeRotation(RenderPass.LEFT), diff --git a/common/src/main/java/org/vivecraft/client_vr/gameplay/screenhandlers/GuiHandler.java b/common/src/main/java/org/vivecraft/client_vr/gameplay/screenhandlers/GuiHandler.java index 040d288d6..4cecb936a 100644 --- a/common/src/main/java/org/vivecraft/client_vr/gameplay/screenhandlers/GuiHandler.java +++ b/common/src/main/java/org/vivecraft/client_vr/gameplay/screenhandlers/GuiHandler.java @@ -510,7 +510,7 @@ public static Vec3 applyGUIModelView(RenderPass currentPass, PoseStack poseStack direction = DH.vrPlayer.vrdata_world_render.getController(0).getDirection(); guirot = guirot.mul(DH.vr.getAimRotation(0), guirot); } else { - guirot = guirot.mul(DH.vr.hmdRotation, guirot); + guirot = guirot.mul(DH.vr.getEyeRotation(RenderPass.CENTER), guirot); } guipos = new Vec3( diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java index 1cce767f8..adf408564 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java @@ -55,11 +55,13 @@ public abstract class MCVR { protected HardwareType detectedHardware = HardwareType.VIVE; - // position/orientation of headset and eye offsets - protected Matrix4f hmdPose = new Matrix4f(); - public Matrix4f hmdRotation = new Matrix4f(); - protected Matrix4f hmdPoseLeftEye = new Matrix4f(); - protected Matrix4f hmdPoseRightEye = new Matrix4f(); + // position/orientation of headset and eyes + protected final Matrix4f hmdPose = new Matrix4f(); + protected final Matrix4f hmdRotation = new Matrix4f(); + protected final Matrix4f hmdPoseLeftEye = new Matrix4f(); + protected final Matrix4f hmdPoseRightEye = new Matrix4f(); + protected final Matrix4f hmdRotationLeftEye = new Matrix4f(); + protected final Matrix4f hmdRotationRightEye = new Matrix4f(); public Vector3fHistory hmdHistory = new Vector3fHistory(); public Vector3fHistory hmdPivotHistory = new Vector3fHistory(); @@ -285,11 +287,10 @@ public Vector3f getHandVector(int controller) { * @return position of the given eye, in room space */ public Vector3f getEyePosition(RenderPass eye) { - Matrix4f pose = new Matrix4f(this.hmdPose); - switch (eye) { - case LEFT -> pose.mul(this.hmdPoseLeftEye); - case RIGHT -> pose.mul(this.hmdPoseRightEye); - default -> {} + Matrix4fc pose = switch (eye) { + case LEFT -> this.hmdPoseLeftEye; + case RIGHT -> this.hmdPoseRightEye; + default -> this.hmdPose; }; Vector3f pos = pose.getTranslation(new Vector3f()); @@ -308,18 +309,11 @@ public Vector3f getEyePosition(RenderPass eye) { * @return rotation of the given eye, in room space */ public Matrix4fc getEyeRotation(RenderPass eye) { - Matrix4f hmdToEye = switch (eye) { - case LEFT -> this.hmdPoseLeftEye; - case RIGHT -> this.hmdPoseRightEye; - default -> null; + return switch (eye) { + case LEFT -> this.hmdRotationLeftEye; + case RIGHT -> this.hmdRotationRightEye; + default -> this.hmdRotation; }; - - if (hmdToEye != null) { - Matrix4f eyeRot = new Matrix4f().set3x3(hmdToEye); - return this.hmdRotation.mul(eyeRot, eyeRot); - } else { - return this.hmdRotation; - } } /** @@ -594,6 +588,9 @@ protected void updateAim() { this.hmdRotation.identity(); this.hmdRotation.set3x3(this.hmdPose); + this.hmdRotationLeftEye.set3x3(this.hmdPoseLeftEye); + this.hmdRotationRightEye.set3x3(this.hmdPoseRightEye); + Vector3fc eye = this.getEyePosition(RenderPass.CENTER); this.hmdHistory.add(eye); diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index be3d7689c..bf8ee4fdc 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -1241,6 +1241,10 @@ private void updatePose() { this.hmdPose.m31(1.62F); } + // ret the complete room eye transforms + this.hmdPose.mul(this.hmdPoseLeftEye, this.hmdPoseLeftEye); + this.hmdPose.mul(this.hmdPoseRightEye, this.hmdPoseRightEye); + // Gotta do this here so we can get the poses if (this.inputInitialized) { this.mc.getProfiler().push("updateActionState"); diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 9a11157f0..7df540539 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -217,7 +217,6 @@ private void updatePose() { logError(error, "xrLocateSpace", "xrViewSpace"); if (error >= 0) { OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.hmdPose); - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.hmdRotation); headIsTracking = true; } else { headIsTracking = false; @@ -299,30 +298,6 @@ private void updatePose() { } } - /** - * @param eye LEFT, RIGHT or CENTER eye - * @return position of the given eye, in room space - */ - @Override - public Vector3f getEyePosition(RenderPass eye) { - Matrix4f pose = new Matrix4f(this.hmdPose); - switch (eye) { - case LEFT -> pose = this.hmdPoseLeftEye; //OpenXR includes total - case RIGHT -> pose = this.hmdPoseRightEye; - default -> {} - }; - - Vector3f pos = pose.getTranslation(new Vector3f()); - - if (this.dh.vrSettings.seated || this.dh.vrSettings.allowStandingOriginOffset) { - if (this.dh.vr.isHMDTracking()) { - pos = pos.add(this.dh.vrSettings.originOffset); - } - } - - return pos; - } - public void readNewData(VRInputAction action) { switch (action.type) { case "boolean" -> { From c8f298bc2c0bfcde4be6008c9e063cf6e1a60204 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 11 Dec 2024 21:08:17 +0100 Subject: [PATCH 12/27] fix nullvr eye offset after last change --- .../java/org/vivecraft/client_vr/provider/nullvr/NullVR.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java index 86978f652..84d2c5b9c 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java @@ -65,7 +65,10 @@ public boolean init() { this.hmdPose.m31(1.62F); // eye offset, 10cm total distance + this.hmdPoseLeftEye.set(this.hmdPose); this.hmdPoseLeftEye.m30(-IPD * 0.5F); + + this.hmdPoseRightEye.set(this.hmdPose); this.hmdPoseRightEye.m30(IPD * 0.5F); this.populateInputActions(); From 8c95d0561150466fdf548d70466413041cbcdc23 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Mon, 16 Dec 2024 13:53:53 +0100 Subject: [PATCH 13/27] fix lwjgl dependency declaration, parchment mappings and mixin extras somehow those got lost on the merge --- build.gradle | 23 ++++++++++++----------- forge/build.gradle | 25 ++++++++++++++----------- neoforge/build.gradle | 25 ++++++++++++++----------- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/build.gradle b/build.gradle index b5c77db1c..9ff0573f2 100644 --- a/build.gradle +++ b/build.gradle @@ -21,19 +21,20 @@ subprojects { dependencies { minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" - // The following line declares the mojmap mappings, you may use other mappings as well - mappings loom.officialMojangMappings() - // The following line declares the yarn mappings you may select this one as well. - // mappings "net.fabricmc:yarn:1.18.2+build.4:v2" - implementation("org.lwjgl:lwjgl-openvr:3.3.2") - implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-linux") - implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") - implementation("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") + mappings loom.layered() { + officialMojangMappings() + // parchment mappings as backup + parchment("org.parchmentmc.data:parchment-${rootProject.minecraft_version}:${rootProject.parchment_version}@zip") + } + implementation("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}") + implementation("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-linux") + implementation("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-macos") + implementation("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-windows") // Use custom OpenXR lib for Android and GLES bindings - implementation("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") - implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") - implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") + implementation("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}") + implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux") + implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows") } tasks.withType(JavaCompile).configureEach { diff --git a/forge/build.gradle b/forge/build.gradle index 5644be879..d5c4a7303 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -60,19 +60,22 @@ dependencies { forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-windows") // Use custom OpenXR lib for Android and GLES bindings - forgeRuntimeLibrary("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") + forgeRuntimeLibrary("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows") // shadow the natives - bundle("org.lwjgl:lwjgl-openvr:3.3.2") { transitive = false } - bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-linux") { transitive = false } - bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") { transitive = false } - bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") { transitive = false } - - bundle("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") { transitive = false } + bundle("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}") { transitive = false } + bundle("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-linux") { transitive = false } + bundle("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-macos") { transitive = false } + bundle("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-windows") { transitive = false } + + bundle("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows") { transitive = false } + + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixin_extras_version}")) + implementation(include("io.github.llamalad7:mixinextras-forge:${rootProject.mixin_extras_version}")) } processResources { diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 55ab34124..3fec03e29 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -36,19 +36,22 @@ dependencies { forgeRuntimeLibrary("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-windows") // Use custom OpenXR lib for Android and GLES bindings - forgeRuntimeLibrary("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") - forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") + forgeRuntimeLibrary("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux") + forgeRuntimeLibrary("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows") // shadow the natives - bundle("org.lwjgl:lwjgl-openvr:3.3.2") { transitive = false } - bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-linux") { transitive = false } - bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-macos") { transitive = false } - bundle("org.lwjgl:lwjgl-openvr:3.3.2:natives-windows") { transitive = false } - - bundle("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux") { transitive = false } - bundle("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows") { transitive = false } + bundle("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}") { transitive = false } + bundle("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-linux") { transitive = false } + bundle("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-macos") { transitive = false } + bundle("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-windows") { transitive = false } + + bundle("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux") { transitive = false } + bundle("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows") { transitive = false } + + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:${rootProject.mixin_extras_version}")) + implementation(include("io.github.llamalad7:mixinextras-neoforge:${rootProject.mixin_extras_version}")) } processResources { From 1ede10d5f2ea149a477c6a94044dffa51ca3b9c2 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Mon, 23 Dec 2024 04:12:15 +0100 Subject: [PATCH 14/27] fix fabric build gradle --- fabric/build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fabric/build.gradle b/fabric/build.gradle index 82f5e8837..7e08316ee 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -69,9 +69,9 @@ dependencies { include(implementation("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-windows")) // Use custom OpenXR lib for Android and GLES bindings - include(implementation("QuestCraftPlusPlus:lwjgl3:3.3.2:lwjgl-openxr-3.3.2")) - include(implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-windows")) - include(implementation("org.lwjgl:lwjgl-openxr:3.3.2:natives-linux")) + include(implementation("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}")) + include(implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows")) + include(implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux")) } processResources { @@ -129,4 +129,4 @@ publishing { repositories { // Add repositories to publish to here. } -} \ No newline at end of file +} From c93483780d205a528daf7c0db8bd5a1c8abcfe8b Mon Sep 17 00:00:00 2001 From: Darien Johnson <84008186+CADIndie@users.noreply.github.com> Date: Tue, 7 Jan 2025 19:16:45 -0500 Subject: [PATCH 15/27] Fixes and temp changes --- build.gradle | 4 +- .../vivecraft/client_vr/VRTextureTarget.java | 4 +- .../client_vr/provider/VRRenderer.java | 21 ------ .../provider/openvr_lwjgl/MCOpenVR.java | 10 +-- .../provider/openxr/DeviceCompat.java | 74 ++++++++++--------- .../client_vr/provider/openxr/MCOpenXR.java | 21 +++--- .../mixin/client_vr/KeyboardInputVRMixin.java | 1 - fabric/build.gradle | 4 +- 8 files changed, 63 insertions(+), 76 deletions(-) diff --git a/build.gradle b/build.gradle index c291e2fc1..5816b61e0 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,9 @@ subprojects { implementation("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-windows") // Use custom OpenXR lib for Android and GLES bindings - implementation("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}") + //implementation("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}") + + implementation("org.lwjgl:lwjgl-openxr:3.3.3") implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux") implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows") diff --git a/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java b/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java index e2185f34d..3cb8fe5f3 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java @@ -42,8 +42,8 @@ public VRTextureTarget( public VRTextureTarget(String name, int width, int height, int colorid, int index) { super(true); this.name = name; - RenderSystem.assertOnGameThreadOrInit(); - this.resize(width, height, Minecraft.ON_OSX); + RenderSystem.assertOnRenderThreadOrInit(); + this.resize(width, height); ((RenderTargetExtension) this).vivecraft$setColorid(colorid); GlStateManager._glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferId); GL30.glFramebufferTextureLayer(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, colorid, 0, index); diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java index c7331a0d0..515bd0a64 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java @@ -659,33 +659,12 @@ public void setupRenderConfiguration(boolean render) throws RenderConfigExceptio this.createRenderTexture(eyew, eyeh); - if (this.LeftEyeTextureId == -1) { - throw new RenderConfigException( - Component.translatable("vivecraft.messages.renderiniterror", this.getName()), - Component.literal(this.getLastError())); - } - VRSettings.LOGGER.info("Vivecraft: VR Provider supplied render texture IDs: {}, {}", this.LeftEyeTextureId, this.RightEyeTextureId); VRSettings.LOGGER.info("Vivecraft: VR Provider supplied texture resolution: {} x {}", eyew, eyeh); - } RenderHelper.checkGLError("Render Texture setup"); - if (this.framebufferEye0 == null) { - this.framebufferEye0 = new VRTextureTarget("L Eye", eyew, eyeh, false, this.LeftEyeTextureId, true, - false, false); - VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEye0); - RenderHelper.checkGLError("Left Eye framebuffer setup"); - } - - if (this.framebufferEye1 == null) { - this.framebufferEye1 = new VRTextureTarget("R Eye", eyew, eyeh, false, this.RightEyeTextureId, true, - false, false); - VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEye1); - RenderHelper.checkGLError("Right Eye framebuffer setup"); - } - float resolutionScale = ResolutionControlHelper.isLoaded() ? ResolutionControlHelper.getCurrentScaleFactor() : 1.0F; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index 9773d559e..728d32b81 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -231,7 +231,7 @@ public MCOpenVR(Minecraft mc, ClientDataHolderVR dh) throws RenderConfigExceptio this.digital = InputDigitalActionData.calloc(); this.analog = InputAnalogActionData.calloc(); - this.trackedDevicePoses = TrackedDevicePose.calloc(k_unMaxTrackedDeviceCount); + this.hmdTrackedDevicePoses = TrackedDevicePose.calloc(k_unMaxTrackedDeviceCount); } @Override @@ -255,7 +255,7 @@ public void destroy() { } // free memory - this.trackedDevicePoses.free(); + this.hmdTrackedDevicePoses.free(); this.poseData.free(); this.originInfo.free(); @@ -1440,7 +1440,7 @@ private void updateTrackerPose(int controller, boolean fetchDeviceIndex) { */ private void updatePose() { // gets poses for all tracked devices from OpenVR - int error = VRCompositor_WaitGetPoses(this.trackedDevicePoses, null); + int error = VRCompositor_WaitGetPoses(this.hmdTrackedDevicePoses, null); if (error > EVRCompositorError_VRCompositorError_None) { VRSettings.LOGGER.error("Vivecraft: Compositor Error: GetPoseError {}", @@ -1477,7 +1477,7 @@ private void updatePose() { // copy device poses for (int device = 0; device < k_unMaxTrackedDeviceCount; device++) { - TrackedDevicePose pose = this.trackedDevicePoses.get(device); + TrackedDevicePose pose = this.hmdTrackedDevicePoses.get(device); if (pose.bPoseIsValid()) { OpenVRUtil.convertSteamVRMatrix3ToMatrix4f(pose.mDeviceToAbsoluteTracking(), this.poseMatrices[device]); HmdVector3 velocity = pose.vVelocity(); @@ -1489,7 +1489,7 @@ private void updatePose() { } // check headset tracking state - if (this.trackedDevicePoses.get(k_unTrackedDeviceIndex_Hmd).bPoseIsValid()) { + if (this.hmdTrackedDevicePoses.get(k_unTrackedDeviceIndex_Hmd).bPoseIsValid()) { this.hmdPose.set(this.poseMatrices[k_unTrackedDeviceIndex_Hmd]); this.headIsTracking = true; } else { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java index c3cff1fc4..65b22f96a 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java @@ -104,57 +104,61 @@ public Struct checkGraphics(MemoryStack stack, XrInstance instance, long systemI class Mobile implements DeviceCompat { @Override public long getPlatformInfo(MemoryStack stack) { - return XrInstanceCreateInfoAndroidKHR.calloc(stack).set( - KHRAndroidCreateInstance.XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, - NULL, - VLoader.getDalvikVM(), - VLoader.getDalvikActivity() - ).address(); +// return XrInstanceCreateInfoAndroidKHR.calloc(stack).set( +// KHRAndroidCreateInstance.XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, +// NULL, +// VLoader.getDalvikVM(), +// VLoader.getDalvikActivity() +// ).address(); + return NULL; } @Override public void initOpenXRLoader(MemoryStack stack) { - VRSettings.LOGGER.info("Platform: {}", System.getProperty("os.version")); - VLoader.setupAndroid(); - XrLoaderInitInfoAndroidKHR initInfo = XrLoaderInitInfoAndroidKHR.calloc(stack).set( - KHRLoaderInitAndroid.XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR, - NULL, - VLoader.getDalvikVM(), - VLoader.getDalvikActivity() - ); - - KHRLoaderInit.xrInitializeLoaderKHR(XrLoaderInitInfoBaseHeaderKHR.create(initInfo.address())); +// VRSettings.LOGGER.info("Platform: {}", System.getProperty("os.version")); +// VLoader.setupAndroid(); +// XrLoaderInitInfoAndroidKHR initInfo = XrLoaderInitInfoAndroidKHR.calloc(stack).set( +// KHRLoaderInitAndroid.XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR, +// NULL, +// VLoader.getDalvikVM(), +// VLoader.getDalvikActivity() +// ); +// +// KHRLoaderInit.xrInitializeLoaderKHR(XrLoaderInitInfoBaseHeaderKHR.create(initInfo.address())); } @Override public String getGraphicsExtension() { - return KHROpenGLESEnable.XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME; + //return KHROpenGLESEnable.XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME; + return null; } @Override public XrSwapchainImageOpenGLKHR.Buffer createImageBuffers(int imageCount, MemoryStack stack) { - XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = XrSwapchainImageOpenGLKHR.calloc(imageCount, stack); - for (XrSwapchainImageOpenGLKHR image : swapchainImageBuffer) { - image.type(KHROpenGLESEnable.XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR); - } - - return swapchainImageBuffer; +// XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = XrSwapchainImageOpenGLKHR.calloc(imageCount, stack); +// for (XrSwapchainImageOpenGLKHR image : swapchainImageBuffer) { +// image.type(KHROpenGLESEnable.XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR); +// } +// +// return swapchainImageBuffer; + return null; } @Override public Struct checkGraphics(MemoryStack stack, XrInstance instance, long systemID) { - XrGraphicsRequirementsOpenGLESKHR graphicsRequirements = XrGraphicsRequirementsOpenGLESKHR.calloc(stack).type(KHROpenGLESEnable.XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR); - KHROpenGLESEnable.xrGetOpenGLESGraphicsRequirementsKHR(instance, systemID, graphicsRequirements); - XrGraphicsBindingOpenGLESAndroidKHR graphicsBinding = XrGraphicsBindingOpenGLESAndroidKHR.calloc(stack); - graphicsBinding.set( - KHROpenGLESEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR, - NULL, - VLoader.getEGLDisplay(), - VLoader.getEGLConfig(), - VLoader.getEGLContext() - ); - - return graphicsBinding; +// XrGraphicsRequirementsOpenGLESKHR graphicsRequirements = XrGraphicsRequirementsOpenGLESKHR.calloc(stack).type(KHROpenGLESEnable.XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR); +// KHROpenGLESEnable.xrGetOpenGLESGraphicsRequirementsKHR(instance, systemID, graphicsRequirements); +// XrGraphicsBindingOpenGLESAndroidKHR graphicsBinding = XrGraphicsBindingOpenGLESAndroidKHR.calloc(stack); +// graphicsBinding.set( +// KHROpenGLESEnable.XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR, +// NULL, +// VLoader.getEGLDisplay(), +// VLoader.getEGLConfig(), +// VLoader.getEGLContext() +// ); +// +// return graphicsBinding; + return null; } } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 7df540539..b43e0641d 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -2,6 +2,7 @@ import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; +import net.minecraft.util.profiling.Profiler; import org.apache.commons.lang3.tuple.Pair; import org.joml.Matrix4f; import org.joml.Vector2f; @@ -147,12 +148,12 @@ protected ControllerType findActiveBindingControllerType(KeyMapping binding) { @Override public void poll(long var1) { if (this.initialized) { - this.mc.getProfiler().push("events"); + Profiler.get().push("events"); this.pollVREvents(); if (!this.dh.vrSettings.seated) { - this.mc.getProfiler().popPush("controllers"); - this.mc.getProfiler().push("gui"); + Profiler.get().popPush("controllers"); + Profiler.get().push("gui"); if (this.mc.screen == null && this.dh.vrSettings.vrTouchHotbar) { @@ -161,15 +162,15 @@ public void poll(long var1) { } } - this.mc.getProfiler().pop(); + Profiler.get().pop(); } - this.mc.getProfiler().popPush("updatePose/Vsync"); + Profiler.get().popPush("updatePose/Vsync"); this.updatePose(); - this.mc.getProfiler().popPush("processInputs"); + Profiler.get().popPush("processInputs"); this.processInputs(); - this.mc.getProfiler().popPush("hmdSampling"); + Profiler.get().popPush("hmdSampling"); this.hmdSampling(); - this.mc.getProfiler().pop(); + Profiler.get().pop(); } } @@ -229,7 +230,7 @@ private void updatePose() { OpenXRUtil.openXRPoseToMarix(viewBuffer.get(1).pose(), this.hmdPoseRightEye); if (this.inputInitialized) { - this.mc.getProfiler().push("updateActionState"); + Profiler.get().push("updateActionState"); if (this.updateActiveActionSets()) { XrActionsSyncInfo syncInfo = XrActionsSyncInfo.calloc(stack) @@ -248,7 +249,7 @@ private void updatePose() { this.readPoseData(this.aim[RIGHT_CONTROLLER], actionSet); this.readPoseData(this.aim[LEFT_CONTROLLER], actionSet); - this.mc.getProfiler().pop(); + Profiler.get().pop(); //reverse if (this.dh.vrSettings.reverseHands) { diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java index 3959e6483..3f3107c7a 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/KeyboardInputVRMixin.java @@ -24,7 +24,6 @@ import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.provider.MCVR; -import org.vivecraft.client_vr.provider.openvr_lwjgl.VRInputAction; import org.vivecraft.common.utils.MathUtils; @Mixin(KeyboardInput.class) diff --git a/fabric/build.gradle b/fabric/build.gradle index d559b1d4f..11a5c477d 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -69,7 +69,9 @@ dependencies { include(implementation("org.lwjgl:lwjgl-openvr:${rootProject.lwjgl_version}:natives-windows")) // Use custom OpenXR lib for Android and GLES bindings - include(implementation("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}")) + //include(implementation("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}")) + + include(implementation("org.lwjgl:lwjgl-openxr:3.3.3")) include(implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows")) include(implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux")) From b73f89f9d4d9f4e5745422ea09c81f1dca5e897b Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 8 Jan 2025 02:20:18 +0100 Subject: [PATCH 16/27] some formatting, and cleanup --- build.gradle | 6 +- .../java/org/vivecraft/client_vr/VRState.java | 10 +- .../vivecraft/client_vr/provider/MCVR.java | 27 +- .../client_vr/provider/VRRenderer.java | 6 - .../provider/control/HapticMusicPlayer.java | 13 +- .../provider/control/VRInputAction.java | 3 +- .../control/VivecraftMovementInput.java | 11 - .../provider/openvr_lwjgl/MCOpenVR.java | 122 +---- .../openvr_lwjgl/OpenVRStereoRenderer.java | 30 +- .../provider/openxr/DeviceCompat.java | 11 +- .../client_vr/provider/openxr/MCOpenXR.java | 459 ++++++++++-------- .../provider/openxr/OpenXRStereoRenderer.java | 76 +-- .../client_vr/provider/openxr/OpenXRUtil.java | 7 +- fabric/build.gradle | 2 +- 14 files changed, 357 insertions(+), 426 deletions(-) delete mode 100644 common/src/main/java/org/vivecraft/client_vr/provider/control/VivecraftMovementInput.java diff --git a/build.gradle b/build.gradle index 5816b61e0..9fe9cb17e 100644 --- a/build.gradle +++ b/build.gradle @@ -22,10 +22,8 @@ subprojects { dependencies { minecraft "com.mojang:minecraft:${rootProject.minecraft_version}" mappings loom.layered() { - // The following line declares the mojmap mappings, you may use other mappings as well + // The following line declares the mojmap mappings officialMojangMappings() - // The following line declares the yarn mappings you may select this one as well. - // "net.fabricmc:yarn:1.18.2+build.4:v2" // parchment mappings as backup parchment("org.parchmentmc.data:parchment-${rootProject.minecraft_version}:${rootProject.parchment_version}@zip") } @@ -37,7 +35,7 @@ subprojects { // Use custom OpenXR lib for Android and GLES bindings //implementation("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}") - implementation("org.lwjgl:lwjgl-openxr:3.3.3") + implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}") implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux") implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows") diff --git a/common/src/main/java/org/vivecraft/client_vr/VRState.java b/common/src/main/java/org/vivecraft/client_vr/VRState.java index 354187a31..1757c06db 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRState.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRState.java @@ -53,11 +53,11 @@ public static void initializeVR() { ClientDataHolderVR dh = ClientDataHolderVR.getInstance(); Minecraft instance = Minecraft.getInstance(); - switch (dh.vrSettings.stereoProviderPluginID) { - case OPENVR -> dh.vr = new MCOpenVR(instance, dh); - case OPENXR -> dh.vr = new MCOpenXR(instance, dh); - default -> dh.vr = new NullVR(instance, dh); - } + dh.vr = switch (dh.vrSettings.stereoProviderPluginID) { + case OPENVR -> new MCOpenVR(instance, dh); + case OPENXR -> new MCOpenXR(instance, dh); + default -> new NullVR(instance, dh); + }; if (!dh.vr.init()) { throw new RenderConfigException(Component.translatable("vivecraft.messages.vriniterror"), diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java index ffd505257..322e2f3bb 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java @@ -1411,6 +1411,7 @@ public void processInputs() { /** * updates the KeyMapping state that is linked to the given VRInputAction + * * @param action VRInputAction to process */ private void processInputAction(VRInputAction action) { @@ -1441,14 +1442,15 @@ private void processInputAction(VRInputAction action) { /** * checks the axis input of the VRInputAction linked to {@code keyMapping} and runs the callbacks when it's non 0 - * @param keyMapping KeyMapping to check - * @param upCallback action to do when the axis input is positive + * + * @param keyMapping KeyMapping to check + * @param upCallback action to do when the axis input is positive * @param downCallback action to do when the axis input is negative */ private void processScrollInput(KeyMapping keyMapping, Runnable upCallback, Runnable downCallback) { VRInputAction action = this.getInputAction(keyMapping); - - if (action.isEnabled() && action.getLastOrigin() != 0L) { /** {@link org.lwjgl.openvr.VR.k_ulInvalidInputValueHandle} and {@link org.lwjgl.system.MemoryUtil.NULL} are both 0 */ + /** {@link org.lwjgl.openvr.VR.k_ulInvalidInputValueHandle} and {@link org.lwjgl.system.MemoryUtil.NULL} are both 0 */ + if (action.isEnabled() && action.getLastOrigin() != 0L) { float value = action.getAxis2D(false).y(); if (value != 0.0F) { if (value > 0.0F) { @@ -1462,16 +1464,21 @@ private void processScrollInput(KeyMapping keyMapping, Runnable upCallback, Runn /** * checks the trackpad input of the controller the {@code keyMapping} is on - * @param keyMapping KeyMapping to check - * @param leftCallback action to do when swiped to the left + * + * @param keyMapping KeyMapping to check + * @param leftCallback action to do when swiped to the left * @param rightCallback action to do when swiped to the right - * @param upCallback action to do when swiped to the up - * @param downCallback action to do when swiped to the down + * @param upCallback action to do when swiped to the up + * @param downCallback action to do when swiped to the down */ - private void processSwipeInput(KeyMapping keyMapping, Runnable leftCallback, Runnable rightCallback, Runnable upCallback, Runnable downCallback) { + private void processSwipeInput( + KeyMapping keyMapping, Runnable leftCallback, Runnable rightCallback, Runnable upCallback, + Runnable downCallback) + { VRInputAction action = this.getInputAction(keyMapping); - if (action.isEnabled() && action.getLastOrigin() != 0L) { /** {@link org.lwjgl.openvr.VR.k_ulInvalidInputValueHandle} and {@link org.lwjgl.system.MemoryUtil.NULL} are both 0 */ + /** {@link org.lwjgl.openvr.VR.k_ulInvalidInputValueHandle} and {@link org.lwjgl.system.MemoryUtil.NULL} are both 0 */ + if (action.isEnabled() && action.getLastOrigin() != 0L) { ControllerType controller = this.findActiveBindingControllerType(keyMapping); if (controller != null) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java index 515bd0a64..30c7eaa75 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java @@ -659,12 +659,6 @@ public void setupRenderConfiguration(boolean render) throws RenderConfigExceptio this.createRenderTexture(eyew, eyeh); - VRSettings.LOGGER.info("Vivecraft: VR Provider supplied render texture IDs: {}, {}", - this.LeftEyeTextureId, this.RightEyeTextureId); - VRSettings.LOGGER.info("Vivecraft: VR Provider supplied texture resolution: {} x {}", eyew, eyeh); - - RenderHelper.checkGLError("Render Texture setup"); - float resolutionScale = ResolutionControlHelper.isLoaded() ? ResolutionControlHelper.getCurrentScaleFactor() : 1.0F; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/control/HapticMusicPlayer.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/HapticMusicPlayer.java index 0c7b4e37c..b391ebe8a 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/control/HapticMusicPlayer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/HapticMusicPlayer.java @@ -65,14 +65,13 @@ public void play() { for (Object object : this.data) { if (object instanceof Note note) { if (note.controller != null) { - ClientDataHolderVR.getInstance().vr - .triggerHapticPulse(note.controller, note.durationSeconds, note.frequency, note.amplitude, - delayAccum); + ClientDataHolderVR.getInstance().vr.triggerHapticPulse(note.controller, + note.durationSeconds, note.frequency, note.amplitude, delayAccum); } else { - ClientDataHolderVR.getInstance().vr.triggerHapticPulse(ControllerType.RIGHT, note.durationSeconds, note.frequency, - note.amplitude, delayAccum); - ClientDataHolderVR.getInstance().vr.triggerHapticPulse(ControllerType.LEFT, note.durationSeconds, note.frequency, - note.amplitude, delayAccum); + ClientDataHolderVR.getInstance().vr.triggerHapticPulse(ControllerType.RIGHT, + note.durationSeconds, note.frequency, note.amplitude, delayAccum); + ClientDataHolderVR.getInstance().vr.triggerHapticPulse(ControllerType.LEFT, + note.durationSeconds, note.frequency, note.amplitude, delayAccum); } } else if (object instanceof Delay delay) { delayAccum += delay.durationSeconds; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java index b977855a4..9c924a8ea 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/control/VRInputAction.java @@ -222,7 +222,8 @@ public boolean isEnabled() { // iterate over all actions, and check if another action has a higher priority for (VRInputAction action : ClientDataHolderVR.getInstance().vr.getInputActions()) { if (action != this && action.isEnabledRaw(hand) && action.isActive() && - action.getPriority() > this.getPriority() && ClientDataHolderVR.getInstance().vr.getOrigins(action).contains(lastOrigin)) + action.getPriority() > this.getPriority() && + ClientDataHolderVR.getInstance().vr.getOrigins(action).contains(lastOrigin)) { if (action.isHanded()) { return !((HandedKeyBinding) action.keyBinding).isPriorityOnController(hand); diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/control/VivecraftMovementInput.java b/common/src/main/java/org/vivecraft/client_vr/provider/control/VivecraftMovementInput.java deleted file mode 100644 index 79de67246..000000000 --- a/common/src/main/java/org/vivecraft/client_vr/provider/control/VivecraftMovementInput.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.vivecraft.client_vr.provider.control; - -import net.minecraft.client.KeyMapping; -import org.vivecraft.client_vr.ClientDataHolderVR; - -public class VivecraftMovementInput { - public static float getMovementAxisValue(KeyMapping keyBinding) { - VRInputAction vrinputaction = ClientDataHolderVR.getInstance().vr.getInputAction(keyBinding); - return Math.abs(vrinputaction.getAxis1DUseTracked()); - } -} diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index 728d32b81..15c8fce67 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -3,7 +3,6 @@ import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.mojang.blaze3d.platform.InputConstants; import com.sun.jna.NativeLibrary; import net.minecraft.Util; import net.minecraft.client.KeyMapping; @@ -17,7 +16,6 @@ import org.apache.commons.lang3.tuple.Triple; import org.joml.*; import org.lwjgl.Version; -import org.lwjgl.glfw.GLFW; import org.lwjgl.openvr.*; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; @@ -27,7 +25,6 @@ import org.vivecraft.client.utils.FileUtils; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRState; -import org.vivecraft.client_vr.gameplay.screenhandlers.GuiHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.RadialHandler; import org.vivecraft.client_vr.provider.*; @@ -91,12 +88,9 @@ public class MCOpenVR extends MCVR { private final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); - private final int[] controllerDeviceIndex = new int[3]; - - private final TrackedDevicePose.Buffer hmdTrackedDevicePoses; + private final TrackedDevicePose.Buffer trackedDevicePoses; // haptic handles - private long leftControllerHandle; private long leftHapticHandle; private long rightHapticHandle; @@ -116,7 +110,6 @@ public class MCOpenVR extends MCVR { private boolean paused = false; - private final Map trackpadSwipeSamplers = new HashMap<>(); private boolean triedToInit; private final Queue vrEvents = new LinkedList<>(); @@ -231,7 +224,7 @@ public MCOpenVR(Minecraft mc, ClientDataHolderVR dh) throws RenderConfigExceptio this.digital = InputDigitalActionData.calloc(); this.analog = InputAnalogActionData.calloc(); - this.hmdTrackedDevicePoses = TrackedDevicePose.calloc(k_unMaxTrackedDeviceCount); + this.trackedDevicePoses = TrackedDevicePose.calloc(k_unMaxTrackedDeviceCount); } @Override @@ -255,7 +248,7 @@ public void destroy() { } // free memory - this.hmdTrackedDevicePoses.free(); + this.trackedDevicePoses.free(); this.poseData.free(); this.originInfo.free(); @@ -1166,109 +1159,6 @@ private void loadActionManifest() throws RenderConfigException { } } - /** - * updates the KeyMapping state that is linked to the given VRInputAction - * - * @param action VRInputAction to process - */ - private void processInputAction(VRInputAction action) { - if (action.isActive() && action.isEnabledRaw() && - // try to prevent double left clicks - (!ClientDataHolderVR.getInstance().vrSettings.ingameBindingsInGui || - !(action.actionSet == VRInputActionSet.INGAME && - action.keyBinding.key.getType() == InputConstants.Type.MOUSE && - action.keyBinding.key.getValue() == GLFW.GLFW_MOUSE_BUTTON_LEFT && this.mc.screen != null - ) - )) - { - if (action.isButtonChanged()) { - if (action.isButtonPressed() && action.isEnabled()) { - // We do this, so shit like closing a GUI by clicking a button won't - // also click in the world immediately after. - if (!this.ignorePressesNextFrame) { - action.pressBinding(); - } - } else { - action.unpressBinding(); - } - } - } else { - action.unpressBinding(); - } - } - - /** - * checks the axis input of the VRInputAction linked to {@code keyMapping} and runs the callbacks when it's non 0 - * - * @param keyMapping KeyMapping to check - * @param upCallback action to do when the axis input is positive - * @param downCallback action to do when the axis input is negative - */ - private void processScrollInput(KeyMapping keyMapping, Runnable upCallback, Runnable downCallback) { - VRInputAction action = this.getInputAction(keyMapping); - - if (action.isEnabled() && action.getLastOrigin() != k_ulInvalidInputValueHandle) { - float value = action.getAxis2D(false).y(); - if (value != 0.0F) { - if (value > 0.0F) { - upCallback.run(); - } else if (value < 0.0F) { - downCallback.run(); - } - } - } - } - - /** - * checks the trackpad input of the controller the {@code keyMapping} is on - * - * @param keyMapping KeyMapping to check - * @param leftCallback action to do when swiped to the left - * @param rightCallback action to do when swiped to the right - * @param upCallback action to do when swiped to the up - * @param downCallback action to do when swiped to the down - */ - private void processSwipeInput( - KeyMapping keyMapping, Runnable leftCallback, Runnable rightCallback, Runnable upCallback, - Runnable downCallback) - { - VRInputAction action = this.getInputAction(keyMapping); - - if (action.isEnabled() && action.getLastOrigin() != k_ulInvalidInputValueHandle) { - ControllerType controller = this.findActiveBindingControllerType(keyMapping); - - if (controller != null) { - // if that keyMapping is not tracked yet, create a new sampler - if (!this.trackpadSwipeSamplers.containsKey(keyMapping.getName())) { - this.trackpadSwipeSamplers.put(keyMapping.getName(), new TrackpadSwipeSampler()); - } - - TrackpadSwipeSampler trackpadswipesampler = this.trackpadSwipeSamplers.get(keyMapping.getName()); - trackpadswipesampler.update(controller, action.getAxis2D(false)); - - if (trackpadswipesampler.isSwipedUp() && upCallback != null) { - this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); - upCallback.run(); - } - - if (trackpadswipesampler.isSwipedDown() && downCallback != null) { - this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); - downCallback.run(); - } - - if (trackpadswipesampler.isSwipedLeft() && leftCallback != null) { - this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); - leftCallback.run(); - } - - if (trackpadswipesampler.isSwipedRight() && rightCallback != null) { - this.triggerHapticPulse(controller, 0.001F, 400.0F, 0.5F); - rightCallback.run(); - } - } - } - } - /** * fetches all available VREvents from OpenVR */ @@ -1440,7 +1330,7 @@ private void updateTrackerPose(int controller, boolean fetchDeviceIndex) { */ private void updatePose() { // gets poses for all tracked devices from OpenVR - int error = VRCompositor_WaitGetPoses(this.hmdTrackedDevicePoses, null); + int error = VRCompositor_WaitGetPoses(this.trackedDevicePoses, null); if (error > EVRCompositorError_VRCompositorError_None) { VRSettings.LOGGER.error("Vivecraft: Compositor Error: GetPoseError {}", @@ -1477,7 +1367,7 @@ private void updatePose() { // copy device poses for (int device = 0; device < k_unMaxTrackedDeviceCount; device++) { - TrackedDevicePose pose = this.hmdTrackedDevicePoses.get(device); + TrackedDevicePose pose = this.trackedDevicePoses.get(device); if (pose.bPoseIsValid()) { OpenVRUtil.convertSteamVRMatrix3ToMatrix4f(pose.mDeviceToAbsoluteTracking(), this.poseMatrices[device]); HmdVector3 velocity = pose.vVelocity(); @@ -1489,7 +1379,7 @@ private void updatePose() { } // check headset tracking state - if (this.hmdTrackedDevicePoses.get(k_unTrackedDeviceIndex_Hmd).bPoseIsValid()) { + if (this.trackedDevicePoses.get(k_unTrackedDeviceIndex_Hmd).bPoseIsValid()) { this.hmdPose.set(this.poseMatrices[k_unTrackedDeviceIndex_Hmd]); this.headIsTracking = true; } else { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java index 26816d8b8..a946f1f90 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java @@ -36,8 +36,9 @@ public OpenVRStereoRenderer(MCOpenVR vr) { super(vr); this.openvr = vr; - hiddenMeshes[0] = HiddenAreaMesh.calloc(); - hiddenMeshes[1] = HiddenAreaMesh.calloc(); + // allocate meshes, they are freed in destroy() + this.hiddenMeshes[0] = HiddenAreaMesh.calloc(); + this.hiddenMeshes[1] = HiddenAreaMesh.calloc(); } @Override @@ -126,19 +127,22 @@ public void createRenderTexture(int width, int height) throws RenderConfigExcept Component.literal(this.getLastError())); } - VRSettings.LOGGER.info("Vivecraft: VR Provider supplied render texture IDs: {}, {}", this.LeftEyeTextureId, this.RightEyeTextureId); + VRSettings.LOGGER.info("Vivecraft: VR Provider supplied render texture IDs: {}, {}", this.LeftEyeTextureId, + this.RightEyeTextureId); VRSettings.LOGGER.info("Vivecraft: VR Provider supplied texture resolution: {} x {}", width, height); RenderHelper.checkGLError("Render Texture setup"); if (this.framebufferEye0 == null) { - this.framebufferEye0 = new VRTextureTarget("L Eye", width, height, false, this.LeftEyeTextureId, false, true, false); + this.framebufferEye0 = new VRTextureTarget("L Eye", width, height, false, this.LeftEyeTextureId, false, + true, false); VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEye0); RenderHelper.checkGLError("Left Eye framebuffer setup"); } if (this.framebufferEye1 == null) { - this.framebufferEye1 = new VRTextureTarget("R Eye", width, height, false, this.RightEyeTextureId, false, true, false); + this.framebufferEye1 = new VRTextureTarget("R Eye", width, height, false, this.RightEyeTextureId, false, + true, false); VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEye1); RenderHelper.checkGLError("Right Eye framebuffer setup"); } @@ -214,15 +218,15 @@ public String getName() { @Override protected void destroyBuffers() { super.destroyBuffers(); - if (this.framebufferEye0 != null) { - this.framebufferEye0.destroyBuffers(); - this.framebufferEye0 = null; - } + if (this.framebufferEye0 != null) { + this.framebufferEye0.destroyBuffers(); + this.framebufferEye0 = null; + } - if (this.framebufferEye1 != null) { - this.framebufferEye1.destroyBuffers(); - this.framebufferEye1 = null; - } + if (this.framebufferEye1 != null) { + this.framebufferEye1.destroyBuffers(); + this.framebufferEye1 = null; + } if (this.LeftEyeTextureId > -1) { TextureUtil.releaseTextureId(this.LeftEyeTextureId); this.LeftEyeTextureId = -1; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java index 65b22f96a..d763519f5 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/DeviceCompat.java @@ -25,10 +25,15 @@ //TODO: VulkanMod Support public interface DeviceCompat { long getPlatformInfo(MemoryStack stack); + void initOpenXRLoader(MemoryStack stack); + String getGraphicsExtension(); + XrSwapchainImageOpenGLKHR.Buffer createImageBuffers(int imageCount, MemoryStack stack); + Struct checkGraphics(MemoryStack stack, XrInstance instance, long systemID); + static DeviceCompat detectDevice() { return System.getProperty("os.version").contains("Android") ? new Mobile() : new Desktop(); } @@ -61,7 +66,8 @@ public XrSwapchainImageOpenGLKHR.Buffer createImageBuffers(int imageCount, Memor @Override public Struct checkGraphics(MemoryStack stack, XrInstance instance, long systemID) { - XrGraphicsRequirementsOpenGLKHR graphicsRequirements = XrGraphicsRequirementsOpenGLKHR.calloc(stack).type(KHROpenGLEnable.XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR); + XrGraphicsRequirementsOpenGLKHR graphicsRequirements = XrGraphicsRequirementsOpenGLKHR.calloc(stack) + .type(KHROpenGLEnable.XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR); KHROpenGLEnable.xrGetOpenGLGraphicsRequirementsKHR(instance, systemID, graphicsRequirements); //Bind the OpenGL context to the OpenXR instance and create the session Window window = Minecraft.getInstance().getWindow(); @@ -80,7 +86,8 @@ public Struct checkGraphics(MemoryStack stack, XrInstance instance, long systemI long glXWindowHandle = GLFWNativeGLX.glfwGetGLXWindow(windowHandle); int fbXID = glXQueryDrawable(xDisplay, glXWindowHandle, GLX_FBCONFIG_ID); - PointerBuffer fbConfigBuf = glXChooseFBConfig(xDisplay, X11.XDefaultScreen(xDisplay), stackInts(GLX_FBCONFIG_ID, fbXID, 0)); + PointerBuffer fbConfigBuf = glXChooseFBConfig(xDisplay, X11.XDefaultScreen(xDisplay), + stackInts(GLX_FBCONFIG_ID, fbXID, 0)); if (fbConfigBuf == null) { throw new IllegalStateException("Your framebuffer config was null, make a github issue"); } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index b43e0641d..f3d2ab1c1 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -50,10 +50,10 @@ public class MCOpenXR extends MCVR { public XrView.Buffer viewBuffer; public int width; public int height; - //TODO either move to MCVR, Or make special for OpenXR holding the instance itself. + // TODO either move to MCVR, Or make special for OpenXR holding the instance itself. private final Map actionSetHandles = new EnumMap<>(VRInputActionSet.class); - //TODO Move to MCVR - private XrActiveActionSet.Buffer activeActionSetsBuffer; + // TODO Move to MCVR + private XrActiveActionSet.Buffer activeActionSetsBuffer; private boolean isActive; private final HashMap paths = new HashMap<>(); private final long[] grip = new long[2]; @@ -83,35 +83,35 @@ public String getName() { @Override public void destroy() { int error; - //Not sure if we need the action sets one here, as we are shutting down - for (Long inputActionSet : actionSetHandles.values()){ - error = XR10.xrDestroyActionSet(new XrActionSet(inputActionSet, instance)); + // Not sure if we need the action sets one here, as we are shutting down + for (Long inputActionSet : this.actionSetHandles.values()) { + error = XR10.xrDestroyActionSet(new XrActionSet(inputActionSet, this.instance)); logError(error, "xrDestroyActionSet", ""); } - if (swapchain != null) { - error = XR10.xrDestroySwapchain(swapchain); + if (this.swapchain != null) { + error = XR10.xrDestroySwapchain(this.swapchain); logError(error, "xrDestroySwapchain", ""); } - if (viewBuffer != null) { - viewBuffer.close(); + if (this.viewBuffer != null) { + this.viewBuffer.close(); } - if (xrAppSpace != null) { - error = XR10.xrDestroySpace(xrAppSpace); + if (this.xrAppSpace != null) { + error = XR10.xrDestroySpace(this.xrAppSpace); logError(error, "xrDestroySpace", "xrAppSpace"); } - if (xrViewSpace != null) { - error = XR10.xrDestroySpace(xrViewSpace); + if (this.xrViewSpace != null) { + error = XR10.xrDestroySpace(this.xrViewSpace); logError(error, "xrDestroySpace", "xrViewSpace"); } - if (session != null){ - error = XR10.xrDestroySession(session); + if (this.session != null) { + error = XR10.xrDestroySession(this.session); logError(error, "xrDestroySession", ""); } - if (instance != null){ - error = XR10.xrDestroyInstance(instance); + if (this.instance != null) { + error = XR10.xrDestroyInstance(this.instance); logError(error, "xrDestroyInstance", ""); } - eventDataBuffer.close(); + this.eventDataBuffer.close(); } @Override @@ -122,7 +122,7 @@ protected ControllerType findActiveBindingControllerType(KeyMapping binding) { long path = this.getInputAction(binding).getLastOrigin(); try (MemoryStack stack = MemoryStack.stackPush()) { IntBuffer buf = stack.callocInt(1); - int error = XR10.xrPathToString(instance, path, buf, null); + int error = XR10.xrPathToString(this.instance, path, buf, null); logError(error, "xrPathToString", "get string length for", binding.getName()); int size = buf.get(); @@ -132,7 +132,7 @@ protected ControllerType findActiveBindingControllerType(KeyMapping binding) { buf = stack.callocInt(size); ByteBuffer byteBuffer = stack.calloc(size); - error = XR10.xrPathToString(instance, path, buf, byteBuffer); + error = XR10.xrPathToString(this.instance, path, buf, byteBuffer); logError(error, "xrPathToString", "get string for", binding.getName()); byte[] bytes = new byte[byteBuffer.remaining()]; byteBuffer.get(bytes); @@ -175,7 +175,7 @@ public void poll(long var1) { } private void updatePose() { - if (mc == null) { + if (this.mc == null) { return; } @@ -183,16 +183,16 @@ private void updatePose() { XrFrameState frameState = XrFrameState.calloc(stack).type(XR10.XR_TYPE_FRAME_STATE); int error = XR10.xrWaitFrame( - session, + this.session, XrFrameWaitInfo.calloc(stack).type(XR10.XR_TYPE_FRAME_WAIT_INFO), frameState); logError(error, "xrWaitFrame", ""); - time = frameState.predictedDisplayTime(); + this.time = frameState.predictedDisplayTime(); this.shouldRender = frameState.shouldRender(); error = XR10.xrBeginFrame( - session, + this.session, XrFrameBeginInfo.calloc(stack).type(XR10.XR_TYPE_FRAME_BEGIN_INFO)); logError(error, "xrBeginFrame", ""); @@ -205,29 +205,29 @@ private void updatePose() { 0, XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, frameState.predictedDisplayTime(), - xrAppSpace + this.xrAppSpace ); - error = XR10.xrLocateViews(session, viewLocateInfo, viewState, intBuf, viewBuffer); + error = XR10.xrLocateViews(this.session, viewLocateInfo, viewState, intBuf, this.viewBuffer); logError(error, "xrLocateViews", ""); XrSpaceLocation space_location = XrSpaceLocation.calloc(stack).type(XR10.XR_TYPE_SPACE_LOCATION); - //HMD pose - error = XR10.xrLocateSpace(xrViewSpace, xrAppSpace, time, space_location); + // HMD pose + error = XR10.xrLocateSpace(this.xrViewSpace, this.xrAppSpace, this.time, space_location); logError(error, "xrLocateSpace", "xrViewSpace"); if (error >= 0) { OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.hmdPose); - headIsTracking = true; + this.headIsTracking = true; } else { - headIsTracking = false; + this.headIsTracking = false; this.hmdPose.identity(); this.hmdPose.m31(1.6F); } - //Eye positions - OpenXRUtil.openXRPoseToMarix(viewBuffer.get(0).pose(), this.hmdPoseLeftEye); - OpenXRUtil.openXRPoseToMarix(viewBuffer.get(1).pose(), this.hmdPoseRightEye); + // Eye positions + OpenXRUtil.openXRPoseToMarix(this.viewBuffer.get(0).pose(), this.hmdPoseLeftEye); + OpenXRUtil.openXRPoseToMarix(this.viewBuffer.get(1).pose(), this.hmdPoseRightEye); if (this.inputInitialized) { Profiler.get().push("updateActionState"); @@ -235,15 +235,16 @@ private void updatePose() { if (this.updateActiveActionSets()) { XrActionsSyncInfo syncInfo = XrActionsSyncInfo.calloc(stack) .type(XR10.XR_TYPE_ACTIONS_SYNC_INFO) - .activeActionSets(activeActionSetsBuffer); - error = XR10.xrSyncActions(session, syncInfo); + .activeActionSets(this.activeActionSetsBuffer); + error = XR10.xrSyncActions(this.session, syncInfo); logError(error, "xrSyncActions", ""); } this.inputActions.values().forEach(this::readNewData); //TODO Not needed it seems? Poses come from the action space - XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), + this.instance); this.readPoseData(this.grip[RIGHT_CONTROLLER], actionSet); this.readPoseData(this.grip[LEFT_CONTROLLER], actionSet); this.readPoseData(this.aim[RIGHT_CONTROLLER], actionSet); @@ -251,44 +252,49 @@ private void updatePose() { Profiler.get().pop(); - //reverse + // reverse if (this.dh.vrSettings.reverseHands) { - XrSpace temp = gripSpace[RIGHT_CONTROLLER]; - gripSpace[RIGHT_CONTROLLER] = gripSpace[LEFT_CONTROLLER]; - gripSpace[LEFT_CONTROLLER] = temp; - temp = aimSpace[RIGHT_CONTROLLER]; - aimSpace[RIGHT_CONTROLLER] = aimSpace[LEFT_CONTROLLER]; - aimSpace[LEFT_CONTROLLER] = temp; + XrSpace temp = this.gripSpace[RIGHT_CONTROLLER]; + this.gripSpace[RIGHT_CONTROLLER] = this.gripSpace[LEFT_CONTROLLER]; + this.gripSpace[LEFT_CONTROLLER] = temp; + temp = this.aimSpace[RIGHT_CONTROLLER]; + this.aimSpace[RIGHT_CONTROLLER] = this.aimSpace[LEFT_CONTROLLER]; + this.aimSpace[LEFT_CONTROLLER] = temp; } - //Controller aim and grip poses - error = XR10.xrLocateSpace(gripSpace[RIGHT_CONTROLLER], xrAppSpace, time, space_location); + // Controller aim and grip poses + error = XR10.xrLocateSpace(this.gripSpace[RIGHT_CONTROLLER], this.xrAppSpace, this.time, + space_location); logError(error, "xrLocateSpace", "gripSpace[0]"); if (error >= 0) { - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.handRotation[RIGHT_CONTROLLER]); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), + this.handRotation[RIGHT_CONTROLLER]); } - error = XR10.xrLocateSpace(gripSpace[LEFT_CONTROLLER], xrAppSpace, time, space_location); + error = XR10.xrLocateSpace(this.gripSpace[LEFT_CONTROLLER], this.xrAppSpace, this.time, space_location); logError(error, "xrLocateSpace", "gripSpace[1]"); if (error >= 0) { - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.handRotation[LEFT_CONTROLLER]); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), + this.handRotation[LEFT_CONTROLLER]); } - error = XR10.xrLocateSpace(aimSpace[RIGHT_CONTROLLER], xrAppSpace, time, space_location); + error = XR10.xrLocateSpace(this.aimSpace[RIGHT_CONTROLLER], this.xrAppSpace, this.time, space_location); logError(error, "xrLocateSpace", "aimSpace[0]"); if (error >= 0) { OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.controllerPose[RIGHT_CONTROLLER]); - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.controllerRotation[RIGHT_CONTROLLER]); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), + this.controllerRotation[RIGHT_CONTROLLER]); this.controllerTracking[RIGHT_CONTROLLER] = true; } else { this.controllerTracking[RIGHT_CONTROLLER] = false; } - error = XR10.xrLocateSpace(aimSpace[LEFT_CONTROLLER], xrAppSpace, time, space_location); + error = XR10.xrLocateSpace(this.aimSpace[LEFT_CONTROLLER], this.xrAppSpace, this.time, space_location); logError(error, "xrLocateSpace", "aimSpace[1]"); if (error >= 0) { OpenXRUtil.openXRPoseToMarix(space_location.pose(), this.controllerPose[LEFT_CONTROLLER]); - OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), this.controllerRotation[LEFT_CONTROLLER]); + OpenXRUtil.openXRPoseToMarix(space_location.pose().orientation(), + this.controllerRotation[LEFT_CONTROLLER]); this.controllerTracking[LEFT_CONTROLLER] = true; } else { this.controllerTracking[LEFT_CONTROLLER] = false; @@ -330,7 +336,6 @@ public void readNewData(VRInputAction action) { this.readVecData(action, null); } } - } } @@ -340,13 +345,14 @@ private void readBoolean(VRInputAction action, ControllerType hand) { if (hand != null) { i = hand.ordinal(); } - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrActionStateGetInfo info = XrActionStateGetInfo.calloc(stack); info.type(XR10.XR_TYPE_ACTION_STATE_GET_INFO); - info.action(new XrAction(action.handle, new XrActionSet(actionSetHandles.get(action.actionSet), instance))); + info.action(new XrAction(action.handle, + new XrActionSet(this.actionSetHandles.get(action.actionSet), this.instance))); XrActionStateBoolean state = XrActionStateBoolean.calloc(stack).type(XR10.XR_TYPE_ACTION_STATE_BOOLEAN); - int error = XR10.xrGetActionStateBoolean(session, info, state); - logError(error, "xrGetActionStateBoolean", action.name); + int error = XR10.xrGetActionStateBoolean(this.session, info, state); + logError(error, "xrGetActionStateBoolean", action.name); action.digitalData[i].state = state.currentState(); action.digitalData[i].isActive = state.isActive(); @@ -361,13 +367,14 @@ private void readFloat(VRInputAction action, ControllerType hand) { if (hand != null) { i = hand.ordinal(); } - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrActionStateGetInfo info = XrActionStateGetInfo.calloc(stack); info.type(XR10.XR_TYPE_ACTION_STATE_GET_INFO); - info.action(new XrAction(action.handle, new XrActionSet(actionSetHandles.get(action.actionSet), instance))); + info.action(new XrAction(action.handle, + new XrActionSet(this.actionSetHandles.get(action.actionSet), this.instance))); XrActionStateFloat state = XrActionStateFloat.calloc(stack).type(XR10.XR_TYPE_ACTION_STATE_FLOAT); - int error = XR10.xrGetActionStateFloat(session, info, state); - logError(error, "xrGetActionStateFloat", action.name); + int error = XR10.xrGetActionStateFloat(this.session, info, state); + logError(error, "xrGetActionStateFloat", action.name); action.analogData[i].deltaX = action.analogData[i].x - state.currentState(); action.analogData[i].x = state.currentState(); @@ -383,13 +390,14 @@ private void readVecData(VRInputAction action, ControllerType hand) { if (hand != null) { i = hand.ordinal(); } - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrActionStateGetInfo info = XrActionStateGetInfo.calloc(stack); info.type(XR10.XR_TYPE_ACTION_STATE_GET_INFO); - info.action(new XrAction(action.handle, new XrActionSet(actionSetHandles.get(action.actionSet), instance))); + info.action(new XrAction(action.handle, + new XrActionSet(this.actionSetHandles.get(action.actionSet), this.instance))); XrActionStateVector2f state = XrActionStateVector2f.calloc(stack).type(XR10.XR_TYPE_ACTION_STATE_VECTOR2F); - int error = XR10.xrGetActionStateVector2f(session, info, state); - logError(error, "xrGetActionStateVector2f", action.name); + int error = XR10.xrGetActionStateVector2f(this.session, info, state); + logError(error, "xrGetActionStateVector2f", action.name); action.analogData[i].deltaX = action.analogData[i].x - state.currentState().x(); action.analogData[i].deltaY = action.analogData[i].y - state.currentState().y(); @@ -402,13 +410,13 @@ private void readVecData(VRInputAction action, ControllerType hand) { } private void readPoseData(Long action, XrActionSet set) { - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrActionStateGetInfo info = XrActionStateGetInfo.calloc(stack); info.type(XR10.XR_TYPE_ACTION_STATE_GET_INFO); info.action(new XrAction(action, set)); XrActionStatePose state = XrActionStatePose.calloc(stack).type(XR10.XR_TYPE_ACTION_STATE_POSE); - int error = XR10.xrGetActionStatePose(session, info, state); - logError(error, "xrGetActionStatePose", ""); + int error = XR10.xrGetActionStatePose(this.session, info, state); + logError(error, "xrGetActionStatePose", ""); } } @@ -437,15 +445,16 @@ private boolean updateActiveActionSets() { } if (this.activeActionSetsBuffer == null) { - activeActionSetsBuffer = XrActiveActionSet.calloc(arraylist.size()); - } else if (activeActionSetsBuffer.capacity() != arraylist.size()) { - activeActionSetsBuffer.close(); - activeActionSetsBuffer = XrActiveActionSet.calloc(arraylist.size()); + this.activeActionSetsBuffer = XrActiveActionSet.calloc(arraylist.size()); + } else if (this.activeActionSetsBuffer.capacity() != arraylist.size()) { + this.activeActionSetsBuffer.close(); + this.activeActionSetsBuffer = XrActiveActionSet.calloc(arraylist.size()); } for (int i = 0; i < arraylist.size(); ++i) { VRInputActionSet vrinputactionset = arraylist.get(i); - activeActionSetsBuffer.get(i).set(new XrActionSet(this.getActionSetHandle(vrinputactionset), instance), NULL); + this.activeActionSetsBuffer.get(i) + .set(new XrActionSet(this.getActionSetHandle(vrinputactionset), this.instance), NULL); } return !arraylist.isEmpty(); @@ -457,18 +466,19 @@ long getActionSetHandle(VRInputActionSet actionSet) { private void pollVREvents() { while (true) { - eventDataBuffer.clear(); - eventDataBuffer.type(XR10.XR_TYPE_EVENT_DATA_BUFFER); - int error = XR10.xrPollEvent(instance, eventDataBuffer); - logError(error, "xrPollEvent", ""); + this.eventDataBuffer.clear(); + this.eventDataBuffer.type(XR10.XR_TYPE_EVENT_DATA_BUFFER); + int error = XR10.xrPollEvent(this.instance, this.eventDataBuffer); + logError(error, "xrPollEvent", ""); if (error != XR10.XR_SUCCESS) { break; } - XrEventDataBaseHeader event = XrEventDataBaseHeader.create(eventDataBuffer.address()); + XrEventDataBaseHeader event = XrEventDataBaseHeader.create(this.eventDataBuffer.address()); switch (event.type()) { case XR10.XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING -> { - XrEventDataInstanceLossPending instanceLossPending = XrEventDataInstanceLossPending.create(event.address()); + XrEventDataInstanceLossPending instanceLossPending = XrEventDataInstanceLossPending.create( + event.address()); } case XR10.XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED -> { this.sessionChanged(XrEventDataSessionStateChanged.create(event.address())); @@ -488,22 +498,22 @@ private void sessionChanged(XrEventDataSessionStateChanged xrEventDataSessionSta switch (state) { case XR10.XR_SESSION_STATE_READY: { - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrSessionBeginInfo sessionBeginInfo = XrSessionBeginInfo.calloc(stack); sessionBeginInfo.type(XR10.XR_TYPE_SESSION_BEGIN_INFO); sessionBeginInfo.next(NULL); sessionBeginInfo.primaryViewConfigurationType(XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO); - int error = XR10.xrBeginSession(session, sessionBeginInfo); - logError(error, "xrBeginSession", "XR_SESSION_STATE_READY"); + int error = XR10.xrBeginSession(this.session, sessionBeginInfo); + logError(error, "xrBeginSession", "XR_SESSION_STATE_READY"); } this.isActive = true; break; } case XR10.XR_SESSION_STATE_STOPPING: { this.isActive = false; - int error = XR10.xrEndSession(session); - logError(error, "xrEndSession", "XR_SESSION_STATE_STOPPING"); + int error = XR10.xrEndSession(this.session); + logError(error, "xrEndSession", "XR_SESSION_STATE_STOPPING"); } case XR10.XR_SESSION_STATE_VISIBLE, XR10.XR_SESSION_STATE_FOCUSED: { this.isActive = true; @@ -525,8 +535,8 @@ private void sessionChanged(XrEventDataSessionStateChanged xrEventDataSessionSta public Vector2f getPlayAreaSize() { try (MemoryStack stack = MemoryStack.stackPush()) { XrExtent2Df vec = XrExtent2Df.calloc(stack); - int error = XR10.xrGetReferenceSpaceBoundsRect(session, XR10.XR_REFERENCE_SPACE_TYPE_STAGE, vec); - logError(error, "xrGetReferenceSpaceBoundsRect", ""); + int error = XR10.xrGetReferenceSpaceBoundsRect(this.session, XR10.XR_REFERENCE_SPACE_TYPE_STAGE, vec); + logError(error, "xrGetReferenceSpaceBoundsRect", ""); return new Vector2f(vec.width(), vec.height()); } } @@ -538,7 +548,7 @@ public boolean init() { } else if (this.tried) { return this.initialized; } else { - tried = true; + this.tried = true; this.mc = Minecraft.getInstance(); try { this.initializeOpenXRInstance(); @@ -553,7 +563,7 @@ public boolean init() { return false; } - //TODO Seated when no controllers + // TODO Seated when no controllers System.out.println("OpenXR initialized & VR connected."); this.deviceVelocity = new Vector3f[64]; @@ -570,23 +580,23 @@ public boolean init() { private void initializeOpenXRInstance() { try (MemoryStack stack = MemoryStack.stackPush()) { - device.initOpenXRLoader(stack); + this.device.initOpenXRLoader(stack); - //Check extensions + // Check extensions IntBuffer numExtensions = stack.callocInt(1); int error = XR10.xrEnumerateInstanceExtensionProperties((ByteBuffer) null, numExtensions, null); - logError(error, "xrEnumerateInstanceExtensionProperties", "get count"); + logError(error, "xrEnumerateInstanceExtensionProperties", "get count"); XrExtensionProperties.Buffer properties = new XrExtensionProperties.Buffer( bufferStack(numExtensions.get(0), XrExtensionProperties.SIZEOF, XR10.XR_TYPE_EXTENSION_PROPERTIES) ); - //Load extensions + // Load extensions error = XR10.xrEnumerateInstanceExtensionProperties((ByteBuffer) null, numExtensions, properties); - logError(error, "xrEnumerateInstanceExtensionProperties", "get extensions"); + logError(error, "xrEnumerateInstanceExtensionProperties", "get extensions"); - //get needed extensions - String graphicsExtension = device.getGraphicsExtension(); + // get needed extensions + String graphicsExtension = this.device.getGraphicsExtension(); boolean missingGraphics = true; PointerBuffer extensions = stack.callocPointer(3); while (properties.hasRemaining()) { @@ -596,11 +606,17 @@ private void initializeOpenXRInstance() { missingGraphics = false; extensions.put(memAddress(stackUTF8(graphicsExtension))); } - if (extensionName.equals(EXTHPMixedRealityController.XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME)) { - extensions.put(memAddress(stackUTF8(EXTHPMixedRealityController.XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))); + if (extensionName.equals( + EXTHPMixedRealityController.XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME)) + { + extensions.put(memAddress( + stackUTF8(EXTHPMixedRealityController.XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME))); } - if (extensionName.equals(HTCViveCosmosControllerInteraction.XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME)) { - extensions.put(memAddress(stackUTF8(HTCViveCosmosControllerInteraction.XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME))); + if (extensionName.equals( + HTCViveCosmosControllerInteraction.XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME)) + { + extensions.put(memAddress(stackUTF8( + HTCViveCosmosControllerInteraction.XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME))); } } @@ -608,22 +624,22 @@ private void initializeOpenXRInstance() { throw new RuntimeException("OpenXR runtime is missing a supported graphics extension."); } - //Create APP info + // Create APP info XrApplicationInfo applicationInfo = XrApplicationInfo.calloc(stack); applicationInfo.apiVersion(XR10.XR_MAKE_VERSION(1, 0, 40)); applicationInfo.applicationName(stack.UTF8("Vivecraft")); applicationInfo.applicationVersion(1); - //Create instance info + // Create instance info XrInstanceCreateInfo createInfo = XrInstanceCreateInfo.calloc(stack); createInfo.type(XR10.XR_TYPE_INSTANCE_CREATE_INFO); - createInfo.next(device.getPlatformInfo(stack)); + createInfo.next(this.device.getPlatformInfo(stack)); createInfo.createFlags(0); createInfo.applicationInfo(applicationInfo); createInfo.enabledApiLayerNames(null); createInfo.enabledExtensionNames(extensions.flip()); - //Create XR instance + // Create XR instance PointerBuffer instancePtr = stack.callocPointer(1); int xrResult = XR10.xrCreateInstance(createInfo, instancePtr); if (xrResult == XR10.XR_ERROR_RUNTIME_FAILURE) { @@ -633,7 +649,7 @@ private void initializeOpenXRInstance() { } else if (xrResult < 0) { throw new RuntimeException("XR method returned " + xrResult); } - instance = new XrInstance(instancePtr.get(0), createInfo); + this.instance = new XrInstance(instancePtr.get(0), createInfo); this.poseMatrices = new Matrix4f[64]; @@ -651,24 +667,24 @@ public static MCOpenXR get() { private void initializeOpenXRSession() { try (MemoryStack stack = MemoryStack.stackPush()) { - //Create system + // Create system XrSystemGetInfo system = XrSystemGetInfo.calloc(stack); system.type(XR10.XR_TYPE_SYSTEM_GET_INFO); system.next(NULL); system.formFactor(XR10.XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY); LongBuffer longBuffer = stack.callocLong(1); - int error = XR10.xrGetSystem(instance, system, longBuffer); - logError(error, "xrGetSystem", ""); + int error = XR10.xrGetSystem(this.instance, system, longBuffer); + logError(error, "xrGetSystem", ""); this.systemID = longBuffer.get(0); - if (systemID == 0) { + if (this.systemID == 0) { throw new RuntimeException("No compatible headset detected"); } XrSystemProperties systemProperties = XrSystemProperties.calloc(stack).type(XR10.XR_TYPE_SYSTEM_PROPERTIES); - error = XR10.xrGetSystemProperties(instance, systemID, systemProperties); - MCOpenXR.get().logError(error, "xrGetSystemProperties", ""); + error = XR10.xrGetSystemProperties(this.instance, this.systemID, systemProperties); + MCOpenXR.get().logError(error, "xrGetSystemProperties", ""); XrSystemTrackingProperties trackingProperties = systemProperties.trackingProperties(); XrSystemGraphicsProperties graphicsProperties = systemProperties.graphicsProperties(); @@ -680,34 +696,35 @@ private void initializeOpenXRSession() { int maxHeight = graphicsProperties.maxSwapchainImageHeight(); int maxLayerCount = graphicsProperties.maxLayerCount(); - VRSettings.LOGGER.info("Found device with id: {}", systemID); + VRSettings.LOGGER.info("Found device with id: {}", this.systemID); VRSettings.LOGGER.info("Headset Name: {}, Vendor: {}", MCOpenXR.get().systemName, vendor); - VRSettings.LOGGER.info("Headset Orientation Tracking: {}, Position Tracking: {}", orientationTracking, positionTracking); - VRSettings.LOGGER.info("Headset Max Width: {}, Max Height: {}, Max Layer Count: {}", maxWidth, maxHeight, maxLayerCount); + VRSettings.LOGGER.info("Headset Orientation Tracking: {}, Position Tracking: {}", orientationTracking, + positionTracking); + VRSettings.LOGGER.info("Headset Max Width: {}, Max Height: {}, Max Layer Count: {}", maxWidth, maxHeight, + maxLayerCount); - //Create session + // Create session XrSessionCreateInfo info = XrSessionCreateInfo.calloc(stack); info.type(XR10.XR_TYPE_SESSION_CREATE_INFO); - info.next(device.checkGraphics(stack, instance, systemID).address()); + info.next(this.device.checkGraphics(stack, this.instance, this.systemID).address()); info.createFlags(0); - info.systemId(systemID); + info.systemId(this.systemID); PointerBuffer sessionPtr = stack.callocPointer(1); - error = XR10.xrCreateSession(instance, info, sessionPtr); - logError(error, "xrCreateSession", ""); + error = XR10.xrCreateSession(this.instance, info, sessionPtr); + logError(error, "xrCreateSession", ""); - session = new XrSession(sessionPtr.get(0), instance); + this.session = new XrSession(sessionPtr.get(0), this.instance); while (!this.isActive) { System.out.println("waiting"); pollVREvents(); } - } } private void initializeOpenXRSpace() { - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrPosef identityPose = XrPosef.calloc(stack); identityPose.set( XrQuaternionf.calloc(stack).set(0, 0, 0, 1), @@ -721,48 +738,51 @@ private void initializeOpenXRSpace() { referenceSpaceCreateInfo.poseInReferenceSpace(identityPose); PointerBuffer pp = stack.callocPointer(1); - int error = XR10.xrCreateReferenceSpace(session, referenceSpaceCreateInfo, pp); - xrAppSpace = new XrSpace(pp.get(0), session); - logError(error, "xrCreateReferenceSpace", "XR_REFERENCE_SPACE_TYPE_STAGE"); + int error = XR10.xrCreateReferenceSpace(this.session, referenceSpaceCreateInfo, pp); + this.xrAppSpace = new XrSpace(pp.get(0), this.session); + logError(error, "xrCreateReferenceSpace", "XR_REFERENCE_SPACE_TYPE_STAGE"); referenceSpaceCreateInfo.referenceSpaceType(XR10.XR_REFERENCE_SPACE_TYPE_VIEW); - error = XR10.xrCreateReferenceSpace(session, referenceSpaceCreateInfo, pp); - logError(error, "xrCreateReferenceSpace", "XR_REFERENCE_SPACE_TYPE_VIEW"); - xrViewSpace = new XrSpace(pp.get(0), session); + error = XR10.xrCreateReferenceSpace(this.session, referenceSpaceCreateInfo, pp); + logError(error, "xrCreateReferenceSpace", "XR_REFERENCE_SPACE_TYPE_VIEW"); + this.xrViewSpace = new XrSpace(pp.get(0), this.session); } } private void initializeOpenXRSwapChain() { try (MemoryStack stack = stackPush()) { - //Check amount of views + // Check amount of views IntBuffer intBuf = stack.callocInt(1); - int error = XR10.xrEnumerateViewConfigurationViews(instance, systemID, XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, intBuf, null); - logError(error, "xrEnumerateViewConfigurationViews", "get count"); + int error = XR10.xrEnumerateViewConfigurationViews(this.instance, this.systemID, + XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, intBuf, null); + logError(error, "xrEnumerateViewConfigurationViews", "get count"); - //Get all views - ByteBuffer viewConfBuffer = bufferStack(intBuf.get(0), XrViewConfigurationView.SIZEOF, XR10.XR_TYPE_VIEW_CONFIGURATION_VIEW); + // Get all views + ByteBuffer viewConfBuffer = bufferStack(intBuf.get(0), XrViewConfigurationView.SIZEOF, + XR10.XR_TYPE_VIEW_CONFIGURATION_VIEW); XrViewConfigurationView.Buffer views = new XrViewConfigurationView.Buffer(viewConfBuffer); - error = XR10.xrEnumerateViewConfigurationViews(instance, systemID, XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, intBuf, views); - logError(error, "xrEnumerateViewConfigurationViews", "get views"); + error = XR10.xrEnumerateViewConfigurationViews(this.instance, this.systemID, + XR10.XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, intBuf, views); + logError(error, "xrEnumerateViewConfigurationViews", "get views"); int viewCountNumber = intBuf.get(0); this.viewBuffer = new XrView.Buffer( bufferHeap(viewCountNumber, XrView.SIZEOF, XR10.XR_TYPE_VIEW) ); - //Check swapchain formats - error = XR10.xrEnumerateSwapchainFormats(session, intBuf, null); - logError(error, "xrEnumerateSwapchainFormats", "get count"); + // Check swapchain formats + error = XR10.xrEnumerateSwapchainFormats(this.session, intBuf, null); + logError(error, "xrEnumerateSwapchainFormats", "get count"); - //Get swapchain formats + // Get swapchain formats LongBuffer swapchainFormats = stack.callocLong(intBuf.get(0)); - error = XR10.xrEnumerateSwapchainFormats(session, intBuf, swapchainFormats); - logError(error, "xrEnumerateSwapchainFormats", "get formats"); + error = XR10.xrEnumerateSwapchainFormats(this.session, intBuf, swapchainFormats); + logError(error, "xrEnumerateSwapchainFormats", "get formats"); long[] desiredSwapchainFormats = { - //SRGB formats + // SRGB formats GL21.GL_SRGB8_ALPHA8, GL21.GL_SRGB8, - //others + // others GL11.GL_RGB10_A2, GL30.GL_RGBA16F, GL30.GL_RGB16F, @@ -773,7 +793,7 @@ private void initializeOpenXRSwapChain() { GL31.GL_RGBA8_SNORM, }; - //Choose format + // Choose format long chosenFormat = 0; for (long glFormatIter : desiredSwapchainFormats) { swapchainFormats.rewind(); @@ -797,7 +817,7 @@ private void initializeOpenXRSwapChain() { throw new RuntimeException("No compatible swapchain / framebuffer format available: " + formats); } - //Make swapchain + // Make swapchain XrViewConfigurationView viewConfig = views.get(0); XrSwapchainCreateInfo swapchainCreateInfo = XrSwapchainCreateInfo.calloc(stack); swapchainCreateInfo.type(XR10.XR_TYPE_SWAPCHAIN_CREATE_INFO); @@ -813,9 +833,9 @@ private void initializeOpenXRSwapChain() { swapchainCreateInfo.mipCount(1); PointerBuffer handlePointer = stack.callocPointer(1); - error = XR10.xrCreateSwapchain(session, swapchainCreateInfo, handlePointer); - logError(error, "xrCreateSwapchain", "format: " + chosenFormat); - swapchain = new XrSwapchain(handlePointer.get(0), session); + error = XR10.xrCreateSwapchain(this.session, swapchainCreateInfo, handlePointer); + logError(error, "xrCreateSwapchain", "format: " + chosenFormat); + this.swapchain = new XrSwapchain(handlePointer.get(0), this.session); this.width = swapchainCreateInfo.width(); this.height = swapchainCreateInfo.height(); } @@ -844,7 +864,6 @@ private void initInputAndApplication() { this.loadDefaultBindings(); //this.installApplicationManifest(false); this.inputInitialized = true; - } @Override @@ -859,14 +878,15 @@ public boolean hasCameraTracker() { @Override public List getOrigins(VRInputAction var1) { - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrBoundSourcesForActionEnumerateInfo info = XrBoundSourcesForActionEnumerateInfo.calloc(stack); info.type(XR10.XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO); info.next(NULL); - info.action(new XrAction(var1.handle, new XrActionSet(actionSetHandles.get(var1.actionSet), instance))); + info.action( + new XrAction(var1.handle, new XrActionSet(this.actionSetHandles.get(var1.actionSet), this.instance))); IntBuffer buf = stack.callocInt(1); - int error = XR10.xrEnumerateBoundSourcesForAction(session, info, buf, null); - logError(error, "xrEnumerateBoundSourcesForAction", var1.name); + int error = XR10.xrEnumerateBoundSourcesForAction(this.session, info, buf, null); + logError(error, "xrEnumerateBoundSourcesForAction", var1.name); int size = buf.get(); if (size <= 0) { @@ -875,8 +895,8 @@ public List getOrigins(VRInputAction var1) { buf = stack.callocInt(size); LongBuffer longbuf = stack.callocLong(size); - error = XR10.xrEnumerateBoundSourcesForAction(session, info, buf, longbuf); - logError(error, "xrEnumerateBoundSourcesForAction", var1.name); + error = XR10.xrEnumerateBoundSourcesForAction(this.session, info, buf, longbuf); + logError(error, "xrEnumerateBoundSourcesForAction", var1.name); long[] array; if (longbuf.hasArray()) { //TODO really? array = longbuf.array(); @@ -894,7 +914,7 @@ public List getOrigins(VRInputAction var1) { @Override public String getOriginName(long l) { - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrInputSourceLocalizedNameGetInfo info = XrInputSourceLocalizedNameGetInfo.calloc(stack); info.type(XR10.XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO); info.next(0); @@ -902,8 +922,8 @@ public String getOriginName(long l) { info.whichComponents(XR10.XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT); IntBuffer buf = stack.callocInt(1); - int error = XR10.xrGetInputSourceLocalizedName(session, info, buf, null); - logError(error, "xrGetInputSourceLocalizedName", "get length"); + int error = XR10.xrGetInputSourceLocalizedName(this.session, info, buf, null); + logError(error, "xrGetInputSourceLocalizedName", "get length"); int size = buf.get(); if (size <= 0) { @@ -912,8 +932,8 @@ public String getOriginName(long l) { buf = stack.callocInt(size); ByteBuffer byteBuffer = stack.calloc(size); - error = XR10.xrGetInputSourceLocalizedName(session, info, buf, byteBuffer); - logError(error, "xrGetInputSourceLocalizedName", "get String"); + error = XR10.xrGetInputSourceLocalizedName(this.session, info, buf, byteBuffer); + logError(error, "xrGetInputSourceLocalizedName", "get String"); return new String(byteBuffer.array()); } } @@ -926,12 +946,12 @@ public VRRenderer createVRRenderer() { @Override public boolean isActive() { this.pollVREvents(); - return isActive; + return this.isActive; } @Override public ControllerType getOriginControllerType(long i) { - if (i == aim[RIGHT_CONTROLLER]) { + if (i == this.aim[RIGHT_CONTROLLER]) { return ControllerType.RIGHT; } return ControllerType.LEFT; @@ -947,43 +967,50 @@ public String getRuntimeName() { return "OpenXR"; } - private static final String[] BOTH_HANDS = new String[] {"/user/hand/left", "/user/hand/right"}; + private static final String[] BOTH_HANDS = new String[]{"/user/hand/left", "/user/hand/right"}; //TODO Collect and register all actions private void loadActionHandles() { for (VRInputActionSet vrinputactionset : VRInputActionSet.values()) { - long actionSet = makeActionSet(instance, vrinputactionset.name, vrinputactionset.localizedName, 0); + long actionSet = makeActionSet(this.instance, vrinputactionset.name, vrinputactionset.localizedName, 0); this.actionSetHandles.put(vrinputactionset, actionSet); } for (VRInputAction vrinputaction : this.inputActions.values()) { - long action = createAction(vrinputaction.name, vrinputaction.name, vrinputaction.type, new XrActionSet(this.actionSetHandles.get(vrinputaction.actionSet), instance), BOTH_HANDS); + long action = createAction(vrinputaction.name, vrinputaction.name, vrinputaction.type, + new XrActionSet(this.actionSetHandles.get(vrinputaction.actionSet), this.instance), BOTH_HANDS); vrinputaction.setHandle(action); } setupControllers(); - XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.haptics[RIGHT_CONTROLLER] = createAction("/actions/global/out/righthaptic", "/actions/global/out/righthaptic", "haptic", actionSet, BOTH_HANDS); - this.haptics[LEFT_CONTROLLER] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", "haptic", actionSet, BOTH_HANDS); - + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), this.instance); + this.haptics[RIGHT_CONTROLLER] = createAction("/actions/global/out/righthaptic", + "/actions/global/out/righthaptic", "haptic", actionSet, BOTH_HANDS); + this.haptics[LEFT_CONTROLLER] = createAction("/actions/global/out/lefthaptic", "/actions/global/out/lefthaptic", + "haptic", actionSet, BOTH_HANDS); } private void setupControllers() { - XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); - this.grip[RIGHT_CONTROLLER] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", "pose", actionSet, BOTH_HANDS); - this.grip[LEFT_CONTROLLER] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", actionSet, BOTH_HANDS); - this.aim[RIGHT_CONTROLLER] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", "pose", actionSet, BOTH_HANDS); - this.aim[LEFT_CONTROLLER] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", "pose", actionSet, BOTH_HANDS); + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), this.instance); + this.grip[RIGHT_CONTROLLER] = createAction("/actions/global/in/righthand", "/actions/global/in/righthand", + "pose", actionSet, BOTH_HANDS); + this.grip[LEFT_CONTROLLER] = createAction("/actions/global/in/lefthand", "/actions/global/in/lefthand", "pose", + actionSet, BOTH_HANDS); + this.aim[RIGHT_CONTROLLER] = createAction("/actions/global/in/righthandaim", "/actions/global/in/righthandaim", + "pose", actionSet, BOTH_HANDS); + this.aim[LEFT_CONTROLLER] = createAction("/actions/global/in/lefthandaim", "/actions/global/in/lefthandaim", + "pose", actionSet, BOTH_HANDS); } private void loadDefaultBindings() { try (MemoryStack stack = MemoryStack.stackPush()) { int error; - for (String headset: XRBindings.supportedHeadsets()) { + for (String headset : XRBindings.supportedHeadsets()) { VRSettings.LOGGER.info("loading defaults for {}", headset); Pair[] defaultBindings = XRBindings.getBinding(headset).toArray(new Pair[0]); - XrActionSuggestedBinding.Buffer bindings = XrActionSuggestedBinding.calloc(defaultBindings.length + 6, stack); //TODO different way of adding controller poses + XrActionSuggestedBinding.Buffer bindings = XrActionSuggestedBinding.calloc(defaultBindings.length + 6, + stack); //TODO different way of adding controller poses for (int i = 0; i < defaultBindings.length; i++) { Pair pair = defaultBindings[i]; @@ -993,13 +1020,15 @@ private void loadDefaultBindings() { continue; } bindings.get(i).set( - new XrAction(binding.handle, new XrActionSet(actionSetHandles.get(binding.actionSet), instance)), + new XrAction(binding.handle, + new XrActionSet(this.actionSetHandles.get(binding.actionSet), this.instance)), getPath(pair.getRight()) ); } //TODO make this also changeable? - XrActionSet actionSet = new XrActionSet(actionSetHandles.get(VRInputActionSet.GLOBAL), instance); + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), + this.instance); bindings.get(defaultBindings.length).set( new XrAction(this.grip[RIGHT_CONTROLLER], actionSet), getPath("/user/hand/right/input/grip/pose") @@ -1027,55 +1056,56 @@ private void loadDefaultBindings() { getPath("/user/hand/left/output/haptic") ); - XrInteractionProfileSuggestedBinding suggested_binds = XrInteractionProfileSuggestedBinding.calloc(stack); + XrInteractionProfileSuggestedBinding suggested_binds = XrInteractionProfileSuggestedBinding.calloc( + stack); suggested_binds.type(XR10.XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING); suggested_binds.next(NULL); suggested_binds.interactionProfile(getPath(headset)); suggested_binds.suggestedBindings(bindings); - error = XR10.xrSuggestInteractionProfileBindings(instance, suggested_binds); - logError(error, "xrSuggestInteractionProfileBindings", headset); + error = XR10.xrSuggestInteractionProfileBindings(this.instance, suggested_binds); + logError(error, "xrSuggestInteractionProfileBindings", headset); } XrSessionActionSetsAttachInfo attach_info = XrSessionActionSetsAttachInfo.calloc(stack); attach_info.type(XR10.XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO); attach_info.next(NULL); - attach_info.actionSets(stackPointers(actionSetHandles.values().stream().mapToLong(value -> value).toArray())); + attach_info.actionSets( + stackPointers(this.actionSetHandles.values().stream().mapToLong(value -> value).toArray())); - error = XR10.xrAttachSessionActionSets(session, attach_info); - logError(error, "xrAttachSessionActionSets", ""); + error = XR10.xrAttachSessionActionSets(this.session, attach_info); + logError(error, "xrAttachSessionActionSets", ""); - XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), instance); + XrActionSet actionSet = new XrActionSet(this.actionSetHandles.get(VRInputActionSet.GLOBAL), this.instance); XrActionSpaceCreateInfo actionSpace = XrActionSpaceCreateInfo.calloc(stack); actionSpace.type(XR10.XR_TYPE_ACTION_SPACE_CREATE_INFO); actionSpace.next(NULL); - actionSpace.action(new XrAction(grip[RIGHT_CONTROLLER], actionSet)); + actionSpace.action(new XrAction(this.grip[RIGHT_CONTROLLER], actionSet)); actionSpace.subactionPath(getPath("/user/hand/right")); actionSpace.poseInActionSpace(POSE_IDENTITY); PointerBuffer pp = stackCallocPointer(1); - error = XR10.xrCreateActionSpace(session, actionSpace, pp); - logError(error, "xrCreateActionSpace", "grip: /user/hand/right"); - this.gripSpace[RIGHT_CONTROLLER] = new XrSpace(pp.get(0), session); + error = XR10.xrCreateActionSpace(this.session, actionSpace, pp); + logError(error, "xrCreateActionSpace", "grip: /user/hand/right"); + this.gripSpace[RIGHT_CONTROLLER] = new XrSpace(pp.get(0), this.session); - actionSpace.action(new XrAction(grip[LEFT_CONTROLLER], actionSet)); + actionSpace.action(new XrAction(this.grip[LEFT_CONTROLLER], actionSet)); actionSpace.subactionPath(getPath("/user/hand/left")); - error = XR10.xrCreateActionSpace(session, actionSpace, pp); - logError(error, "xrCreateActionSpace", "grip: /user/hand/left"); - this.gripSpace[LEFT_CONTROLLER] = new XrSpace(pp.get(0), session); + error = XR10.xrCreateActionSpace(this.session, actionSpace, pp); + logError(error, "xrCreateActionSpace", "grip: /user/hand/left"); + this.gripSpace[LEFT_CONTROLLER] = new XrSpace(pp.get(0), this.session); - actionSpace.action(new XrAction(aim[RIGHT_CONTROLLER], actionSet)); + actionSpace.action(new XrAction(this.aim[RIGHT_CONTROLLER], actionSet)); actionSpace.subactionPath(getPath("/user/hand/right")); error = XR10.xrCreateActionSpace(session, actionSpace, pp); - logError(error, "xrCreateActionSpace", "aim: /user/hand/right"); - this.aimSpace[RIGHT_CONTROLLER] = new XrSpace(pp.get(0), session); + logError(error, "xrCreateActionSpace", "aim: /user/hand/right"); + this.aimSpace[RIGHT_CONTROLLER] = new XrSpace(pp.get(0), this.session); - actionSpace.action(new XrAction(aim[LEFT_CONTROLLER], actionSet)); + actionSpace.action(new XrAction(this.aim[LEFT_CONTROLLER], actionSet)); actionSpace.subactionPath(getPath("/user/hand/left")); - error = XR10.xrCreateActionSpace(session, actionSpace, pp); - logError(error, "xrCreateActionSpace", "aim: /user/hand/left"); - this.aimSpace[LEFT_CONTROLLER] = new XrSpace(pp.get(0), session); - + error = XR10.xrCreateActionSpace(this.session, actionSpace, pp); + logError(error, "xrCreateActionSpace", "aim: /user/hand/left"); + this.aimSpace[LEFT_CONTROLLER] = new XrSpace(pp.get(0), this.session); } } @@ -1083,16 +1113,18 @@ public long getPath(String pathString) { return this.paths.computeIfAbsent(pathString, s -> { try (MemoryStack ignored = stackPush()) { LongBuffer buf = stackCallocLong(1); - int error = XR10.xrStringToPath(instance, pathString, buf); - logError(error, "getPath", pathString); + int error = XR10.xrStringToPath(this.instance, pathString, buf); + logError(error, "getPath", pathString); return buf.get(); } }); } - private long createAction(String name, String localisedName, String type, XrActionSet actionSet, @Nullable String[] subactionPaths) { - try (MemoryStack stack = MemoryStack.stackPush()){ - String s = name.split("/")[name.split("/").length -1].toLowerCase(); + private long createAction( + String name, String localisedName, String type, XrActionSet actionSet, @Nullable String[] subactionPaths) + { + try (MemoryStack stack = MemoryStack.stackPush()) { + String s = name.split("/")[name.split("/").length - 1].toLowerCase(); XrActionCreateInfo hands = XrActionCreateInfo.calloc(stack); hands.type(XR10.XR_TYPE_ACTION_CREATE_INFO); hands.next(NULL); @@ -1104,9 +1136,9 @@ private long createAction(String name, String localisedName, String type, XrActi case "pose" -> hands.actionType(XR10.XR_ACTION_TYPE_POSE_INPUT); case "haptic" -> hands.actionType(XR10.XR_ACTION_TYPE_VIBRATION_OUTPUT); } - if(subactionPaths != null) { + if (subactionPaths != null) { LongBuffer buffer = stackCallocLong(subactionPaths.length); - for(String path : subactionPaths) { + for (String path : subactionPaths) { buffer.put(getPath(path)); } hands.countSubactionPaths(subactionPaths.length); @@ -1119,13 +1151,13 @@ private long createAction(String name, String localisedName, String type, XrActi PointerBuffer buffer = stackCallocPointer(1); int error = XR10.xrCreateAction(actionSet, hands, buffer); - logError(error, "xrCreateAction", "name:", name, "type:", type); + logError(error, "xrCreateAction", "name:", name, "type:", type); return buffer.get(0); } } private long makeActionSet(XrInstance instance, String name, String localisedName, int priority) { - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { XrActionSetCreateInfo info = XrActionSetCreateInfo.calloc(stack); info.type(XR10.XR_TYPE_ACTION_SET_CREATE_INFO); info.next(NULL); @@ -1217,7 +1249,7 @@ private String getResultName(int xrResult) { try (MemoryStack stack = MemoryStack.stackPush()) { ByteBuffer str = stack.calloc(XR10.XR_MAX_RESULT_STRING_SIZE); - if (XR10.xrResultToString(instance, xrResult, str) == XR10.XR_SUCCESS) { + if (XR10.xrResultToString(this.instance, xrResult, str) == XR10.XR_SUCCESS) { resultString = (memUTF8(memAddress(str))); } else { resultString = "Unknown Error: " + xrResult; @@ -1229,9 +1261,10 @@ private String getResultName(int xrResult) { /** * logs only errors + * * @param xrResult result to check - * @param caller where the xrResult came from - * @param args arguments may be helpful in locating the error + * @param caller where the xrResult came from + * @param args arguments may be helpful in locating the error */ protected void logError(int xrResult, String caller, String... args) { if (xrResult < 0) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index 3cebe96cc..a11e9201b 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -33,19 +33,21 @@ public OpenXRStereoRenderer(MCOpenXR vr) { } @Override - public void createRenderTexture(int width, int height) throws RenderConfigException{ + public void createRenderTexture(int width, int height) throws RenderConfigException { try (MemoryStack stack = MemoryStack.stackPush()) { //Get amount of views in the swapchain IntBuffer intBuffer = stack.ints(0); //Set value to 0 - int error = XR10.xrEnumerateSwapchainImages(openxr.swapchain, intBuffer, null); + int error = XR10.xrEnumerateSwapchainImages(this.openxr.swapchain, intBuffer, null); this.openxr.logError(error, "xrEnumerateSwapchainImages", "get count"); //Now we know the amount, create the image buffer int imageCount = intBuffer.get(0); - XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = this.openxr.device.createImageBuffers(imageCount, stack); + XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = this.openxr.device.createImageBuffers(imageCount, + stack); - error = XR10.xrEnumerateSwapchainImages(openxr.swapchain, intBuffer, XrSwapchainImageBaseHeader.create(swapchainImageBuffer.address(), swapchainImageBuffer.capacity())); + error = XR10.xrEnumerateSwapchainImages(this.openxr.swapchain, intBuffer, + XrSwapchainImageBaseHeader.create(swapchainImageBuffer.address(), swapchainImageBuffer.capacity())); this.openxr.logError(error, "xrEnumerateSwapchainImages", "get images"); this.leftFramebuffers = new VRTextureTarget[imageCount]; @@ -53,36 +55,38 @@ public void createRenderTexture(int width, int height) throws RenderConfigExcept for (int i = 0; i < imageCount; i++) { XrSwapchainImageOpenGLKHR openxrImage = swapchainImageBuffer.get(i); - leftFramebuffers[i] = new VRTextureTarget("L Eye " + i, width, height, openxrImage.image(), 0); + this.leftFramebuffers[i] = new VRTextureTarget("L Eye " + i, width, height, openxrImage.image(), 0); RenderHelper.checkGLError("Left Eye framebuffer setup"); - rightFramebuffers[i] = new VRTextureTarget("R Eye " + i, width, height, openxrImage.image(), 1); + this.rightFramebuffers[i] = new VRTextureTarget("R Eye " + i, width, height, openxrImage.image(), 1); RenderHelper.checkGLError("Right Eye framebuffer setup"); } - this.rightFramebuffer = new VRTextureTarget("R Eye mirror", width, height, true, -1, true, true, ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); - this.leftFramebuffer = new VRTextureTarget("L Eye mirror", width, height, true, -1, true, true, ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); + this.rightFramebuffer = new VRTextureTarget("R Eye mirror", width, height, true, -1, true, true, + ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); + this.leftFramebuffer = new VRTextureTarget("L Eye mirror", width, height, true, -1, true, true, + ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); } } @Override public void setupRenderConfiguration(boolean render) throws IOException, RenderConfigException { super.setupRenderConfiguration(render); - + if (!render) { return; } this.projectionLayerViews = XrCompositionLayerProjectionView.calloc(2); - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { IntBuffer intBuf2 = stack.callocInt(1); int error = XR10.xrAcquireSwapchainImage( - openxr.swapchain, + this.openxr.swapchain, XrSwapchainImageAcquireInfo.calloc(stack).type(XR10.XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO), intBuf2); this.openxr.logError(error, "xrAcquireSwapchainImage", ""); - error = XR10.xrWaitSwapchainImage(openxr.swapchain, + error = XR10.xrWaitSwapchainImage(this.openxr.swapchain, XrSwapchainImageWaitInfo.calloc(stack) .type(XR10.XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO) .timeout(XR10.XR_INFINITE_DURATION)); @@ -93,67 +97,71 @@ public void setupRenderConfiguration(boolean render) throws IOException, RenderC // Render view to the appropriate part of the swapchain image. for (int viewIndex = 0; viewIndex < 2; viewIndex++) { - var subImage = projectionLayerViews.get(viewIndex) + var subImage = this.projectionLayerViews.get(viewIndex) .type(XR10.XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) - .pose(openxr.viewBuffer.get(viewIndex).pose()) - .fov(openxr.viewBuffer.get(viewIndex).fov()) + .pose(this.openxr.viewBuffer.get(viewIndex).pose()) + .fov(this.openxr.viewBuffer.get(viewIndex).fov()) .subImage(); - subImage.swapchain(openxr.swapchain); + subImage.swapchain(this.openxr.swapchain); subImage.imageRect().offset().set(0, 0); - subImage.imageRect().extent().set(openxr.width, openxr.height); + subImage.imageRect().extent().set(this.openxr.width, this.openxr.height); subImage.imageArrayIndex(viewIndex); - } } } @Override public Matrix4f getProjectionMatrix(int eyeType, float nearClip, float farClip) { - XrFovf fov = openxr.viewBuffer.get(eyeType).fov(); - return new Matrix4f().setPerspectiveOffCenterFov(fov.angleLeft(), fov.angleRight(), fov.angleDown(), fov.angleUp(), nearClip, farClip); + XrFovf fov = this.openxr.viewBuffer.get(eyeType).fov(); + return new Matrix4f().setPerspectiveOffCenterFov(fov.angleLeft(), fov.angleRight(), fov.angleDown(), + fov.angleUp(), nearClip, farClip); } @Override public void endFrame() throws RenderConfigException { GL31.glBindFramebuffer(GL31.GL_READ_FRAMEBUFFER, getLeftEyeTarget().frameBufferId); - GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, leftFramebuffers[swapIndex].frameBufferId); - GL31.glBlitFramebuffer(0,0, getLeftEyeTarget().viewWidth, getLeftEyeTarget().viewHeight, 0,0, leftFramebuffers[swapIndex].viewWidth, leftFramebuffers[swapIndex].viewHeight, GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); + GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, this.leftFramebuffers[this.swapIndex].frameBufferId); + GL31.glBlitFramebuffer(0, 0, getLeftEyeTarget().viewWidth, getLeftEyeTarget().viewHeight, 0, 0, + this.leftFramebuffers[this.swapIndex].viewWidth, this.leftFramebuffers[this.swapIndex].viewHeight, + GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); GL31.glBindFramebuffer(GL31.GL_READ_FRAMEBUFFER, getRightEyeTarget().frameBufferId); - GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, rightFramebuffers[swapIndex].frameBufferId); - GL31.glBlitFramebuffer(0,0, getRightEyeTarget().viewWidth, getRightEyeTarget().viewHeight, 0,0, rightFramebuffers[swapIndex].viewWidth, rightFramebuffers[swapIndex].viewHeight, GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); + GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, this.rightFramebuffers[this.swapIndex].frameBufferId); + GL31.glBlitFramebuffer(0, 0, getRightEyeTarget().viewWidth, getRightEyeTarget().viewHeight, 0, 0, + this.rightFramebuffers[this.swapIndex].viewWidth, this.rightFramebuffers[this.swapIndex].viewHeight, + GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); - try (MemoryStack stack = MemoryStack.stackPush()){ + try (MemoryStack stack = MemoryStack.stackPush()) { PointerBuffer layers = stack.callocPointer(1); int error; error = XR10.xrReleaseSwapchainImage( - openxr.swapchain, + this.openxr.swapchain, XrSwapchainImageReleaseInfo.calloc(stack) .type(XR10.XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO)); this.openxr.logError(error, "xrReleaseSwapchainImage", ""); XrCompositionLayerProjection compositionLayerProjection = XrCompositionLayerProjection.calloc(stack) .type(XR10.XR_TYPE_COMPOSITION_LAYER_PROJECTION) - .space(openxr.xrAppSpace) - .views(projectionLayerViews); + .space(this.openxr.xrAppSpace) + .views(this.projectionLayerViews); layers.put(compositionLayerProjection); layers.flip(); error = XR10.xrEndFrame( - openxr.session, + this.openxr.session, XrFrameEndInfo.calloc(stack) .type(XR10.XR_TYPE_FRAME_END_INFO) - .displayTime(openxr.time) + .displayTime(this.openxr.time) .environmentBlendMode(XR10.XR_ENVIRONMENT_BLEND_MODE_OPAQUE) .layers(layers)); this.openxr.logError(error, "xrEndFrame", ""); - projectionLayerViews.close(); + this.projectionLayerViews.close(); } } @@ -164,12 +172,12 @@ public boolean providesStencilMask() { @Override public RenderTarget getLeftEyeTarget() { - return leftFramebuffer; + return this.leftFramebuffer; } @Override public RenderTarget getRightEyeTarget() { - return rightFramebuffer; + return this.rightFramebuffer; } @Override @@ -179,6 +187,6 @@ public String getName() { @Override public Tuple getRenderTextureSizes() { - return new Tuple<>(openxr.width, openxr.height); + return new Tuple<>(this.openxr.width, this.openxr.height); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java index ebc94576f..eaa865b2a 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRUtil.java @@ -8,9 +8,10 @@ public class OpenXRUtil { public static void openXRPoseToMarix(XrPosef pose, Matrix4f mat) { - mat.set(new Quaternionf(pose.orientation().x(), pose.orientation().y(), pose.orientation().z(), pose.orientation().w())) - .setTranslation(pose.position$().x(), pose.position$().y(), pose.position$().z()) - .m33(1); + mat.set(new Quaternionf(pose.orientation().x(), pose.orientation().y(), pose.orientation().z(), + pose.orientation().w())) + .setTranslation(pose.position$().x(), pose.position$().y(), pose.position$().z()) + .m33(1); } public static void openXRPoseToMarix(XrQuaternionf quat, Matrix4f mat) { diff --git a/fabric/build.gradle b/fabric/build.gradle index 11a5c477d..711a531fc 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -71,7 +71,7 @@ dependencies { // Use custom OpenXR lib for Android and GLES bindings //include(implementation("QuestCraftPlusPlus:lwjgl3:${rootProject.lwjgl_version}:lwjgl-openxr-${rootProject.lwjgl_version}")) - include(implementation("org.lwjgl:lwjgl-openxr:3.3.3")) + include(implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}")) include(implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-windows")) include(implementation("org.lwjgl:lwjgl-openxr:${rootProject.lwjgl_version}:natives-linux")) From d6205e0cd4942f5360d21d0ed17679dd49d2a096 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 8 Jan 2025 02:36:05 +0100 Subject: [PATCH 17/27] fix binding origin name getting --- .../java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index f3d2ab1c1..f2eca05c9 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -14,6 +14,7 @@ import org.lwjgl.opengl.GL31; import org.lwjgl.openxr.*; import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; import org.vivecraft.client.VivecraftVRMod; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; @@ -934,7 +935,7 @@ public String getOriginName(long l) { ByteBuffer byteBuffer = stack.calloc(size); error = XR10.xrGetInputSourceLocalizedName(this.session, info, buf, byteBuffer); logError(error, "xrGetInputSourceLocalizedName", "get String"); - return new String(byteBuffer.array()); + return MemoryUtil.memUTF8(MemoryUtil.memAddress(buf)); } } From 1a8ea30ad4dfa3298ce08724a97d3171d76d5bab Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 8 Jan 2025 03:35:27 +0100 Subject: [PATCH 18/27] change mirror to use framebuffer blits and openvr/nullvr fixes --- .../extensions/RenderTargetExtension.java | 6 - .../vivecraft/client_vr/VRTextureTarget.java | 26 +++- .../client_vr/provider/VRRenderer.java | 23 ++-- .../provider/nullvr/NullVRStereoRenderer.java | 58 ++++++--- .../openvr_lwjgl/OpenVRStereoRenderer.java | 76 ++++++----- .../provider/openxr/OpenXRStereoRenderer.java | 74 ++++++----- .../vivecraft/client_vr/render/VRShaders.java | 5 - .../render/helpers/ShaderHelper.java | 119 +++++++++--------- .../render/helpers/VRPassHelper.java | 10 +- .../client/blaze3d/RenderTargetMixin.java | 7 -- .../mixin/client_vr/MinecraftVRMixin.java | 11 -- .../assets/vivecraft/shaders/core/blit_vr.fsh | 11 -- .../vivecraft/shaders/core/blit_vr.json | 10 -- .../shaders/core/mixedreality_vr.fsh | 5 - 14 files changed, 218 insertions(+), 223 deletions(-) delete mode 100644 common/src/main/resources/assets/vivecraft/shaders/core/blit_vr.fsh delete mode 100644 common/src/main/resources/assets/vivecraft/shaders/core/blit_vr.json diff --git a/common/src/main/java/org/vivecraft/client/extensions/RenderTargetExtension.java b/common/src/main/java/org/vivecraft/client/extensions/RenderTargetExtension.java index 7d9e0645d..5bea9454b 100644 --- a/common/src/main/java/org/vivecraft/client/extensions/RenderTargetExtension.java +++ b/common/src/main/java/org/vivecraft/client/extensions/RenderTargetExtension.java @@ -39,10 +39,4 @@ public interface RenderTargetExtension { * @return if the RenderTarget is set to use mipmaps */ boolean vivecraft$hasMipmaps(); - - /** - * Sets the color id - * @param colorid the color id to set - */ - void vivecraft$setColorid(int colorid); } diff --git a/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java b/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java index 3cb8fe5f3..5b99d1586 100644 --- a/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java +++ b/common/src/main/java/org/vivecraft/client_vr/VRTextureTarget.java @@ -2,8 +2,8 @@ import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.platform.TextureUtil; import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.Minecraft; import org.lwjgl.opengl.GL30; import org.vivecraft.client.Xplat; import org.vivecraft.client.extensions.RenderTargetExtension; @@ -39,14 +39,28 @@ public VRTextureTarget( this.setClearColor(0, 0, 0, 0); } - public VRTextureTarget(String name, int width, int height, int colorid, int index) { - super(true); + public VRTextureTarget(String name, int width, int height, int colorId, int index) { + super(false); this.name = name; RenderSystem.assertOnRenderThreadOrInit(); this.resize(width, height); - ((RenderTargetExtension) this).vivecraft$setColorid(colorid); - GlStateManager._glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferId); - GL30.glFramebufferTextureLayer(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, colorid, 0, index); + + // free the old one when setting a new one + if (this.colorTextureId != -1) { + TextureUtil.releaseTextureId(this.colorTextureId); + } + this.colorTextureId = colorId; + + GlStateManager._glBindFramebuffer(GL30.GL_FRAMEBUFFER, this.frameBufferId); + // unset the old GL_COLOR_ATTACHMENT0 + GlStateManager._glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL30.GL_TEXTURE_2D, 0, + 0); + GL30.glFramebufferTextureLayer(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, colorId, 0, index); + + // unbind the framebuffer + this.unbindRead(); + this.unbindWrite(); + this.setClearColor(0, 0, 0, 0); } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java index 30c7eaa75..f2e366b47 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/VRRenderer.java @@ -25,7 +25,6 @@ import org.vivecraft.client.utils.TextUtils; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRTextureTarget; -import org.vivecraft.client_vr.extensions.GameRendererExtension; import org.vivecraft.client_vr.extensions.WindowExtension; import org.vivecraft.client_vr.gameplay.screenhandlers.GuiHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; @@ -54,8 +53,8 @@ public abstract class VRRenderer { private float lastFarClip = 0F; // render buffers - protected int LeftEyeTextureId = -1; - protected int RightEyeTextureId = -1; + protected boolean eyeFramebuffersCreated = false; + public RenderTarget framebufferMR; public RenderTarget framebufferUndistorted; public RenderTarget framebufferVrRender; @@ -100,7 +99,7 @@ public VRRenderer(MCVR vr) { * @param width width of the texture * @param height height of the texture */ - public abstract void createRenderTexture(int width, int height) throws RenderConfigException; + public abstract void createRenderTexture(int width, int height); /** * gets the cached projection matrix if the farClip distance matches with the last, else gets a new one from the VR runtime @@ -607,10 +606,6 @@ public void setupRenderConfiguration(boolean render) throws RenderConfigExceptio this.resizeFrameBuffers = false; } - //for OPENXR, it needs to reinit - this.eyeProj[0] = this.getProjectionMatrix(0, ((GameRendererExtension) minecraft.gameRenderer).vivecraft$getMinClipDistance(), lastFarClip); - this.eyeProj[1] = this.getProjectionMatrix(1, ((GameRendererExtension) minecraft.gameRenderer).vivecraft$getMinClipDistance(), lastFarClip); - if (this.reinitFrameBuffers) { RenderHelper.checkGLError("Start Init"); @@ -657,7 +652,17 @@ public void setupRenderConfiguration(boolean render) throws RenderConfigExceptio destroyBuffers(); - this.createRenderTexture(eyew, eyeh); + if (!this.eyeFramebuffersCreated) { + VRSettings.LOGGER.info("Vivecraft: VR Provider supplied texture resolution: {} x {}", eyew, eyeh); + this.createRenderTexture(eyew, eyeh); + + if (!this.getLastError().isEmpty()) { + throw new RenderConfigException( + Component.translatable("vivecraft.messages.renderiniterror", this.getName()), + Component.literal(this.getLastError())); + } + this.eyeFramebuffersCreated = true; + } float resolutionScale = ResolutionControlHelper.isLoaded() ? ResolutionControlHelper.getCurrentScaleFactor() : 1.0F; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVRStereoRenderer.java index d71ebabca..90e0107ca 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVRStereoRenderer.java @@ -8,9 +8,9 @@ import net.minecraft.util.Tuple; import org.joml.Matrix4f; import org.lwjgl.opengl.GL11; +import org.vivecraft.client_vr.VRTextureTarget; import org.vivecraft.client_vr.provider.MCVR; import org.vivecraft.client_vr.provider.VRRenderer; -import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.render.RenderPass; import org.vivecraft.client_vr.render.helpers.RenderHelper; import org.vivecraft.client_vr.settings.VRSettings; @@ -19,8 +19,8 @@ public class NullVRStereoRenderer extends VRRenderer { protected int LeftEyeTextureId = -1; protected int RightEyeTextureId = -1; - public RenderTarget framebufferEye0; - public RenderTarget framebufferEye1; + public RenderTarget framebufferEyeLeft; + public RenderTarget framebufferEyeRight; public NullVRStereoRenderer(MCVR vr) { super(vr); @@ -44,25 +44,44 @@ protected Matrix4f getProjectionMatrix(int eyeType, float nearClip, float farCli } @Override - public void createRenderTexture(int lwidth, int lheight) throws RenderConfigException { + public void createRenderTexture(int width, int height) { + int boundTextureId = GlStateManager._getInteger(GL11.GL_TEXTURE_BINDING_2D); + this.LeftEyeTextureId = GlStateManager._genTexture(); - int i = GlStateManager._getInteger(GL11.GL_TEXTURE_BINDING_2D); RenderSystem.bindTexture(this.LeftEyeTextureId); RenderSystem.texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); RenderSystem.texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); - GlStateManager._texImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, lwidth, lheight, 0, GL11.GL_RGBA, GL11.GL_INT, + GlStateManager._texImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL11.GL_RGBA, GL11.GL_INT, null); - RenderSystem.bindTexture(i); this.RightEyeTextureId = GlStateManager._genTexture(); - i = GlStateManager._getInteger(GL11.GL_TEXTURE_BINDING_2D); RenderSystem.bindTexture(this.RightEyeTextureId); RenderSystem.texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); RenderSystem.texParameter(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); - GlStateManager._texImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, lwidth, lheight, 0, GL11.GL_RGBA, GL11.GL_INT, + GlStateManager._texImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL11.GL_RGBA, GL11.GL_INT, null); - RenderSystem.bindTexture(i); + this.lastError = RenderHelper.checkGLError("create VR textures"); + + this.framebufferEyeLeft = new VRTextureTarget("L Eye", width, height, false, this.LeftEyeTextureId, true, false, + false); + + VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEyeLeft); + + String leftError = RenderHelper.checkGLError("Left Eye framebuffer setup"); + + this.framebufferEyeRight = new VRTextureTarget("R Eye", width, height, false, this.RightEyeTextureId, true, false, + false); + + VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEyeRight); + + String rightError = RenderHelper.checkGLError("Right Eye framebuffer setup"); + + if (this.lastError.isEmpty()) { + this.lastError = !leftError.isEmpty() ? leftError : rightError; + } + + RenderSystem.bindTexture(boundTextureId); } @Override @@ -75,12 +94,12 @@ public boolean providesStencilMask() { @Override public RenderTarget getLeftEyeTarget() { - return framebufferEye0; + return this.framebufferEyeLeft; } @Override public RenderTarget getRightEyeTarget() { - return framebufferEye1; + return this.framebufferEyeRight; } @@ -95,17 +114,18 @@ public String getName() { } @Override - protected void destroyBuffers() { + public void destroy() { super.destroyBuffers(); + super.destroy(); - if (this.framebufferEye0 != null) { - this.framebufferEye0.destroyBuffers(); - this.framebufferEye0 = null; + if (this.framebufferEyeLeft != null) { + this.framebufferEyeLeft.destroyBuffers(); + this.framebufferEyeLeft = null; } - if (this.framebufferEye1 != null) { - this.framebufferEye1.destroyBuffers(); - this.framebufferEye1 = null; + if (this.framebufferEyeRight != null) { + this.framebufferEyeRight.destroyBuffers(); + this.framebufferEyeRight = null; } if (this.LeftEyeTextureId > -1) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java index a946f1f90..1aa30a1ba 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/OpenVRStereoRenderer.java @@ -29,8 +29,8 @@ public class OpenVRStereoRenderer extends VRRenderer { private final MCOpenVR openvr; protected int LeftEyeTextureId = -1; protected int RightEyeTextureId = -1; - public RenderTarget framebufferEye0; - public RenderTarget framebufferEye1; + public RenderTarget framebufferEyeLeft; + public RenderTarget framebufferEyeRight; public OpenVRStereoRenderer(MCOpenVR vr) { super(vr); @@ -97,8 +97,9 @@ protected Matrix4f getProjectionMatrix(int eyeType, float nearClip, float farCli } @Override - public void createRenderTexture(int width, int height) throws RenderConfigException { + public void createRenderTexture(int width, int height) { int boundTextureId = GlStateManager._getInteger(GL11C.GL_TEXTURE_BINDING_2D); + // generate left eye texture this.LeftEyeTextureId = GlStateManager._genTexture(); RenderSystem.bindTexture(this.LeftEyeTextureId); @@ -121,33 +122,31 @@ public void createRenderTexture(int width, int height) throws RenderConfigExcept this.openvr.texType1.eColorSpace(VR.EColorSpace_ColorSpace_Gamma); this.openvr.texType1.eType(VR.ETextureType_TextureType_OpenGL); - if (this.LeftEyeTextureId == -1) { - throw new RenderConfigException( - Component.translatable("vivecraft.messages.renderiniterror", this.getName()), - Component.literal(this.getLastError())); - } - VRSettings.LOGGER.info("Vivecraft: VR Provider supplied render texture IDs: {}, {}", this.LeftEyeTextureId, this.RightEyeTextureId); - VRSettings.LOGGER.info("Vivecraft: VR Provider supplied texture resolution: {} x {}", width, height); - RenderHelper.checkGLError("Render Texture setup"); + this.lastError = RenderHelper.checkGLError("create VR textures"); - if (this.framebufferEye0 == null) { - this.framebufferEye0 = new VRTextureTarget("L Eye", width, height, false, this.LeftEyeTextureId, false, - true, false); - VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEye0); - RenderHelper.checkGLError("Left Eye framebuffer setup"); - } + this.framebufferEyeLeft = new VRTextureTarget("L Eye", width, height, false, this.LeftEyeTextureId, true, false, + false); + + VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEyeLeft); + + String leftError = RenderHelper.checkGLError("Left Eye framebuffer setup"); - if (this.framebufferEye1 == null) { - this.framebufferEye1 = new VRTextureTarget("R Eye", width, height, false, this.RightEyeTextureId, false, - true, false); - VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEye1); - RenderHelper.checkGLError("Right Eye framebuffer setup"); + this.framebufferEyeRight = new VRTextureTarget("R Eye", width, height, false, this.RightEyeTextureId, true, + false, + false); + + VRSettings.LOGGER.info("Vivecraft: {}", this.framebufferEyeRight); + + String rightError = RenderHelper.checkGLError("Right Eye framebuffer setup"); + + if (this.lastError.isEmpty()) { + this.lastError = !leftError.isEmpty() ? leftError : rightError; } + RenderSystem.bindTexture(boundTextureId); - this.lastError = RenderHelper.checkGLError("create VR textures"); } @Override @@ -195,12 +194,12 @@ public boolean providesStencilMask() { @Override public RenderTarget getLeftEyeTarget() { - return framebufferEye0; + return this.framebufferEyeLeft; } @Override public RenderTarget getRightEyeTarget() { - return framebufferEye1; + return this.framebufferEyeRight; } public float[] getStencilMask(RenderPass eye) { @@ -216,16 +215,20 @@ public String getName() { } @Override - protected void destroyBuffers() { - super.destroyBuffers(); - if (this.framebufferEye0 != null) { - this.framebufferEye0.destroyBuffers(); - this.framebufferEye0 = null; + public void destroy() { + super.destroy(); + + this.hiddenMeshes[0].free(); + this.hiddenMeshes[1].free(); + + if (this.framebufferEyeLeft != null) { + this.framebufferEyeLeft.destroyBuffers(); + this.framebufferEyeLeft = null; } - if (this.framebufferEye1 != null) { - this.framebufferEye1.destroyBuffers(); - this.framebufferEye1 = null; + if (this.framebufferEyeRight != null) { + this.framebufferEyeRight.destroyBuffers(); + this.framebufferEyeRight = null; } if (this.LeftEyeTextureId > -1) { TextureUtil.releaseTextureId(this.LeftEyeTextureId); @@ -237,11 +240,4 @@ protected void destroyBuffers() { this.RightEyeTextureId = -1; } } - - @Override - public void destroy() { - super.destroy(); - this.hiddenMeshes[0].free(); - this.hiddenMeshes[1].free(); - } } diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index a11e9201b..a263d4db5 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -7,7 +7,6 @@ import org.lwjgl.opengl.GL31; import org.lwjgl.openxr.*; import org.lwjgl.system.MemoryStack; -import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.VRTextureTarget; import org.vivecraft.client_vr.provider.VRRenderer; import org.vivecraft.client_vr.render.RenderConfigException; @@ -23,8 +22,6 @@ public class OpenXRStereoRenderer extends VRRenderer { private VRTextureTarget[] rightFramebuffers; private boolean render; private XrCompositionLayerProjectionView.Buffer projectionLayerViews; - private VRTextureTarget rightFramebuffer; - private VRTextureTarget leftFramebuffer; public OpenXRStereoRenderer(MCOpenXR vr) { @@ -33,15 +30,15 @@ public OpenXRStereoRenderer(MCOpenXR vr) { } @Override - public void createRenderTexture(int width, int height) throws RenderConfigException { + public void createRenderTexture(int width, int height) { try (MemoryStack stack = MemoryStack.stackPush()) { - //Get amount of views in the swapchain + // Get amount of views in the swapchain IntBuffer intBuffer = stack.ints(0); //Set value to 0 int error = XR10.xrEnumerateSwapchainImages(this.openxr.swapchain, intBuffer, null); this.openxr.logError(error, "xrEnumerateSwapchainImages", "get count"); - //Now we know the amount, create the image buffer + // Now we know the amount, create the image buffer int imageCount = intBuffer.get(0); XrSwapchainImageOpenGLKHR.Buffer swapchainImageBuffer = this.openxr.device.createImageBuffers(imageCount, stack); @@ -56,15 +53,14 @@ public void createRenderTexture(int width, int height) throws RenderConfigExcept for (int i = 0; i < imageCount; i++) { XrSwapchainImageOpenGLKHR openxrImage = swapchainImageBuffer.get(i); this.leftFramebuffers[i] = new VRTextureTarget("L Eye " + i, width, height, openxrImage.image(), 0); - RenderHelper.checkGLError("Left Eye framebuffer setup"); + String leftError = RenderHelper.checkGLError("Left Eye " + i + " framebuffer setup"); this.rightFramebuffers[i] = new VRTextureTarget("R Eye " + i, width, height, openxrImage.image(), 1); - RenderHelper.checkGLError("Right Eye framebuffer setup"); - } + String rightError = RenderHelper.checkGLError("Right Eye " + i + " framebuffer setup"); - this.rightFramebuffer = new VRTextureTarget("R Eye mirror", width, height, true, -1, true, true, - ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); - this.leftFramebuffer = new VRTextureTarget("L Eye mirror", width, height, true, -1, true, true, - ClientDataHolderVR.getInstance().vrSettings.vrUseStencil); + if (this.lastError.isEmpty()) { + this.lastError = !leftError.isEmpty() ? leftError : rightError; + } + } } } @@ -72,9 +68,8 @@ public void createRenderTexture(int width, int height) throws RenderConfigExcept public void setupRenderConfiguration(boolean render) throws IOException, RenderConfigException { super.setupRenderConfiguration(render); - if (!render) { - return; - } + if (!render) return; + this.projectionLayerViews = XrCompositionLayerProjectionView.calloc(2); try (MemoryStack stack = MemoryStack.stackPush()) { @@ -96,7 +91,6 @@ public void setupRenderConfiguration(boolean render) throws IOException, RenderC // Render view to the appropriate part of the swapchain image. for (int viewIndex = 0; viewIndex < 2; viewIndex++) { - var subImage = this.projectionLayerViews.get(viewIndex) .type(XR10.XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) .pose(this.openxr.viewBuffer.get(viewIndex).pose()) @@ -110,6 +104,15 @@ public void setupRenderConfiguration(boolean render) throws IOException, RenderC } } + /** + * no caching for openxr + */ + @Override + public Matrix4f getCachedProjectionMatrix(int eyeType, float nearClip, float farClip) { + this.eyeProj[eyeType] = this.getProjectionMatrix(eyeType, nearClip, farClip); + return this.eyeProj[eyeType]; + } + @Override public Matrix4f getProjectionMatrix(int eyeType, float nearClip, float farClip) { XrFovf fov = this.openxr.viewBuffer.get(eyeType).fov(); @@ -119,20 +122,6 @@ public Matrix4f getProjectionMatrix(int eyeType, float nearClip, float farClip) @Override public void endFrame() throws RenderConfigException { - - GL31.glBindFramebuffer(GL31.GL_READ_FRAMEBUFFER, getLeftEyeTarget().frameBufferId); - GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, this.leftFramebuffers[this.swapIndex].frameBufferId); - GL31.glBlitFramebuffer(0, 0, getLeftEyeTarget().viewWidth, getLeftEyeTarget().viewHeight, 0, 0, - this.leftFramebuffers[this.swapIndex].viewWidth, this.leftFramebuffers[this.swapIndex].viewHeight, - GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); - - GL31.glBindFramebuffer(GL31.GL_READ_FRAMEBUFFER, getRightEyeTarget().frameBufferId); - GL31.glBindFramebuffer(GL31.GL_DRAW_FRAMEBUFFER, this.rightFramebuffers[this.swapIndex].frameBufferId); - GL31.glBlitFramebuffer(0, 0, getRightEyeTarget().viewWidth, getRightEyeTarget().viewHeight, 0, 0, - this.rightFramebuffers[this.swapIndex].viewWidth, this.rightFramebuffers[this.swapIndex].viewHeight, - GL31.GL_STENCIL_BUFFER_BIT | GL31.GL_COLOR_BUFFER_BIT, GL31.GL_NEAREST); - - try (MemoryStack stack = MemoryStack.stackPush()) { PointerBuffer layers = stack.callocPointer(1); int error; @@ -172,12 +161,12 @@ public boolean providesStencilMask() { @Override public RenderTarget getLeftEyeTarget() { - return this.leftFramebuffer; + return this.leftFramebuffers[this.swapIndex]; } @Override public RenderTarget getRightEyeTarget() { - return this.rightFramebuffer; + return this.rightFramebuffers[this.swapIndex]; } @Override @@ -189,4 +178,23 @@ public String getName() { public Tuple getRenderTextureSizes() { return new Tuple<>(this.openxr.width, this.openxr.height); } + + @Override + public void destroy() { + super.destroy(); + + if (this.leftFramebuffers != null) { + for (VRTextureTarget leftFramebuffer : this.leftFramebuffers) { + leftFramebuffer.destroyBuffers(); + } + this.leftFramebuffers = null; + } + + if (this.rightFramebuffers != null) { + for (VRTextureTarget rightFramebuffer : this.rightFramebuffers) { + rightFramebuffer.destroyBuffers(); + } + this.rightFramebuffers = null; + } + } } diff --git a/common/src/main/java/org/vivecraft/client_vr/render/VRShaders.java b/common/src/main/java/org/vivecraft/client_vr/render/VRShaders.java index 79cf11e3b..98c5af94f 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/VRShaders.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/VRShaders.java @@ -44,11 +44,6 @@ public class VRShaders { public static AbstractUniform POST_PROCESSING_OVERLAY_BLACK_ALPHA_UNIFORM; public static AbstractUniform POST_PROCESSING_OVERLAY_EYE_UNIFORM; - // blit shader - public static ShaderProgram BLIT_VR_SHADER = new ShaderProgram( - ResourceLocation.fromNamespaceAndPath("vivecraft", "core/blit_vr"), - DefaultVertexFormat.POSITION_TEX, ShaderDefines.EMPTY); - // end portal shaders public static ShaderProgram RENDERTYPE_END_PORTAL_VR_SHADER = new ShaderProgram( ResourceLocation.fromNamespaceAndPath("vivecraft", "core/rendertype_end_portal_vr"), diff --git a/common/src/main/java/org/vivecraft/client_vr/render/helpers/ShaderHelper.java b/common/src/main/java/org/vivecraft/client_vr/render/helpers/ShaderHelper.java index a3b05d93d..253c81978 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/helpers/ShaderHelper.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/helpers/ShaderHelper.java @@ -1,6 +1,7 @@ package org.vivecraft.client_vr.render.helpers; import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; import net.minecraft.Util; @@ -16,6 +17,8 @@ import org.jetbrains.annotations.NotNull; import org.joml.Matrix4f; import org.joml.Vector3f; +import org.lwjgl.opengl.GL11C; +import org.lwjgl.opengl.GL30C; import org.lwjgl.opengl.GL43; import org.vivecraft.client_vr.ClientDataHolderVR; import org.vivecraft.client_vr.extensions.GameRendererExtension; @@ -88,7 +91,9 @@ private static void drawFullscreenQuad(VertexFormat format) { throw new IllegalStateException("Unexpected vertex format " + format); } + RenderSystem.disableDepthTest(); BufferUploader.draw(builder.buildOrThrow()); + RenderSystem.enableDepthTest(); } /** @@ -262,11 +267,11 @@ public static void drawMirror() { int screenHeight = MC.mainRenderTarget.height; if (leftEye != null) { - ShaderHelper.blitToScreen(leftEye, 0, screenWidth, screenHeight, 0, 0.0F, 0.0F, false); + blitFramebuffer(leftEye, 0, 0, screenWidth, screenHeight); } if (rightEye != null) { - ShaderHelper.blitToScreen(rightEye, screenWidth, screenWidth, screenHeight, 0, 0.0F, 0.0F, false); + blitFramebuffer(rightEye, screenWidth, 0, MC.mainRenderTarget.width, screenHeight); } } else { // general single buffer case @@ -305,9 +310,7 @@ public static void drawMirror() { // source = DataHolder.getInstance().vrRenderer.telescopeFramebufferR; // if (source != null) { - ShaderHelper.blitToScreen(source, - 0, MC.mainRenderTarget.width, - MC.mainRenderTarget.height, 0, + blitFramebufferCrop(source, 0, 0, MC.mainRenderTarget.width, MC.mainRenderTarget.height, xCrop, yCrop, keepAspect); } } @@ -362,6 +365,12 @@ public static void doMixedRealityMirror() { mixedRealityShader.bindSampler("thirdPersonDepth", DATA_HOLDER.vrRenderer.framebufferMR.getDepthTextureId()); + mixedRealityShader.apply(); + + drawFullscreenQuad(VRShaders.MIXED_REALITY_SHADER.vertexFormat()); + + mixedRealityShader.clear(); + if (DATA_HOLDER.vrSettings.mixedRealityUnityLike) { RenderTarget source; if (DATA_HOLDER.vrSettings.displayMirrorUseScreenshotCamera && DATA_HOLDER.cameraTracker.isVisible()) { @@ -375,14 +384,9 @@ public static void doMixedRealityMirror() { source = DATA_HOLDER.vrRenderer.getRightEyeTarget(); } } - mixedRealityShader.bindSampler("firstPersonColor", source.getColorTextureId()); + blitFramebuffer(source, MC.mainRenderTarget.width / 2, 0, + MC.mainRenderTarget.width, MC.mainRenderTarget.height / 2); } - - mixedRealityShader.apply(); - - drawFullscreenQuad(VRShaders.MIXED_REALITY_SHADER.vertexFormat()); - - mixedRealityShader.clear(); } /** @@ -436,71 +440,66 @@ public static void doFSAA(RenderTarget source, RenderTarget firstPass, RenderTar } /** - * blits the given {@code source} RenderTarget to the screen/bound buffer
+ * blits the given {@code source} RenderTarget to the bound framebuffer
* the {@code source} is drawn to the rectangle at {@code left},{@code top} with a size of {@code width},{@code height}
* if {@code xCropFactor} or {@code yCropFactor} are non 0 the {@code source} gets zoomed in - * - * @param source RenderTarget to draw to the screen - * @param left left edge of the target area - * @param width width of the target area - * @param height height of the target area - * @param top top edge of the target area + * @param source RenderTarget to draw to the screen + * @param left left edge of the target area + * @param top top edge of the target area + * @param right right edge width of the target area + * @param bottom bottom edge of the target area * @param xCropFactor vertical crop factor for the {@code source} * @param yCropFactor horizontal crop factor for the {@code source} - * @param keepAspect keeps the aspect ratio in takt when cropping the buffer + * @param keepAspect keeps the aspect ratio in takt when cropping the buffer */ - public static void blitToScreen( - RenderTarget source, int left, int width, int height, int top, float xCropFactor, float yCropFactor, - boolean keepAspect) + private static void blitFramebufferCrop( + RenderTarget source, int left, int top, int right, int bottom, + float xCropFactor, float yCropFactor, boolean keepAspect) { - RenderSystem.assertOnRenderThread(); - RenderSystem.colorMask(true, true, true, false); - RenderSystem.disableDepthTest(); - RenderSystem.depthMask(false); - RenderSystem.viewport(left, top, width, height); - RenderSystem.disableBlend(); - - float drawAspect = (float) width / (float) height; - float bufferAspect = (float) source.viewWidth / (float) source.viewHeight; - - float xMin = xCropFactor; - float yMin = yCropFactor; - float xMax = 1.0F - xCropFactor; - float yMax = 1.0F - yCropFactor; - if (keepAspect) { + float drawAspect = (float) MC.mainRenderTarget.width / (float) MC.mainRenderTarget.height; + float bufferAspect = (float) source.viewWidth / (float) source.viewHeight; if (drawAspect > bufferAspect) { // destination is wider than the buffer float heightAspect = (bufferAspect / drawAspect) * (0.5F - yCropFactor); - yMin = 0.5F - heightAspect; - yMax = 0.5F + heightAspect; + yCropFactor = 0.5F - heightAspect; } else { // destination is taller than the buffer float widthAspect = (drawAspect / bufferAspect) * (0.5F - xCropFactor); - xMin = 0.5F - widthAspect; - xMax = 0.5F + widthAspect; + xCropFactor = 0.5F - widthAspect; } } - CompiledShaderProgram blitShader = Objects.requireNonNull( - RenderSystem.setShader(VRShaders.BLIT_VR_SHADER), "Vivecraft blit shader not loaded"); - blitShader.bindSampler("DiffuseSampler", source.getColorTextureId()); - - blitShader.apply(); - - BufferBuilder bufferbuilder = RenderSystem.renderThreadTesselator() - .begin(VertexFormat.Mode.QUADS, VRShaders.BLIT_VR_SHADER.vertexFormat()); - - bufferbuilder.addVertex(-1.0F, -1.0F, 0.0F).setUv(xMin, yMin); - bufferbuilder.addVertex(1.0F, -1.0F, 0.0F).setUv(xMax, yMin); - bufferbuilder.addVertex(1.0F, 1.0F, 0.0F).setUv(xMax, yMax); - bufferbuilder.addVertex(-1.0F, 1.0F, 0.0F).setUv(xMin, yMax); - BufferUploader.draw(bufferbuilder.buildOrThrow()); - blitShader.clear(); - - RenderSystem.depthMask(true); - RenderSystem.colorMask(true, true, true, true); + int xMin = (int) (xCropFactor * source.width); + int yMin = (int) (yCropFactor * source.height); + int xMax = source.width - xMin; + int yMax = source.height - yMin; + + GlStateManager._glBindFramebuffer(GL30C.GL_READ_FRAMEBUFFER, source.frameBufferId); + GlStateManager._glBlitFrameBuffer( + xMin, yMin, xMax, yMax, + left, top, right, bottom, + GL11C.GL_COLOR_BUFFER_BIT, GL11C.GL_LINEAR); + GlStateManager._glBindFramebuffer(GL30C.GL_READ_FRAMEBUFFER, 0); + } + /** + * blits the given {@code source} RenderTarget to the bound framebuffer + * @param source RenderTarget to draw to the screen + * @param left left edge of the target area + * @param top top edge of the target area + * @param right right edge width of the target area + * @param bottom bottom edge of the target area + */ + private static void blitFramebuffer( + RenderTarget source, int left, int top, int right, int bottom) + { + GlStateManager._glBindFramebuffer(GL30C.GL_READ_FRAMEBUFFER, source.frameBufferId); + GlStateManager._glBlitFrameBuffer( + 0, 0, source.width, source.height, + left, top, right, bottom, + GL11C.GL_COLOR_BUFFER_BIT, GL11C.GL_LINEAR); + GlStateManager._glBindFramebuffer(GL30C.GL_READ_FRAMEBUFFER, 0); } } diff --git a/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRPassHelper.java b/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRPassHelper.java index 0497a164c..95bbc90a2 100644 --- a/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRPassHelper.java +++ b/common/src/main/java/org/vivecraft/client_vr/render/helpers/VRPassHelper.java @@ -248,7 +248,15 @@ public static void renderAndSubmit(boolean renderLevel, DeltaTracker.Timer delta Profiler.get().pop(); DATA_HOLDER.vrPlayer.postRender(deltaTracker.getGameTimeDeltaPartialTick(true)); - Profiler.get().push("Display/Reproject"); + + Profiler.get().push("vrMirror"); + // use the vanilla target for the mirror + RenderPassManager.setMirrorRenderPass(); + MC.mainRenderTarget.bindWrite(true); + ShaderHelper.drawMirror(); + RenderHelper.checkGLError("post-mirror"); + + Profiler.get().popPush("Display/Reproject"); try { DATA_HOLDER.vrRenderer.endFrame(); diff --git a/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java b/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java index 576fed1fe..1952f065e 100644 --- a/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client/blaze3d/RenderTargetMixin.java @@ -23,8 +23,6 @@ public abstract class RenderTargetMixin implements RenderTargetExtension { public int width; @Shadow public int height; - @Shadow - protected int colorTextureId; @Unique private int vivecraft$texId = -1; @Unique @@ -54,11 +52,6 @@ public abstract class RenderTargetMixin implements RenderTargetExtension { this.vivecraft$texId = texId; } - @Override - public void vivecraft$setColorid(int colorid) { - this.colorTextureId = colorid; - } - @Unique public void vivecraft$setLinearFilter(boolean linearFilter) { this.vivecraft$linearFilter = linearFilter; diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java index 1a7eec76d..da7ffd95a 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java @@ -352,17 +352,6 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { } } - @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/pipeline/RenderTarget;unbindWrite()V")) - private void vivecraft$blitMirror(CallbackInfo ci) { - if (VRState.VR_RUNNING) { - Profiler.get().popPush("vrMirror"); - RenderPassManager.setMirrorRenderPass(); - this.mainRenderTarget.bindWrite(true); - ShaderHelper.drawMirror(); - RenderHelper.checkGLError("post-mirror"); - } - } - @Inject(method = "setCameraEntity", at = @At("HEAD")) private void vivecraft$rideEntity(Entity entity, CallbackInfo ci) { if (VRState.VR_INITIALIZED) { diff --git a/common/src/main/resources/assets/vivecraft/shaders/core/blit_vr.fsh b/common/src/main/resources/assets/vivecraft/shaders/core/blit_vr.fsh deleted file mode 100644 index d961ccfc5..000000000 --- a/common/src/main/resources/assets/vivecraft/shaders/core/blit_vr.fsh +++ /dev/null @@ -1,11 +0,0 @@ -#version 150 core - -uniform sampler2D DiffuseSampler; - -in vec2 texCoordinates; - -out vec4 fragColor; - -void main(){ - fragColor = texture(DiffuseSampler, texCoordinates.st); -} diff --git a/common/src/main/resources/assets/vivecraft/shaders/core/blit_vr.json b/common/src/main/resources/assets/vivecraft/shaders/core/blit_vr.json deleted file mode 100644 index 0f3041b2a..000000000 --- a/common/src/main/resources/assets/vivecraft/shaders/core/blit_vr.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "vertex": "vivecraft:core/passthrough_vr", - "fragment": "vivecraft:core/blit_vr", - "samplers": [ - { - "name": "DiffuseSampler" - } - ], - "uniforms": [] -} diff --git a/common/src/main/resources/assets/vivecraft/shaders/core/mixedreality_vr.fsh b/common/src/main/resources/assets/vivecraft/shaders/core/mixedreality_vr.fsh index 346fab2b2..44d5465b1 100644 --- a/common/src/main/resources/assets/vivecraft/shaders/core/mixedreality_vr.fsh +++ b/common/src/main/resources/assets/vivecraft/shaders/core/mixedreality_vr.fsh @@ -1,7 +1,5 @@ #version 330 core -uniform sampler2D firstPersonColor; - uniform sampler2D thirdPersonColor; uniform sampler2D thirdPersonDepth; @@ -63,9 +61,6 @@ void main(void) { out_Color.rgb = vec3(1.0); } } - } else if (texCoordinates.x >= 0.5 && texCoordinates.y < 0.5){ - // first person - out_Color.rgb = texture(firstPersonColor, sampleTexcCoord).rgb; } } else { // side by side From 054fb744b5a0cabb187741c0ffe21c68cdb46a07 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 8 Jan 2025 16:45:16 +0100 Subject: [PATCH 19/27] handle VR events regardless of active state fix openxr not shutting down when the runtime closes fix some naming/formatting things --- .../vivecraft/client_vr/provider/MCVR.java | 7 ++- .../client_vr/provider/nullvr/NullVR.java | 3 + .../provider/openvr_lwjgl/MCOpenVR.java | 16 +++-- .../client_vr/provider/openxr/MCOpenXR.java | 63 ++++++++++++------- ...edular.java => OpenXRHapticScheduler.java} | 6 +- .../provider/openxr/OpenXRStereoRenderer.java | 1 - .../mixin/client_vr/MinecraftVRMixin.java | 5 +- 7 files changed, 67 insertions(+), 34 deletions(-) rename common/src/main/java/org/vivecraft/client_vr/provider/openxr/{OpenXRHapticSchedular.java => OpenXRHapticScheduler.java} (90%) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java index 322e2f3bb..a2803c9db 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/MCVR.java @@ -1520,7 +1520,12 @@ private void processSwipeInput( protected abstract ControllerType findActiveBindingControllerType(KeyMapping keyMapping); /** - * polls VR events, and fetches new device poses and inputs + * polls and processes VR events + */ + public abstract void handleEvents(); + + /** + * fetches new device poses and inputs * * @param frameIndex index of the current VR frame. Some VR runtimes need that */ diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java index 309fb34cc..572e9ca38 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/nullvr/NullVR.java @@ -123,6 +123,9 @@ public boolean init() { return this.initialized; } + @Override + public void handleEvents() {} + @Override public void poll(long frameIndex) { if (this.initialized) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index 15c8fce67..af2679bbc 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -421,15 +421,21 @@ private void initializeOpenVR() throws RuntimeException { } @Override - public void poll(long frameIndex) { - if (!this.initialized) return; - - this.paused = VRSystem_ShouldApplicationPause(); + public void handleEvents() { Profiler.get().push("pollEvents"); this.pollVREvents(); Profiler.get().popPush("processEvents"); this.processVREvents(); - Profiler.get().popPush("updatePose/Vsync"); + Profiler.get().pop(); + } + + @Override + public void poll(long frameIndex) { + if (!this.initialized) return; + + this.paused = VRSystem_ShouldApplicationPause(); + + Profiler.get().push("updatePose/Vsync"); this.updatePose(); if (!this.dh.vrSettings.seated) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index f2eca05c9..c0bdaf2f0 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -17,6 +17,7 @@ import org.lwjgl.system.MemoryUtil; import org.vivecraft.client.VivecraftVRMod; import org.vivecraft.client_vr.ClientDataHolderVR; +import org.vivecraft.client_vr.VRState; import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler; import org.vivecraft.client_vr.gameplay.screenhandlers.RadialHandler; import org.vivecraft.client_vr.provider.ControllerType; @@ -73,7 +74,7 @@ public class MCOpenXR extends MCVR { public MCOpenXR(Minecraft mc, ClientDataHolderVR dh) { super(mc, dh, VivecraftVRMod.INSTANCE); OME = this; - this.hapticScheduler = new OpenXRHapticSchedular(); + this.hapticScheduler = new OpenXRHapticScheduler(); } @Override @@ -116,15 +117,15 @@ public void destroy() { } @Override - protected ControllerType findActiveBindingControllerType(KeyMapping binding) { + protected ControllerType findActiveBindingControllerType(KeyMapping keyMapping) { if (!this.inputInitialized) { return null; } else { - long path = this.getInputAction(binding).getLastOrigin(); + long path = this.getInputAction(keyMapping).getLastOrigin(); try (MemoryStack stack = MemoryStack.stackPush()) { IntBuffer buf = stack.callocInt(1); int error = XR10.xrPathToString(this.instance, path, buf, null); - logError(error, "xrPathToString", "get string length for", binding.getName()); + logError(error, "xrPathToString", "get string length for", keyMapping.getName()); int size = buf.get(); if (size <= 0) { @@ -134,7 +135,7 @@ protected ControllerType findActiveBindingControllerType(KeyMapping binding) { buf = stack.callocInt(size); ByteBuffer byteBuffer = stack.calloc(size); error = XR10.xrPathToString(this.instance, path, buf, byteBuffer); - logError(error, "xrPathToString", "get string for", binding.getName()); + logError(error, "xrPathToString", "get string for", keyMapping.getName()); byte[] bytes = new byte[byteBuffer.remaining()]; byteBuffer.get(bytes); String name = new String(bytes); @@ -147,13 +148,18 @@ protected ControllerType findActiveBindingControllerType(KeyMapping binding) { } @Override - public void poll(long var1) { + public void handleEvents() { + Profiler.get().push("events"); + this.pollVREvents(); + Profiler.get().pop(); + } + + @Override + public void poll(long frameIndex) { if (this.initialized) { - Profiler.get().push("events"); - this.pollVREvents(); if (!this.dh.vrSettings.seated) { - Profiler.get().popPush("controllers"); + Profiler.get().push("controllers"); Profiler.get().push("gui"); if (this.mc.screen == null && this.dh.vrSettings.vrTouchHotbar) { @@ -515,6 +521,16 @@ private void sessionChanged(XrEventDataSessionStateChanged xrEventDataSessionSta this.isActive = false; int error = XR10.xrEndSession(this.session); logError(error, "xrEndSession", "XR_SESSION_STATE_STOPPING"); + + if (ClientDataHolderVR.getInstance().vrSettings.closeWithRuntime) { + VRSettings.LOGGER.info("Vivecraft: OpenXR stopped, closing the game with it"); + this.mc.stop(); + } else { + VRSettings.LOGGER.info("Vivecraft: OpenXR stopped, disabling VR"); + VRState.VR_ENABLED = !VRState.VR_ENABLED; + ClientDataHolderVR.getInstance().vrSettings.vrEnabled = VRState.VR_ENABLED; + ClientDataHolderVR.getInstance().vrSettings.saveOptions(); + } } case XR10.XR_SESSION_STATE_VISIBLE, XR10.XR_SESSION_STATE_FOCUSED: { this.isActive = true; @@ -558,7 +574,7 @@ public boolean init() { this.initializeOpenXRSwapChain(); this.initInputAndApplication(); } catch (Exception e) { - e.printStackTrace(); + VRSettings.LOGGER.error("Vivecraft: OpenXR init failed", e); this.initSuccess = false; this.initStatus = e.getLocalizedMessage(); return false; @@ -566,7 +582,7 @@ public boolean init() { // TODO Seated when no controllers - System.out.println("OpenXR initialized & VR connected."); + VRSettings.LOGGER.info("Vivecraft: OpenXR initialized & VR connected."); this.deviceVelocity = new Vector3f[64]; for (int i = 0; i < this.poseMatrices.length; ++i) { @@ -718,7 +734,7 @@ private void initializeOpenXRSession() { this.session = new XrSession(sessionPtr.get(0), this.instance); while (!this.isActive) { - System.out.println("waiting"); + VRSettings.LOGGER.info("Vivecraft: waiting for OpenXR session to start"); pollVREvents(); } } @@ -843,7 +859,7 @@ private void initializeOpenXRSwapChain() { } /** - * Creates an array of XrStructs with their types pre set to @param type + * Creates an array of XrStructs with their types preset to {@code type} */ static ByteBuffer bufferStack(int capacity, int sizeof, int type) { ByteBuffer b = stackCalloc(capacity * sizeof); @@ -868,7 +884,7 @@ private void initInputAndApplication() { } @Override - public Matrix4f getControllerComponentTransform(int var1, String var2) { + public Matrix4f getControllerComponentTransform(int controllerIndex, String componentName) { return new Matrix4f(); } @@ -878,16 +894,16 @@ public boolean hasCameraTracker() { } @Override - public List getOrigins(VRInputAction var1) { + public List getOrigins(VRInputAction action) { try (MemoryStack stack = MemoryStack.stackPush()) { XrBoundSourcesForActionEnumerateInfo info = XrBoundSourcesForActionEnumerateInfo.calloc(stack); info.type(XR10.XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO); info.next(NULL); - info.action( - new XrAction(var1.handle, new XrActionSet(this.actionSetHandles.get(var1.actionSet), this.instance))); + info.action(new XrAction(action.handle, + new XrActionSet(this.actionSetHandles.get(action.actionSet), this.instance))); IntBuffer buf = stack.callocInt(1); int error = XR10.xrEnumerateBoundSourcesForAction(this.session, info, buf, null); - logError(error, "xrEnumerateBoundSourcesForAction", var1.name); + logError(error, "xrEnumerateBoundSourcesForAction", action.name); int size = buf.get(); if (size <= 0) { @@ -897,7 +913,7 @@ public List getOrigins(VRInputAction var1) { buf = stack.callocInt(size); LongBuffer longbuf = stack.callocLong(size); error = XR10.xrEnumerateBoundSourcesForAction(this.session, info, buf, longbuf); - logError(error, "xrEnumerateBoundSourcesForAction", var1.name); + logError(error, "xrEnumerateBoundSourcesForAction", action.name); long[] array; if (longbuf.hasArray()) { //TODO really? array = longbuf.array(); @@ -914,12 +930,12 @@ public List getOrigins(VRInputAction var1) { } @Override - public String getOriginName(long l) { + public String getOriginName(long origin) { try (MemoryStack stack = MemoryStack.stackPush()) { XrInputSourceLocalizedNameGetInfo info = XrInputSourceLocalizedNameGetInfo.calloc(stack); info.type(XR10.XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO); info.next(0); - info.sourcePath(l); + info.sourcePath(origin); info.whichComponents(XR10.XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT); IntBuffer buf = stack.callocInt(1); @@ -946,13 +962,12 @@ public VRRenderer createVRRenderer() { @Override public boolean isActive() { - this.pollVREvents(); return this.isActive; } @Override - public ControllerType getOriginControllerType(long i) { - if (i == this.aim[RIGHT_CONTROLLER]) { + public ControllerType getOriginControllerType(long inputValueHandle) { + if (inputValueHandle == this.aim[RIGHT_CONTROLLER]) { return ControllerType.RIGHT; } return ControllerType.LEFT; diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticScheduler.java similarity index 90% rename from common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java rename to common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticScheduler.java index 819a355e8..a0022a671 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticSchedular.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRHapticScheduler.java @@ -11,9 +11,11 @@ import static java.sql.Types.NULL; -public class OpenXRHapticSchedular extends HapticScheduler { +public class OpenXRHapticScheduler extends HapticScheduler { - private void triggerHapticPulse(ControllerType controller, float durationSeconds, float frequency, float amplitude) { + private void triggerHapticPulse( + ControllerType controller, float durationSeconds, float frequency, float amplitude) + { try (MemoryStack stack = MemoryStack.stackPush()){ int i = controller == ControllerType.RIGHT ? 0 : 1; if (ClientDataHolderVR.getInstance().vrSettings.reverseHands) { diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index a263d4db5..4d8aecca6 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -4,7 +4,6 @@ import net.minecraft.util.Tuple; import org.joml.Matrix4f; import org.lwjgl.PointerBuffer; -import org.lwjgl.opengl.GL31; import org.lwjgl.openxr.*; import org.lwjgl.system.MemoryStack; import org.vivecraft.client_vr.VRTextureTarget; diff --git a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java index da7ffd95a..f5b3c5ad4 100644 --- a/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java +++ b/common/src/main/java/org/vivecraft/mixin/client_vr/MinecraftVRMixin.java @@ -74,7 +74,6 @@ import org.vivecraft.client_vr.render.RenderConfigException; import org.vivecraft.client_vr.render.VRFirstPersonArmSwing; import org.vivecraft.client_vr.render.helpers.RenderHelper; -import org.vivecraft.client_vr.render.helpers.ShaderHelper; import org.vivecraft.client_vr.settings.VRHotkeys; import org.vivecraft.client_vr.settings.VRSettings; import org.vivecraft.client_xr.render_pass.RenderPassManager; @@ -246,6 +245,10 @@ public abstract class MinecraftVRMixin implements MinecraftExtension { if (!VRState.VR_INITIALIZED) { return; } + + // handle vr events, regardless of VR active state + ClientDataHolderVR.getInstance().vr.handleEvents(); + boolean vrActive = !ClientDataHolderVR.getInstance().vrSettings.vrHotswitchingEnabled || ClientDataHolderVR.getInstance().vr.isActive(); if (VRState.VR_RUNNING != vrActive && (ClientNetworking.SERVER_ALLOWS_VR_SWITCHING || this.player == null)) { From b54e705de95293629c1a8a50b359b8f10e522465 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 8 Jan 2025 18:19:46 +0100 Subject: [PATCH 20/27] fix inputs with openvr --- .../org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java | 1 - 1 file changed, 1 deletion(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java index af2679bbc..fdca4b509 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openvr_lwjgl/MCOpenVR.java @@ -102,7 +102,6 @@ public class MCOpenVR extends MCVR { // holds the handle to the devices other than the headset private final long[] deviceHandle = new long[MCVR.TRACKABLE_DEVICE_COUNT]; - private boolean inputInitialized; private final InputOriginInfo originInfo; private final InputPoseActionData poseData; private final InputDigitalActionData digital; From ab612fc72c53567cc16b9bf95e308027eafa79bb Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 8 Jan 2025 19:36:23 +0100 Subject: [PATCH 21/27] projection matrix only once per frame --- .../provider/openxr/OpenXRStereoRenderer.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java index 4d8aecca6..13b89a698 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/OpenXRStereoRenderer.java @@ -21,6 +21,7 @@ public class OpenXRStereoRenderer extends VRRenderer { private VRTextureTarget[] rightFramebuffers; private boolean render; private XrCompositionLayerProjectionView.Buffer projectionLayerViews; + private boolean recalculateProjectionMatrix = true; public OpenXRStereoRenderer(MCOpenXR vr) { @@ -90,7 +91,7 @@ public void setupRenderConfiguration(boolean render) throws IOException, RenderC // Render view to the appropriate part of the swapchain image. for (int viewIndex = 0; viewIndex < 2; viewIndex++) { - var subImage = this.projectionLayerViews.get(viewIndex) + XrSwapchainSubImage subImage = this.projectionLayerViews.get(viewIndex) .type(XR10.XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) .pose(this.openxr.viewBuffer.get(viewIndex).pose()) .fov(this.openxr.viewBuffer.get(viewIndex).fov()) @@ -100,15 +101,21 @@ public void setupRenderConfiguration(boolean render) throws IOException, RenderC subImage.imageRect().extent().set(this.openxr.width, this.openxr.height); subImage.imageArrayIndex(viewIndex); } + this.recalculateProjectionMatrix = true; } } /** * no caching for openxr + * the projection matrix may change every frame, so recalculate it once per frame for up to date info */ @Override public Matrix4f getCachedProjectionMatrix(int eyeType, float nearClip, float farClip) { - this.eyeProj[eyeType] = this.getProjectionMatrix(eyeType, nearClip, farClip); + if (this.recalculateProjectionMatrix) { + this.eyeProj[0] = this.getProjectionMatrix(0, nearClip, farClip); + this.eyeProj[1] = this.getProjectionMatrix(1, nearClip, farClip); + this.recalculateProjectionMatrix = false; + } return this.eyeProj[eyeType]; } From 3a71a9e1ccaa458b43a8ca26fb451f437a1f7af0 Mon Sep 17 00:00:00 2001 From: fayer3 Date: Wed, 8 Jan 2025 23:56:24 +0100 Subject: [PATCH 22/27] fix analog button input --- .../org/vivecraft/client_vr/provider/openxr/MCOpenXR.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index c0bdaf2f0..0cf12d801 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -383,7 +383,7 @@ private void readFloat(VRInputAction action, ControllerType hand) { int error = XR10.xrGetActionStateFloat(this.session, info, state); logError(error, "xrGetActionStateFloat", action.name); - action.analogData[i].deltaX = action.analogData[i].x - state.currentState(); + action.analogData[i].deltaX = state.currentState() - action.analogData[i].x; action.analogData[i].x = state.currentState(); action.analogData[i].activeOrigin = getOrigins(action).get(0); action.analogData[i].isActive = state.isActive(); @@ -406,8 +406,8 @@ private void readVecData(VRInputAction action, ControllerType hand) { int error = XR10.xrGetActionStateVector2f(this.session, info, state); logError(error, "xrGetActionStateVector2f", action.name); - action.analogData[i].deltaX = action.analogData[i].x - state.currentState().x(); - action.analogData[i].deltaY = action.analogData[i].y - state.currentState().y(); + action.analogData[i].deltaX = state.currentState().x() - action.analogData[i].x; + action.analogData[i].deltaY = state.currentState().y() - action.analogData[i].y; action.analogData[i].x = state.currentState().x(); action.analogData[i].y = state.currentState().y(); action.analogData[i].activeOrigin = getOrigins(action).get(0); From 48023e9fb004da98cee79b1cf1de21cec58e939c Mon Sep 17 00:00:00 2001 From: fayer3 Date: Thu, 9 Jan 2025 00:46:56 +0100 Subject: [PATCH 23/27] add interact/climbey bindings, fix cosoms bindings --- .../client_vr/provider/openxr/XRBindings.java | 54 ++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java index 8a3a684a6..987f3d8d9 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java @@ -49,6 +49,16 @@ private static HashSet> quest2Bindings() { set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/right/input/squeeze")); set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/left/input/trigger")); set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/right/input/trigger")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/trigger")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/trigger")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/trigger")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/trigger")); return set; } @@ -84,6 +94,16 @@ private static HashSet> viveBindings() { set.add(new MutablePair<>("/actions/technical/in/vivecraft.key.trackpadTouch", "/user/hand/left/input/trackpad/click")); set.add(new MutablePair<>("/actions/technical/in/vivecraft.key.trackpadTouch", "/user/hand/right/input/trackpad/touch")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/squeeze/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/trigger/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/squeeze/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/trigger/click")); + return set; } @@ -91,30 +111,40 @@ private static HashSet> cosmosBindings() { HashSet> set = new HashSet<>(); set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/y/click")); - set.add(new MutablePair<>("/actions/global/in/vivecraft.key.toggleKeyboard", "/user/hand/left/input/y/long")); + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.toggleKeyboard", "/user/hand/left/input/y/click")); set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/left/input/x/click")); - set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/grip/click")); - set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiMiddleClick", "/user/hand/right/input/grip/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiMiddleClick", "/user/hand/right/input/squeeze/click")); set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiLeftClick", "/user/hand/right/input/trigger/click")); set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiRightClick", "/user/hand/right/input/a/click")); - set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiScrollAxis", "/user/hand/right/input/joystick/scroll")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiScrollAxis", "/user/hand/right/input/thumbstick")); - set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarPrev", "/user/hand/left/input/grip/click")); - set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarNext", "/user/hand/right/input/grip/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarPrev", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarNext", "/user/hand/right/input/squeeze/click")); set.add(new MutablePair<>("/actions/ingame/in/key.attack", "/user/hand/right/input/trigger/click")); set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleport", "/user/hand/left/input/trigger/click")); set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.radialMenu", "/user/hand/right/input/b/click")); set.add(new MutablePair<>("/actions/ingame/in/key.use", "/user/hand/right/input/a/click")); - set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.freeMoveStrafe", "/user/hand/left/input/joystick/position")); - set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.rotateAxis", "/user/hand/right/input/joystick/position")); - set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleportFallback", "/user/hand/left/input/trigger/pull")); - set.add(new MutablePair<>("/actions/ingame/in/key.jump", "/user/hand/left/input/bumper/click")); - set.add(new MutablePair<>("/actions/ingame/in/key.sneak", "/user/hand/right/input/bumper/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.freeMoveStrafe", "/user/hand/left/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.rotateAxis", "/user/hand/right/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleportFallback", "/user/hand/left/input/trigger/value")); + set.add(new MutablePair<>("/actions/ingame/in/key.jump", "/user/hand/left/input/shoulder/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.sneak", "/user/hand/right/input/shoulder/click")); - set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/left/input/grip/click")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/left/input/squeeze/click")); set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/left/input/trigger/click")); set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/right/input/trigger/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/squeeze/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/trigger/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/squeeze/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/squeeze/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/trigger/click")); return set; } From 6c3a95be36c3ca1c70fb118fff09f95a9c733873 Mon Sep 17 00:00:00 2001 From: Darien Johnson <84008186+CADIndie@users.noreply.github.com> Date: Mon, 27 Jan 2025 20:10:30 -0500 Subject: [PATCH 24/27] Add Default, Pico, and Index Controller Bindings --- .../client_vr/provider/openxr/XRBindings.java | 130 ++++++++++++++++-- 1 file changed, 122 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java index 987f3d8d9..76ce8a5f6 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/XRBindings.java @@ -9,14 +9,19 @@ public class XRBindings { public static HashSet supportedHeadsets() { HashSet set = new HashSet<>(); - if (MCOpenXR.get().systemName.toLowerCase().contains("oculus") || MCOpenXR.get().systemName.toLowerCase().contains("meta")) { - set.add("/interaction_profiles/oculus/touch_controller"); - return set; - } if (MCOpenXR.get().session.getCapabilities().XR_HTC_vive_cosmos_controller_interaction) { set.add("/interaction_profiles/htc/vive_cosmos_controller"); } + + if (MCOpenXR.get().session.getCapabilities().XR_BD_controller_interaction) { + set.add("/interaction_profiles/bytedance/pico4_controller"); + set.add("/interaction_profiles/bytedance/pico_neo3_controller"); + } + + set.add("/interaction_profiles/khr/simple_controller"); + set.add("/interaction_profiles/oculus/touch_controller"); set.add("/interaction_profiles/htc/vive_controller"); + set.add("/interaction_profiles/valve/index_controller"); return set; } @@ -24,7 +29,6 @@ private static HashSet> quest2Bindings() { HashSet> set = new HashSet<>(); set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/y/click")); - set.add(new MutablePair<>("/actions/global/in/vivecraft.key.toggleKeyboard", "/user/hand/left/input/squeeze")); set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/left/input/x/click")); set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/squeeze")); @@ -66,7 +70,6 @@ private static HashSet> viveBindings() { HashSet> set = new HashSet<>(); set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/menu/click")); - set.add(new MutablePair<>("/actions/global/in/vivecraft.key.toggleKeyboard", "/user/hand/left/input/squeeze/click")); set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/right/input/trackpad/click")); set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/squeeze/click")); @@ -111,7 +114,6 @@ private static HashSet> cosmosBindings() { HashSet> set = new HashSet<>(); set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/y/click")); - set.add(new MutablePair<>("/actions/global/in/vivecraft.key.toggleKeyboard", "/user/hand/left/input/y/click")); set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/left/input/x/click")); set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/squeeze/click")); @@ -148,6 +150,111 @@ private static HashSet> cosmosBindings() { return set; } + private static HashSet> picoBindings() { + HashSet> set = new HashSet<>(); + + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/y/click")); + set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/left/input/x/click")); + + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiMiddleClick", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiLeftClick", "/user/hand/right/input/trigger/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiRightClick", "/user/hand/right/input/a/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiScrollAxis", "/user/hand/right/input/thumbstick/y")); + + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarPrev", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarNext", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/ingame/in/key.attack", "/user/hand/right/input/trigger/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleport", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.radialMenu", "/user/hand/right/input/b/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.use", "/user/hand/right/input/a/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleportFallback", "/user/hand/left/input/trigger/value")); + set.add(new MutablePair<>("/actions/ingame/in/key.jump", "/user/hand/left/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.freeMoveStrafe", "/user/hand/left/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/key.sneak", "/user/hand/right/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.rotateAxis", "/user/hand/right/input/thumbstick")); + + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/right/input/trigger/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/trigger/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/trigger/click")); + return set; + } + + private static HashSet> indexBindings() { + HashSet> set = new HashSet<>(); + + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/b/click")); + set.add(new MutablePair<>("/actions/global/in/key.inventory", "/user/hand/left/input/a/click")); + + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiShift", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiMiddleClick", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiLeftClick", "/user/hand/right/input/trigger/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiRightClick", "/user/hand/right/input/trackpad")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiScrollAxis", "/user/hand/right/input/thumbstick/y")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiScrollAxis", "/user/hand/right/input/trackpad/y")); + + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarPrev", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.hotbarNext", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/ingame/in/key.attack", "/user/hand/right/input/trigger/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleport", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.radialMenu", "/user/hand/right/input/b/click")); + set.add(new MutablePair<>("/actions/ingame/in/key.use", "/user/hand/right/input/trackpad")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleportFallback", "/user/hand/left/input/trigger/value")); + set.add(new MutablePair<>("/actions/ingame/in/key.jump", "/user/hand/left/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.freeMoveStrafe", "/user/hand/left/input/thumbstick")); + set.add(new MutablePair<>("/actions/ingame/in/key.sneak", "/user/hand/right/input/a/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.rotateAxis", "/user/hand/right/input/thumbstick")); + + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardShift", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/right/input/trigger/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/trigger/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/squeeze")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/trigger/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/trigger/click")); + return set; + } + + private static HashSet> defaultBindings() { + HashSet> set = new HashSet<>(); + + set.add(new MutablePair<>("/actions/global/in/vivecraft.key.ingameMenuButton", "/user/hand/left/input/menu/click")); + set.add(new MutablePair<>("/actions/gui/in/vivecraft.key.guiLeftClick", "/user/hand/right/input/select/click")); + + set.add(new MutablePair<>("/actions/ingame/in/key.attack", "/user/hand/right/input/select/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleport", "/user/hand/left/input/select/click")); + set.add(new MutablePair<>("/actions/ingame/in/vivecraft.key.teleportFallback", "/user/hand/left/input/select/click")); + + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/left/input/select/click")); + set.add(new MutablePair<>("/actions/keyboard/in/vivecraft.key.keyboardClick", "/user/hand/right/input/select/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/left/input/select/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.vrInteract", "/user/hand/right/input/select/click")); + + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/left/input/select/click")); + set.add(new MutablePair<>("/actions/contextual/in/vivecraft.key.climbeyGrab", "/user/hand/right/input/select/click")); + + return set; + } + public static HashSet> getBinding(String Headset){ switch (Headset) { case "/interaction_profiles/htc/vive_cosmos_controller" -> { @@ -156,11 +263,18 @@ public static HashSet> getBinding(String Headset){ case "/interaction_profiles/htc/vive_controller" -> { return viveBindings(); } + case "/interaction_profiles/valve/index_controller" -> { + return indexBindings(); + } case "/interaction_profiles/oculus/touch_controller" -> { return quest2Bindings(); } + case "/interaction_profiles/bytedance/pico4_controller", + "/interaction_profiles/bytedance/pico_neo3_controller" -> { + return picoBindings(); + } default -> { - return viveBindings(); + return defaultBindings(); } } } From a87509b2a453da999b891d2b04c06915e336ca97 Mon Sep 17 00:00:00 2001 From: Darien Johnson <84008186+CADIndie@users.noreply.github.com> Date: Mon, 27 Jan 2025 20:33:43 -0500 Subject: [PATCH 25/27] Totally didn't forget the extension --- .../org/vivecraft/client_vr/provider/openxr/MCOpenXR.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 0cf12d801..6122bb42a 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -615,7 +615,7 @@ private void initializeOpenXRInstance() { // get needed extensions String graphicsExtension = this.device.getGraphicsExtension(); boolean missingGraphics = true; - PointerBuffer extensions = stack.callocPointer(3); + PointerBuffer extensions = stack.callocPointer(4); while (properties.hasRemaining()) { XrExtensionProperties prop = properties.get(); String extensionName = prop.extensionNameString(); @@ -635,6 +635,12 @@ private void initializeOpenXRInstance() { extensions.put(memAddress(stackUTF8( HTCViveCosmosControllerInteraction.XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME))); } + if (extensionName.equals( + BDControllerInteraction.XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME)) + { + extensions.put(memAddress(stackUTF8( + BDControllerInteraction.XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME))); + } } if (missingGraphics) { From db061c10bea30362de8af7f444697996091140a0 Mon Sep 17 00:00:00 2001 From: Darien Johnson <84008186+CADIndie@users.noreply.github.com> Date: Mon, 27 Jan 2025 21:25:41 -0500 Subject: [PATCH 26/27] Set Refresh Rate --- .../client_vr/provider/openxr/MCOpenXR.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 6122bb42a..532d5cef6 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -30,6 +30,7 @@ import javax.annotation.Nullable; import java.nio.ByteBuffer; +import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.util.*; @@ -615,7 +616,7 @@ private void initializeOpenXRInstance() { // get needed extensions String graphicsExtension = this.device.getGraphicsExtension(); boolean missingGraphics = true; - PointerBuffer extensions = stack.callocPointer(4); + PointerBuffer extensions = stack.callocPointer(5); while (properties.hasRemaining()) { XrExtensionProperties prop = properties.get(); String extensionName = prop.extensionNameString(); @@ -641,6 +642,12 @@ private void initializeOpenXRInstance() { extensions.put(memAddress(stackUTF8( BDControllerInteraction.XR_BD_CONTROLLER_INTERACTION_EXTENSION_NAME))); } + if (extensionName.equals( + FBDisplayRefreshRate.XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME)) + { + extensions.put(memAddress(stackUTF8( + FBDisplayRefreshRate.XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME))); + } } if (missingGraphics) { @@ -864,6 +871,17 @@ private void initializeOpenXRSwapChain() { } } + private void initDisplayRefreshRate() { + try (MemoryStack stack = MemoryStack.stackPush()) { + IntBuffer refreshRateCount = stack.callocInt(1); + FBDisplayRefreshRate.xrEnumerateDisplayRefreshRatesFB(session, refreshRateCount, null); + FloatBuffer refreshRateBuffer = stack.callocFloat(refreshRateCount.get(0)); + FBDisplayRefreshRate.xrEnumerateDisplayRefreshRatesFB(session, refreshRateCount, refreshRateBuffer); + refreshRateBuffer.rewind(); + FBDisplayRefreshRate.xrRequestDisplayRefreshRateFB(session, refreshRateBuffer.get(refreshRateCount.get(0) -1)); + } + } + /** * Creates an array of XrStructs with their types preset to {@code type} */ @@ -887,6 +905,7 @@ private void initInputAndApplication() { this.loadDefaultBindings(); //this.installApplicationManifest(false); this.inputInitialized = true; + this.initDisplayRefreshRate(); } @Override From 248facb75b021c23b49b510741cd8f5c64fba961 Mon Sep 17 00:00:00 2001 From: Darien Johnson <84008186+CADIndie@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:20:13 -0500 Subject: [PATCH 27/27] Ensure FBRefreshRate Before Usage --- .../vivecraft/client_vr/provider/openxr/MCOpenXR.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java index 532d5cef6..f0ca6df34 100644 --- a/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java +++ b/common/src/main/java/org/vivecraft/client_vr/provider/openxr/MCOpenXR.java @@ -872,13 +872,15 @@ private void initializeOpenXRSwapChain() { } private void initDisplayRefreshRate() { - try (MemoryStack stack = MemoryStack.stackPush()) { + if (this.session.getCapabilities().XR_FB_display_refresh_rate) { + try (MemoryStack stack = MemoryStack.stackPush()) { IntBuffer refreshRateCount = stack.callocInt(1); - FBDisplayRefreshRate.xrEnumerateDisplayRefreshRatesFB(session, refreshRateCount, null); + FBDisplayRefreshRate.xrEnumerateDisplayRefreshRatesFB(this.session, refreshRateCount, null); FloatBuffer refreshRateBuffer = stack.callocFloat(refreshRateCount.get(0)); - FBDisplayRefreshRate.xrEnumerateDisplayRefreshRatesFB(session, refreshRateCount, refreshRateBuffer); + FBDisplayRefreshRate.xrEnumerateDisplayRefreshRatesFB(this.session, refreshRateCount, refreshRateBuffer); refreshRateBuffer.rewind(); - FBDisplayRefreshRate.xrRequestDisplayRefreshRateFB(session, refreshRateBuffer.get(refreshRateCount.get(0) -1)); + FBDisplayRefreshRate.xrRequestDisplayRefreshRateFB(this.session, refreshRateBuffer.get(refreshRateCount.get(0) -1)); + } } }