Skip to content

Suggestion of a function to get screen coordinates #7059

Closed
@inaridarkfox4231

Description

@inaridarkfox4231

Increasing access

Proposal to implement functions like screenX(), screenY(), screenZ() in processing.

I often see suggestions that p5.js also needs a function to calculate screen coordinates.
I thought it would be good to have such a function, even if it's not the method I proposed here.

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • Build process
  • Unit testing
  • Internationalization
  • Friendly errors
  • Other (specify if possible)

Feature request details

I thought of a function like this:

p5.prototype.getNDC = function (v){
  const _gl = this._renderer;
  // Transfer to camera coordinate system using uMVMatrix
  const camCoord = _gl.uMVMatrix.multiplyPoint(v);
  // Calculate ndc using uPMatrix
  const ndc = _gl.uPMatrix.multiplyAndNormalizePoint(camCoord);
  // Drop into canvas coordinates.
  // The depth value is converted so that near is 0 and far is 1.
  const _x = (0.5 + 0.5 * ndc.x) * this.width;
  const _y = (0.5 - 0.5 * ndc.y) * this.height;
  const _z = (0.5 + 0.5 * ndc.z);
  // Output in vector form.
  return createVector(_x, _y, _z);
}

This is a function that calculates screen coordinates and depth values ​​from 3D coordinates for the currently set camera.
Screen coordinates are values ​​based on the coordinate system of the 2D canvas, and depth values ​​are 0 for near and 1 for far.

This kind of technique is actually already used in the p5.js library.

In #6116, when I improved orbitControl, it became necessary to obtain normalized device coordinates, so I implemented functions by suggestion of dave pagurek.
The method used here is based on that method.

"getNDC" is a temporary name and has no particular meaning. I think it needs to be changed with a proper name.

getNDC demo

let gr;

function setup() {
  createCanvas(400, 400, WEBGL);
  gr = createGraphics(400, 400);
  gr.textSize(20);
  gr.textAlign(CENTER,CENTER);
  noStroke();
}

function draw() {
  background(220);
  orbitControl();
  lights();
  fill(255);
  sphere(40);

  const ndc = getNDC(createVector(0,0,0));
  gr.clear();
  gr.text(ndc.z.toFixed(2), ndc.x, ndc.y);

  push();
  noLights();
  camera(0,0,1,0,0,0,0,1,0);
  ortho(-1,1,-1,1,0,1);
  translate(0,0,1);
  texture(gr);
  plane(2);
  pop();
}

p5.prototype.getNDC = function (v){
  const _gl = this._renderer;
  // Transfer to camera coordinate system using uMVMatrix
  const camCoord = _gl.uMVMatrix.multiplyPoint(v);
  // Calculate ndc using uPMatrix
  const ndc = _gl.uPMatrix.multiplyAndNormalizePoint(camCoord);
  // Drop into canvas coordinates.
  // The depth value is converted so that near is 0 and far is 1.
  const _x = (0.5 + 0.5 * ndc.x) * this.width;
  const _y = (0.5 - 0.5 * ndc.y) * this.height;
  const _z = (0.5 + 0.5 * ndc.z);
  // Output in vector form.
  return createVector(_x, _y, _z);
}
2024-05-19.09-02-24.mp4

Metadata

Metadata

Assignees

Type

No type

Projects

Status

DONE! 🎉

Status

Completed

Relationships

None yet

Development

No branches or pull requests

Issue actions