UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

91 lines (90 loc) 4.12 kB
import { Mesh, MeshBasicMaterial, PerspectiveCamera, PlaneGeometry, Scene } from "three"; import { isDevEnvironment, showBalloonError } from "./debug/index.js"; // Adapted from WebARCameraBackground /** * Assigns the camera feed to a texture - this must be called during the render loop */ export function updateTextureFromXRFrame(renderer, target) { const xrframe = renderer.xr.getFrame(); if (!xrframe) { console.warn("No XRFrame available"); return false; } // If camera feed is not present, then abort and hiden background const enabledFeatures = xrframe.session.enabledFeatures; if (enabledFeatures && !enabledFeatures.some(x => x === 'camera-access')) { console.error(`No camera feed available - please request the 'camera-access' feature before starting WebXR or add the ARCameraBackground component to your scene. Example to request camera-access in global scope: NeedleXRSession.onSessionRequestStart(evt => { evt.init.optionalFeatures = evt.init.optionalFeatures || []; evt.init.optionalFeatures.push('camera-access'); }); `); if (isDevEnvironment()) { showBalloonError("No camera feed available - please request the 'camera-access' feature before starting WebXR or add the ARCameraBackground component to your scene"); } return false; } // https://chromium.googlesource.com/chromium/src/+/7c5ac3c0f95b97cf12be95a5c1c0a8ff163246d8/third_party/webxr_test_pages/webxr-samples/proposals/camera-access-barebones.html const pose = xrframe.getViewerPose(renderer.xr.getReferenceSpace()); if (pose) { for (const view of pose.views) { // @ts-ignore if ('camera' in view && view.camera) { let binding = renderer.xr.getBinding(); // not sure how / why this can be null, but we can recreate it here if (!binding) binding = new XRWebGLBinding(xrframe.session, renderer.getContext()); if (binding) { let glImage = null; if ('getCameraImage' in binding) { ensureTextureIsInitialized(renderer, target); // discussion on exactly this: // https://discourse.threejs.org/t/using-a-webgltexture-as-texture-for-three-js/46245/8 // HACK from https://stackoverflow.com/a/55084367 to inject a custom texture into three.js const texProps = renderer.properties.get(target); if (texProps) { // @ts-ignore glImage = binding.getCameraImage(view.camera); texProps.__webglTexture = glImage; return true; } else { console.warn("No texture properties found for target texture"); } } } else { console.error(view.camera, renderer.xr); } } else { console.error("NO CAMERA IN VIEW"); } } } else { console.error(renderer.xr.getReferenceSpace(), xrframe); } return false; } const initcache = new WeakMap(); function ensureTextureIsInitialized(renderer, texture) { // ensure the texture is initialized const inits = initcache.get(texture) || new WeakSet(); if (inits.has(renderer)) { return; } inits.add(renderer); initcache.set(texture, inits); console.debug("Initialize texture for camera feed"); const material = new MeshBasicMaterial(); const geometry = new PlaneGeometry(); const scene = new Scene(); scene.add(new Mesh(geometry, material)); const camera = new PerspectiveCamera(); material.map = texture; renderer.render(scene, camera); } ; //# sourceMappingURL=engine_utils_screenshot.xr.js.map