# screenX screenY equivalent in p5.js

**URL:** https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581
**Category:** Coding Questions
**Created:** [April 23, 2019, 7:48pm UTC](https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581 "2019-04-23T19:48:05Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [April 23, 2019, 7:48pm UTC](https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581/1 "2019-04-23T19:48:05Z")

</div>

Wow, p5.js is awesome

I just look for a screenX screenY equivalent

together with orbitControl()

Thanks for a great language!

Chrisir

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [April 23, 2019, 7:53pm UTC](https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581/2 "2019-04-23T19:53:06Z")

</div>

> <https://github.com/processing/p5.js/issues/1553>

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [April 23, 2019, 8:08pm UTC](https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581/3 "2019-04-23T20:08:21Z")

</div>

I don’t understand a word here

How do I call it?

`let screenCoor = projectWorldToCanvas( canvas, world ) ;`

??

Thanks

Chrisir

```auto

 
  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;
}

```

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [April 23, 2019, 8:14pm UTC](https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581/4 "2019-04-23T20:14:16Z")

</div>

if I call it like this:

```auto
  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

```auto
/* 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 [Add screenX, screenY and screenZ · Issue #1553 · processing/p5.js · GitHub](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

---

<div class="post-metadata">

### Author: ![bohnacker](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/bohnacker/32/5868_2.png) [@bohnacker](https://discourse.processing.org/u/bohnacker)
#### Post date: [July 19, 2019, 2:18pm UTC](https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581/5 "2019-07-19T14:18:52Z")

</div>

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:

> **[bohnacker/p5js-screenPosition](https://github.com/bohnacker/p5js-screenPosition)**
>
> This function provides a solution to the missing screenX and screenY functions in p5.js. See https://github.com/processing/p5.js/issues/1553 for the discussion. - bohnacker/p5js-screenPosition

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

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [July 28, 2019, 11:38am UTC](https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581/6 "2019-07-28T11:38:44Z")

</div>

Thanks a ton!

Chrisir

---

<div class="post-metadata">

### Author: ![clankill3r](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/clankill3r/32/1098_2.png) [@clankill3r](https://discourse.processing.org/u/clankill3r)
#### Post date: [February 2, 2022, 1:03pm UTC](https://discourse.processing.org/t/screenx-screeny-equivalent-in-p5-js/10581/7 "2022-02-02T13:03:36Z")

</div>

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.

```auto
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;
}

```
