Hello!
Michael writing this week. We decided to delay last week’s newsletter until our Quest 3s arrived, so there’s a lot to update you on.
Quest 3
Laurent and I received our Quest 3s this week. I immediately unboxed mine, and I have to say I’m both impressed and frustrated. The pass-through, hand tracking, and scene understanding are quite impressive given the price point, but it’s frustrating that I spent $1500 on a Quest Pro less than a year ago, and it’s already rendered obsolete by a “non-pro” product. It isn’t the worst problem to have, but still.
I’ve moved my entire workflow over to the Quest 3, and I’m excited to share some demos with y’all.
MR.js
I’ve made a lot of progress with mr.js. This week’s update will focus on adaptive UI & physics-based interactions, but here are some other updates:
- improved default lighting & shadows
- surfaced the THREE.js layers API
With that said, let’s dive in.
Adaptive UI
I’m a firm believer in “show then tell,” and my partner had asked me to order a whiteboard for the apartment. So naturally, I opted to build one instead, knocking out two tasks at once.
Wow! An MR whiteboard, already very cool. You can checkout the full demo here!
…but what if you don’t have access to a headset?
Obviously, this is a Spatial Web company, but it wouldn’t be small-minded to totally exclude the rest of the web. So what would happen if I were to pull up this same demo on an iPad?
One code base, all platforms
A responsive interface isn’t a new concept. Pioneered by web developers in the early days of iOS/Android, it filled the need to serve different devices with a single code-base. As XR headsets become more ubiquitous, this need will resurface.
Mr.js is designed from the ground up to fulfill this need. Developers can write their spatial app once and expect it to fit any screen with minimal overhead.
<mr-app camera="camera: orthographic">
<mr-surface>
<mr-container>
<mr-column>
<mr-whiteboard id="board"></mr-whiteboard>
<!--markers-->
<mr-row height ="0.2" width="3">
<mr-button color="black"></mr-button>
<mr-button color="red"></mr-button>
<mr-button color="blue"></mr-button>
<mr-button color="green"></mr-button>
<mr-button color="yellow"></mr-button>
<mr-button color="purple"></mr-button>
<mr-button color="brown"></mr-button>
<mr-button color="orange"></mr-button>
<mr-button color="magenta"></mr-button>
<mr-button color="darkred"></mr-button>
<mr-button id="eraser" color="white"></mr-button>
</mr-row>
</mr-column>
</mr-container>
</mr-surface>
</mr-app>
This enables developers to comfortably build for the spatial web without alienating the planar web.
Physics-based events and interactions
The interactions for the above demo were achieved using Rapier.js. Rapier is a powerful physics’ engine, written in Rust and compiled to WASM, enabling performant physics simulations in real time.
This allows us to accurately detect collisions and generate events that can be captured using standard event listeners.
this.addEventListener('touch-start', (event) => {
this.context.beginPath();
this.drawStartPosition.copy(event.detail.position)
this.getCanvasPosition(this.drawStartPosition)
})
this.addEventListener('touch', (event) => {
console.log('touch');
this.drawPosition.copy(event.detail.position)
this.getCanvasPosition(this.drawPosition)
this.draw()
})
Some practical magic
Another update they may not have been entirely obvious from the above demo is our UI clipping implementation. Here’s a more practical example, and a bad magic trick for fun.
Clipping prevents content from flowing out of the UI window/panel, keeping things clean and organized.
til next time!
The code for the whiteboard demo can be found here, and the rest of mrjs can be found here. Star the repo and follow me on mastodon for more frequent updates (and magic).
michael.