Skip to content

computeNormals(SMOOTH) causes seams around values close to 0 #6590

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
1 of 17 tasks
davepagurek opened this issue Nov 25, 2023 · 0 comments · Fixed by #6591
Closed
1 of 17 tasks

computeNormals(SMOOTH) causes seams around values close to 0 #6590

davepagurek opened this issue Nov 25, 2023 · 0 comments · Fixed by #6591
Assignees

Comments

@davepagurek
Copy link
Contributor

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
  • Internalization
  • Friendly Errors
  • Other (specify if possible)

p5.js version

main branch

Web browser and version

Firefox 117

Operating System

MacOS 14

Steps to reproduce this

Steps:

  1. Create custom geometry with vertices that should wrap around back on themselves and make a seamless gap
  2. Compute smooth normals

What actually happens is that you can still get a seam:
image

What seems to be happening is that around zero, some vertices end up being exactly 0, while some end up being very close to but not equal to zero, but negative, e.g. -1e-8. However, due to being slightly negative, when calling value.toFixed(3), you get -0.000 instead of just 0.000. Because we use toFixed to determine whether vertices are the same, these values end up not being the same, and we get a seam:

const getKey = vert =>
`${vert.x.toFixed(roundToPrecision)},${vert.y.toFixed(roundToPrecision)},${vert.z.toFixed(roundToPrecision)}`;

Snippet:

let tube;

function setup() {
  createCanvas(216, 216, WEBGL);
  describe("A rotating, warped tube");
  
  tube = buildGeometry(() => {
    let verticesPerRing = 20;
    let rings = 20;
    for (let ring = 0; ring < rings - 1; ring++) {
      beginShape(QUAD_STRIP);
      for (let i = 0; i <= verticesPerRing; i++) {
        for (let ringOffset of [0, 1]) {
          let y = map(ring + ringOffset, 0, rings, 70, -70);
          let angle = map(i, 0, verticesPerRing, 0, TWO_PI);
          
          // Rotate a line 70px from the tube center according to the angle
          let position = createVector(70, 0).rotate(angle);

          // Pick a random value between 0 and 1 that we'll use to squish
          // the tube in towards the center. The input to noise() changes
          // based on the position of the shape to get a smoothly changing
          // output.
          // If you were to set radius=1 instead, you would get a perfect
          // tube with no warping.
          let radius = noise(
            200 + position.x * 0.01,
            200 + y * 0.01,
            200 + position.y * 0.01
          );

          // Use radius to squish in towards the center of the tube
          let squishedPosition = createVector(
            position.x * radius,
            y,
            position.y * radius
          );
          if (i === 0 || i === verticesPerRing) {
            console.log(squishedPosition.array().map(v => v.toFixed(3)))
          }
          
          vertex(squishedPosition.x, squishedPosition.y, squishedPosition.z);
        }
      }
      endShape();
    }
  });
  tube.computeNormals(SMOOTH);
}

function draw() {
  background(255);
  orbitControl();

  lights();
  noStroke();
  specularMaterial(50);
  shininess(100);
  rotateY(frameCount * 0.01);
  model(tube);
}

https://editor.p5js.org/davepagurek/sketches/ycn3WTVtJ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant