Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
Platane committed Aug 11, 2024
1 parent f460490 commit e338911
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 2 deletions.
7 changes: 6 additions & 1 deletion src/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import { useXR8 } from "../XR8Canvas/useXR8";
// @ts-ignore
import { Visualizer } from "react-touch-visualizer";
import { xr8Hosted } from "../XR8Canvas/getXR8";
import { WebXRControls } from "../WebXRCanvas/WebXRControls";

const xr8ApiKey: string = ""; //process.env.XR8_API_KEY!;
const touchSupported = "ontouchend" in document;

type Props = {
webXRSession?: XRSession;
started: boolean;
onReady: () => void;
onProgress?: (x: number) => void;
Expand All @@ -40,7 +42,7 @@ const useHint = ({ status, k, dicesToReroll, roundKey }: any) => {
}
};

export const App = ({ onReady, onProgress, started }: Props) => {
export const App = ({ onReady, onProgress, webXRSession, started }: Props) => {
const [error, setError] = React.useState<Error>();
if (error) throw error;

Expand Down Expand Up @@ -97,6 +99,7 @@ export const App = ({ onReady, onProgress, started }: Props) => {

<Canvas
camera={{ position: new THREE.Vector3(0, 6, 6) }}
frameloop="never"
shadows
style={{
position: "fixed",
Expand All @@ -111,6 +114,8 @@ export const App = ({ onReady, onProgress, started }: Props) => {
<ErrorBoundary onError={setError}>
{xr8 && <XR8Controls xr8={xr8} onReady={() => setXr8Ready(true)} />}

{webXRSession && <WebXRControls webXRSession={webXRSession} />}

<React.Suspense fallback={null}>
<Environment path={"assets/"} files={"lebombo_1k.hdr"} />

Expand Down
9 changes: 8 additions & 1 deletion src/App/Boot.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from "react";
import { LoadingScreen } from "./Ui/LoadingScreen";
import loadable from "@loadable/component";
import { useWebXRSession } from "../WebXRCanvas/WebXRControls";

const LazyApp = loadable(() => import("./App"));

Expand All @@ -10,11 +11,14 @@ export const Boot = () => {
>({ progress: 0 });
const [started, setStarted] = React.useState(false);

const webXR = useWebXRSession();

return (
<ErrorBoundary>
<React.Suspense fallback={null}>
<LazyApp
started={started}
webXRSession={webXR.session}
onReady={() => setLoadingStatus("ready")}
onProgress={(progress) =>
setLoadingStatus((s) => (s === "ready" ? s : { progress }))
Expand All @@ -28,7 +32,10 @@ export const Boot = () => {
loadingProgress={
loadingStatus !== "ready" ? loadingStatus.progress : 1
}
onClose={() => setStarted(true)}
onClose={() => {
webXR.init();
setStarted(true);
}}
/>
)}
</ErrorBoundary>
Expand Down
117 changes: 117 additions & 0 deletions src/WebXRCanvas/WebXRControls.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import * as React from "react";
import { useThree, useFrame } from "@react-three/fiber";

/**
* true if webXR is supported
*/
export const useIsWebXRSupported = () => {
const [isSupported, setIsSupported] = React.useState<boolean | "loading">(
"loading"
);
React.useLayoutEffect(() => {
if (!navigator.xr) setIsSupported(false);
else navigator.xr.isSessionSupported("immersive-ar").then(setIsSupported);
}, []);
return isSupported;
};

/**
*
*/
export const useWebXRSession = () => {
const [session, setSession] = React.useState<XRSession>();

const [error, setError] = React.useState<Error>();
if (error) throw error;

const init = React.useCallback(() => {
if (!navigator.xr || !navigator.xr.isSessionSupported("immersive-ar"))
return;

return navigator.xr
.requestSession("immersive-ar")
.then(setSession)
.catch(setError);
}, []);

console.log("session", session);

return { init, session };
};

export const WebXRControls = ({
webXRSession,
}: {
webXRSession: XRSession;
}) => {
const [error, setError] = React.useState<Error>();
if (error) throw error;

const { gl: renderer, scene, camera } = useThree();

React.useLayoutEffect(() => {
console.log("xrSession", webXRSession);

const gl = renderer.getContext();

gl.makeXRCompatible().then(() => {
webXRSession.updateRenderState({
baseLayer: new XRWebGLLayer(webXRSession, gl),
});
});

let referenceSpace: XRReferenceSpace | XRBoundedReferenceSpace;

webXRSession.requestReferenceSpace("local").then((r) => {
referenceSpace = r;

referenceSpace.addEventListener("reset", (evt) => {
console.log("reset");
if (evt.transform) {
// AR experiences typically should stay grounded to the real world.
// If there's a known origin shift, compensate for it here.
referenceSpace = referenceSpace.getOffsetReferenceSpace(
evt.transform
);
}
});
});

let cancel: number;

const onXRFrame = (t: number, frame: XRFrame) => {
const glLayer = webXRSession.renderState.baseLayer;
const pose = referenceSpace && frame.getViewerPose(referenceSpace);

if (glLayer) {
// console.log("frame", frame, "pose", pose);

gl.bindFramebuffer(gl.FRAMEBUFFER, glLayer.framebuffer);

// Clear the framebuffer
// renderer.clear(true, true, false);
renderer.render(scene, camera);

console.log("render");

if (pose) {
// Loop through each of the views reported by the frame and draw them
// into the corresponding viewport.
for (const view of pose.views) {
let viewport = glLayer.getViewport(view);
}
}
}

cancel = webXRSession.requestAnimationFrame(onXRFrame);
};

cancel = webXRSession.requestAnimationFrame(onXRFrame);

return () => webXRSession.cancelAnimationFrame(cancel);

// session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
}, [webXRSession, renderer]);

return null;
};

0 comments on commit e338911

Please sign in to comment.