p5.js icon indicating copy to clipboard operation
p5.js copied to clipboard

beginShape(TESS) does not respect UV coordinates when tessellating.

Open sflanker opened this issue 2 years ago • 1 comments

Most appropriate sub-area of p5.js?

  • [ ] Accessibility (Web Accessibility)
  • [ ] Build tools and processes
  • [ ] Color
  • [ ] Core/Environment/Rendering
  • [ ] Data
  • [ ] DOM
  • [ ] Events
  • [ ] Friendly error system
  • [ ] Image
  • [ ] IO (Input/Output)
  • [ ] Localization
  • [ ] Math
  • [ ] Unit Testing
  • [ ] Typography
  • [ ] Utilities
  • [X] WebGL
  • [ ] Other (specify if possible)

p5.js version

1.4.1

Web browser and version

No response

Operating System

No response

Steps to reproduce this

Steps:

  1. Use WEB_GL mode
  2. Specify a texture
  3. Draw a concave shape using beginShape(TESS) and specify UV coordinates

Expected

Tessellation should respect/preserve the specified UV coordinates.

Actual

The resulting set of vertices do not match the specified UV coordinates at all and the texture is displayed but very distorted.

Snippet:

let tex;

function preload() {
  tex = loadImage('checkerboard-spotlight.jpeg');
}

function setup() {
  createCanvas(400, 400, WEBGL);
  textureMode(NORMAL)
}

function draw() {
  background(220);
  orbitControl(4, 2, 0.1);
  scale(3, 3);
  translate(-50, -50);
  texture(tex);
  beginShape(TESS);
  vertex(20, 20, 0, 0);
  vertex(80, 20, 1, 0);
  vertex(80, 40, 1, 0.33);
  vertex(40, 40, 0.33, 0.33);
  vertex(40, 60, 0.33, 0.67);
  vertex(80, 60, 1, 0.67);
  vertex(80, 80, 1, 1);
  vertex(20, 80, 0, 1);
  endShape(CLOSE);
}

sflanker avatar Mar 09 '22 22:03 sflanker

I looked into this a little bit to see what it would involve. Our tesselation uses libtess, and I've found another I'm not 100% sure this is correct but I've found another library using libtess and it seems to indicate that it supports arbitrary vertex dimensions. The idea being, instead of passing in [x, y, z] per vertex, we pass in [x, y, z, u, v] (or if we have vertex colors and vertex normals, [x, y, z, u, v, r, g, b, nx, ny, nz]?) and interpolating all of those along with the position data.

If we were to do something like that, it would mean adding texture coordinates (and more) here, which is where we construct the data we pass to libtess: https://github.com/processing/p5.js/blob/05c93858bcf2ed8f7b1c4362cd459c8312369112/src/webgl/p5.RendererGL.js#L1484

We would then need to update our combine and vertex callbacks to handle the extra data, and put it back into p5's buffers when libtess is done. For the combine and vertex callbacks, the aforementioned library has an implementation of this already that we could borrow from.

I think the key is this line, which uses the vertex weights (Barycentric weights?) to interpolate all the data, not just the position, which is what is all that the library does for us and is what we are currently using: https://github.com/floorplanner/polygon-tools/blob/9ae3ec6/src/tesselator.js#L176

davepagurek avatar Jul 13 '22 01:07 davepagurek