screenX screenY equivalent in p5.js

Wow, p5.js is awesome

I just look for a screenX screenY equivalent

together with orbitControl()

Thanks for a great language!

Chrisir

1 Like
2 Likes

I don’t understand a word here

How do I call it?

let screenCoor = projectWorldToCanvas( canvas, world ) ;

??

Thanks

Chrisir


 
  fill(0,255,0);
  translate(0,-37,0); 
  sphere(44);
  
  let screenCoor =   projectWorldToCanvas(  canvas, world   ) ; 
  
  pop();
}

function mousePressed() {
  
  //projectWorldToCanvas(canvas, vWorld) 
  // let canvasMy ;       projectWorldToCanvas(canvasMy , vWorld) ; 
  
  if (dist(mouseX, mouseY, 55, 55) < 46)
    colFlag = !colFlag;
}

/* Project a vector from World to Canvas coordinates. */
function projectWorldToCanvas(canvas, vWorld) {
  // Calculate the ModelViewProjection Matrix.
  var mvp = (canvas.uMVMatrix.copy()).mult(canvas.uPMatrix);

  // Transform the vector to Normalized Device Coordinate.
  var vNDC = multMatrixVector(mvp, vWorld);

  // Transform vector from NDC to Canvas coordinates.
  var vCanvas = createVector();
  vCanvas.x = 0.5 * (vNDC.x + 1.0) * canvas.GL.drawingBufferWidth;
  vCanvas.y = 0.5 * (vNDC.y + 1.0) * canvas.GL.drawingBufferHeight;
  vCanvas.z = 0.5 * (vNDC.z + 1.0);

  return vCanvas;
}

if I call it like this:

  var worldMy = createVector( 0,0,0 );
  let screenCoor =   projectWorldToCanvas(  canvas, worldMy    ) ;

I receive

TypeError: canvas.uMVMatrix is undefined (sketch: line 99)

p5.RendererGL: enabled webgl context

in

/* Project a vector from World to Canvas coordinates. */
function projectWorldToCanvas(canvas, vWorld) {
  // Calculate the ModelViewProjection Matrix.
  var mvp = (canvas.uMVMatrix.copy()).mult(canvas.uPMatrix);   // !!!!!!!!!!!!!!!!!! HERE 

  // Transform the vector to Normalized Device Coordinate.

?

I gather that of the 3 funcs in https://github.com/processing/p5.js/issues/1553
I only need projectWorldToCanvas ?
and not the other?

That’s overly complicated…

Is canvas = 2D and world = 3D?

Thanks for your help!

Chrisir

I’ve seen that there are many others with the same problem. So I’ve decided to build a small library that adds this functionality to p5js.

You’ll find the library here:

And an example of how it’s used here:
https://editor.p5js.org/bohnacker/sketches/nUk3bVW7b

3 Likes

Thanks a ton!

Chrisir

I had a problem why my port didn’t work and turned out I had the column order swapped.
Here a version that looks like the processing java source. I didn’t do any cleanup, the name of the function is _zoomX for example. The accepted answer seems also simpler, I drop this more for archive purposes.

const nonZero = function(a) {
    const FLOAT_EPS = 1.4E-45;
    return FLOAT_EPS <= Math.abs(a);
}


const m00 = 0; const m01 = 4; const m02 = 8;  const m03 = 12;
const m10 = 1; const m11 = 5; const m12 = 9;  const m13 = 13;
const m20 = 2; const m21 = 6; const m22 = 10; const m23 = 14;
const m30 = 3; const m31 = 7; const m32 = 11; const m33 = 15;



const screenXImpl_w = function(x, y, z, w) {

    const projection = this._renderer.uPMatrix.mat4;

    let ox =
      projection[m00]*x + projection[m01]*y + projection[m02]*z + projection[m03]*w;
    const ow =
      projection[m30]*x + projection[m31]*y + projection[m32]*z + projection[m33]*w;

    if (nonZero(ow)) {
      ox /= ow;
    }
    const sx = width * (1 + ox) / 2.0;
    return sx;
  }


const screenYImpl_w = function(x, y, z, w) {

    const projection = this._renderer.uPMatrix.mat4;

    let oy =
      projection[m10]*x + projection[m11]*y + projection[m12]*z + projection[m13]*w;
    const ow =
      projection[m30]*x + projection[m31]*y + projection[m32]*z + projection[m33]*w;

    if (nonZero(ow)) {
      oy /= ow;
    }
    let sy = height * (1 + oy) / 2.0;
    // Turning value upside down because of Processing's inverted Y axis.
    sy = height - sy;
    return sy;
  }

// const screenZImpl_w = function(x, y, z, w) {

//     const projection = this._renderer.uPMatrix.mat4;

//     let oz =
//       projection.m20*x + projection.m21*y + projection.m22*z + projection.m23*w;
//     const ow =
//       projection.m30*x + projection.m31*y + projection.m32*z + projection.m33*w;

//     if (nonZero(ow)) {
//       oz /= ow;
//     }
//     const sz = (oz + 1) / 2.0;
//     return sz;
// }


const _screenX = function(x, y, z) {

    const modelview = this._renderer.uMVMatrix.mat4;

    const ax =
      modelview[m00]*x + modelview[m01]*y + modelview[m02]*z + modelview[m03];
    const ay =
      modelview[m10]*x + modelview[m11]*y + modelview[m12]*z + modelview[m13];
    const az =
      modelview[m20]*x + modelview[m21]*y + modelview[m22]*z + modelview[m23];
    const aw =
      modelview[m30]*x + modelview[m31]*y + modelview[m32]*z + modelview[m33];
    return screenXImpl_w(ax, ay, az, aw);
}




const _screenY = function(x, y, z) {

    const modelview = this._renderer.uMVMatrix.mat4;

    const ax =
      modelview[m00]*x + modelview[m01]*y + modelview[m02]*z + modelview[m03];
    const ay =
      modelview[m10]*x + modelview[m11]*y + modelview[m12]*z + modelview[m13];
    const az =
      modelview[m20]*x + modelview[m21]*y + modelview[m22]*z + modelview[m23];
    const aw =
      modelview[m30]*x + modelview[m31]*y + modelview[m32]*z + modelview[m33];
    return screenYImpl_w(ax, ay, az, aw);
}


const _screenZ = function(x, y, z, w) {

    const projection = this._renderer.uPMatrix.mat4;

    let oz =
      projection[m20]*x + projection[m21]*y + projection[m22]*z + projection[m23]*w;
    const ow =
      projection[m30]*x + projection[m31]*y + projection[m32]*z + projection[m33]*w;

    if (nonZero(ow)) {
      oz /= ow;
    }
    const sz = (oz + 1) / 2.0;
    return sz;
}
1 Like