diff --git a/bootup.mp4 b/bootup.mp4 new file mode 100644 index 0000000..d0cdcbf Binary files /dev/null and b/bootup.mp4 differ diff --git a/index.html b/index.html index eeba379..1b7ca9e 100644 --- a/index.html +++ b/index.html @@ -15,9 +15,34 @@ + +
diff --git a/main.js b/main.js index 48ae566..1bc058e 100644 --- a/main.js +++ b/main.js @@ -1,9 +1,9 @@ -import "./style.css" import * as THREE from "three" import {OrbitControls} from "three/examples/jsm/controls/OrbitControls" import Hyperbeam from "@hyperbeam/web" (async () => { + const renderHyperbeam = renderScene() let embedURL = "" // Running locally and you have an embed URL? Set it here if (embedURL === "") { const room = location.pathname.substring(1) @@ -18,10 +18,10 @@ import Hyperbeam from "@hyperbeam/web" } embedURL = body.url } - main(embedURL) + setTimeout(renderHyperbeam, 4000, embedURL) })() -async function main(embedURL) { +function renderScene() { const scene = new THREE.Scene() const pointer = new THREE.Vector2() const raycaster = new THREE.Raycaster() @@ -44,10 +44,9 @@ async function main(embedURL) { // The default aspect ratio of the virtual computer is 16:9 const width = 0.62 const height = width * 9 / 16 - const texture = new THREE.Texture() - // force flipY to false, three.js is inconsistent with this behaviour + bootup.play() + let texture = new THREE.VideoTexture(bootup) texture.flipY = false - texture.generateMipmaps = false const geometry = new THREE.PlaneBufferGeometry(width, height) const material = new THREE.MeshBasicMaterial({ map: texture }) @@ -63,127 +62,129 @@ async function main(embedURL) { scene.add(checkerboardMesh(1, 15)) plane.add(sound) - const hb = await Hyperbeam(hbcontainer, embedURL, { - frameCb: (frame) => { - if (texture.image === null) { - if (frame.constructor === HTMLVideoElement) { - // hack: three.js internal methods check for .width and .height - // need to set manually for video so that three.js handles it correctly - frame.width = frame.videoWidth - frame.height = frame.videoHeight - } - texture.image = frame - texture.needsUpdate = true - } else { - renderer.copyTextureToTexture(new THREE.Vector2(0, 0), new THREE.Texture(frame), texture) - } - }, - audioTrackCb: tryAudio - }) - - window.addEventListener("resize", onWindowResized) - window.addEventListener("wheel", onWheel) - window.addEventListener("contextmenu", onContextMenu) - window.addEventListener("pointermove", onPointerMove) - window.addEventListener("pointerdown", onPointerDown) - window.addEventListener("pointerup", onPointerUp) - - onWindowResized() + function animate() { + window.requestAnimationFrame(animate) + controls.update() + renderer.render(scene, camera) + } animate() - function tryAudio(track) { - sound.setMediaStreamSource(new MediaStream([track])) - sound.setRefDistance(0.5) - // The audio context might be waiting on a user gesture - // In that case, we'll call sound.play() in the pointerdown handler - if (listener.context.state === "running") { - sound.play() + async function renderHyperbeam(embedURL) { + texture.dispose() + texture = new THREE.Texture() + texture.flipY = false // force flipY to false, three.js is inconsistent with this behaviour + texture.generateMipmaps = false + material.map = texture + + const hb = await Hyperbeam(hbcontainer, embedURL, { + frameCb: (frame) => { + if (texture.image === null) { + if (frame.constructor === HTMLVideoElement) { + // hack: three.js internal methods check for .width and .height + // need to set manually for video so that three.js handles it correctly + frame.width = frame.videoWidth + frame.height = frame.videoHeight + } + texture.image = frame + texture.needsUpdate = true + } else { + renderer.copyTextureToTexture(new THREE.Vector2(0, 0), new THREE.Texture(frame), texture) + } + }, + audioTrackCb: tryAudio + }) + + window.addEventListener("resize", onWindowResized) + window.addEventListener("wheel", onWheel) + window.addEventListener("contextmenu", onContextMenu) + window.addEventListener("pointermove", onPointerMove) + window.addEventListener("pointerdown", onPointerDown) + window.addEventListener("pointerup", onPointerUp) + + onWindowResized() + + function tryAudio(track) { + sound.setMediaStreamSource(new MediaStream([track])) + sound.setRefDistance(0.5) + // The audio context might be waiting on a user gesture + // In that case, we'll call sound.play() in the pointerdown handler + if (listener.context.state === "running") { + sound.play() + } } - } - - function onWindowResized() { - const w = window.innerWidth - const h = window.innerHeight - renderer.setSize(w, h) - camera.aspect = w / h - camera.updateProjectionMatrix() - } - function getPlaneIntersects() { - raycaster.setFromCamera(pointer, camera) - return raycaster.intersectObject(plane, false) - } + function onWindowResized() { + const w = window.innerWidth + const h = window.innerHeight + renderer.setSize(w, h) + camera.aspect = w / h + camera.updateProjectionMatrix() + } - function onWheel(e) { - if (getPlaneIntersects().length > 0) { - hb.sendEvent({ - type: "wheel", - deltaY: e.deltaY, - }) + function getPlaneIntersects() { + raycaster.setFromCamera(pointer, camera) + return raycaster.intersectObject(plane, false) } - } - function onContextMenu(e) { - if (getPlaneIntersects().length > 0) { - e.preventDefault() + function onWheel(e) { + if (getPlaneIntersects().length > 0) { + hb.sendEvent({ + type: "wheel", + deltaY: e.deltaY, + }) + } } - } - function handlePointer(e, type) { - pointer.x = (e.clientX / window.innerWidth) * 2 - 1 - pointer.y = -(e.clientY / window.innerHeight) * 2 + 1 - const intersects = getPlaneIntersects() - if (intersects.length > 0) { - // We disable the OrbitControls when the user's pointer is on the virtual computer - controls.enabled = false - const vector = new THREE.Vector3().copy(intersects[0].point) - plane.worldToLocal(vector) - hb.sendEvent({ - type, - x: vector.x / width + 0.5, - y: -vector.y / height + 0.5, - button: e.button - }) - } else { - controls.enabled = true + function onContextMenu(e) { + if (getPlaneIntersects().length > 0) { + e.preventDefault() + } } - } - function onPointerMove(e) { - handlePointer(e, "mousemove") - } + function handlePointer(e, type) { + pointer.x = (e.clientX / window.innerWidth) * 2 - 1 + pointer.y = -(e.clientY / window.innerHeight) * 2 + 1 + const intersects = getPlaneIntersects() + if (intersects.length > 0) { + // We disable the OrbitControls when the user's pointer is on the virtual computer + controls.enabled = false + const vector = new THREE.Vector3().copy(intersects[0].point) + plane.worldToLocal(vector) + hb.sendEvent({ + type, + x: vector.x / width + 0.5, + y: -vector.y / height + 0.5, + button: e.button + }) + } else { + controls.enabled = true + } + } - function onPointerDown(e) { - handlePointer(e, "mousedown") - } + function onPointerMove(e) { + handlePointer(e, "mousemove") + } - async function onPointerUp(e) { - handlePointer(e, "mouseup") - // If the audio context was suspended because there were no user gestures, - // resume the audio context now since the user interacted with the page - if (listener.context.state === "suspended") { - await listener.context.resume() - await sound.play() + function onPointerDown(e) { + handlePointer(e, "mousedown") } - } - function animate() { - window.requestAnimationFrame(animate) - controls.update() - renderer.render(scene, camera) + async function onPointerUp(e) { + handlePointer(e, "mouseup") + if (listener.context.state === "suspended") { // If the audio context was suspended because there were no user gestures, + await listener.context.resume() // resume the audio context now since the user interacted with the page + await sound.play() + } + } } + return renderHyperbeam } function checkerboardMesh(width, segments) { const geometry = new THREE.PlaneGeometry(width, width, segments, segments).toNonIndexed() - const material = new THREE.MeshBasicMaterial({ - vertexColors: true, - transparent: true, - side: THREE.DoubleSide - }) + const material = new THREE.MeshBasicMaterial({ vertexColors: true, transparent: true, side: THREE.DoubleSide }) const positionAttribute = geometry.getAttribute("position") const colors = [] - console.log(segments * segments, positionAttribute.count / 6) for (let i = 0; i < positionAttribute.count; i++) { colors.push(0, 0, 0, i % 6 === i % 12 ? 1 : 0) } diff --git a/style.css b/style.css deleted file mode 100644 index 287fbb0..0000000 --- a/style.css +++ /dev/null @@ -1,16 +0,0 @@ -html, body { - overflow: hidden; - background-color: #ff889b; -} - -#threejscontainer { - position: absolute; - top: 0; - left: 0; - background-color: #ff889b; -} - -#hbcontainer { - position: fixed; - visibility: hidden; -}