ffd8 / P5LIVE

p5.js collaborative live-coding vj environment!
https://p5live.org
GNU General Public License v3.0
229 stars 35 forks source link

Hard Compile Question – XRSession Persistance – p5 recreation #95

Closed TiborUdvari closed 1 month ago

TiborUdvari commented 3 months ago

I'm working on improving the workflow with p5.xr, as I mentioned before in #88.

In WebXR the browser needs to start an XRSession with a user interaction, usually a button click. This works fine with P5LIVE. However any time there is a hard compile users currently need to start this session again by clicking, which kind of breaks the live coding flow.

I'm attempting to start and persist this session on the parent object, like so:

// Simplified code example
if (!window.parent.activeSession) {
  const xrSession = await window.parent.navigator.xr.requestSession('immersive-ar');
  this.__startSketch(xrSession);
} else {
  this.__startSketch(window.parent.activeSession);
}

Previous code w/o persistance in context

The persisting works in this case, although p5.js does not seem to be properly resetting. Notably the camera seems to be going back to the default settings.

I've isolated the part of the code that is not getting updated I think, but after the hard compile, setting matrices on the renderer just seem to set anything, for instance in the code below the headset is sending correct values it simply doesn't update he values in the matrix. It's really weird, I don't know how it's not possible to update this value.

  set view(newView) {
    this._view = newView;
    console.log('before set');
    console.log(this._view.transform.inverse.matrix);
    p5.instance._renderer.uMVMatrix.set(this._view.transform.inverse.matrix);
    console.log('after set');
    console.log(p5.instance._renderer.uMVMatrix.mat4);
    // result: the uMVMatrix always has the default values, it does not change, even though it should have been just set
...
}

Previous code in context

The code I'm using in p5 live is something like this. I also noticed that after hard compiling, the preload gets executed twice.

let libs = [
    'https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.1/p5.js',
    'https://cdn.jsdelivr.net/npm/@tiborudvari/p5.xr@0.4.67/dist/p5xr.js'
]

new p5(); 

function preload() {
    createARCanvas();
}

function draw() {
  sphere(1);
}

Any tips / ideas would be more than welcome. I've been trying to debug this for 2 days with no avail.

TiborUdvari commented 1 month ago

I'm still trying to figure this out ... do you have any pointers?

I think I have an old class of p5xr that is lingering around, it's pretty hard to debug. When I debug p5Frame.contentWindow.p5xr.instance.someUsefulVarIneed from the browser tools I get a value, but inside my client code I'm getting 0's.

I think there might be something with how the context gets teared down and recreated. For example when you load an external library why do you need to call the new p5() function again?

ffd8 commented 1 month ago

Heyhey – I'll have to borrow a headset from our institute to test – but you should be able to remove both loading p5.js manually and the new p5() – that was only needed to load a different version of p5.js than P5LIVE has built in. Can test running print(VERSION) in setup. If there's an issue from p5.js loading 2x - you can at the very top add //no p5 to prevent it, then from the code you have are manually loading a version.

TiborUdvari commented 1 month ago

Sorry, it's a little discombobulated question. I checked how p5LIVE handled reloading the sketch.

I don't understand my problem 100%, but in essence it seems when I hold on to a reference of an object that itself has references to p5, not everything gets recreated properly after a hard reload.

Issues start popping up when there are code checks like this for example in the set function of the p5.Matrix for example.

if (inMatrix instanceof p5.Matrix) {
   refArray = inMatrix.mat4;

Something to look out for if someone wants to hoist objects with references.

TiborUdvari commented 1 month ago

So I managed to get it work, should work starting from version 0.5.0 of p5xr.

Here is a quick snippet with a working setup if you even want to try it out. The headset needs to have this flag for a seamless experience though: https://p5xr.org/#/quick-start/tips

let libs = ['https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.10.0/p5.min.js', 
'https://cdn.jsdelivr.net/npm/p5.xr@latest/dist/p5xr.min.js'];

function setup() {
  createCanvas(0, 0, AR);
  describe("A cube waiting to be seen");
}

function draw() {
  background(255, 0, 0, 1);
  push();
  push();
  strokeWeight(4);
  fill(255, 0, 0);
  noFill();
  translate(0, 0, -0.5);
  rotateY(frameCount / 1000);
  scale(1.9);
  box(0.1, 0.1, 0.1);
  pop();

  pop();
}