fix(webgl): normalize nearly identical vertices before tessellation#8204
fix(webgl): normalize nearly identical vertices before tessellation#8204avinxshKD wants to merge 4 commits into
Conversation
|
🎉 Thanks for opening this pull request! For guidance on contributing, check out our contributor guidelines and other resources for contributors! Thank You! |
|
hey @davepagurek, kindly review when you get a chance |
There was a problem hiding this comment.
Hi, thanks for taking this on! The approach looks good. I was initially testing in p5 2.x, have we confirmed that this issue exists in 1.x? (Update: this exists in 1.x too, so we can keep this PR into main around, but we'll need another one into the dev-2.0 branch for 2.x.) Regardless, it may be a good idea to start by making the change just in 2.x, in the dev-2.0 branch instead of main.
| myp5.loadPixels(); | ||
|
|
||
| // Check that center pixels are white (hole cut out properly) | ||
| const centerIdx = (myp5.width / 2 + myp5.height / 2 * myp5.width) * 4; |
There was a problem hiding this comment.
Grabbing pixels out of an array can be hard for contributors to debug when something breaks a test in the future, do you think we could add this as a visual test instead?
Converted pixel-checking unit test to visual test as suggested by maintainer. This makes the test easier to debug when issues arise in the future.
Thanks for the review @davepagurek I've converted the pixel-checking unit test to a visual test as you suggested. And also created a separate PR targeting the dev-2.0 branch with the same fixes, since the file structure is different there (ShapeBuilder.js instead of p5.RendererGL.Immediate.js). Here's the link #8221 Thanks |
| if (Math.abs(prevZ - currZ) < epsilon) { | ||
| contour[i + 2] = prevZ; | ||
| } |
There was a problem hiding this comment.
Was there a reason for snapping the z coordinates as well? I don't think we need to do that for z?
| }); | ||
| }); | ||
|
|
||
| visualSuite('Tessellation', function() { |
There was a problem hiding this comment.
The new visual test doesn’t actually cover this change. I see the same output before and after the patch. Please update the sketch to reproduce the bug which is fixed at your PR.
Removed Z-axis coordinate normalization as testing confirmed it's not needed. Replaced simple test case with actual textToContours() example from issue processing#8186 that clearly demonstrates the tessellation bug and verifies the fix works. Resolves processing#8186
|
Hey @davepagurek @perminder-17, made the necessary changes. Please review whenever you get a chance. |
|
@perminder-17 @davepagurek can you pls check this one? Just checking if it still makes sense for me to continue working on it. This one was for the main branch as asked. Thanks |
|
Hey @perminder-17 @davepagurek @ksen0 updated the visual test, now uses hardcoded vertex data with a ~1e-8 coordinate offset that actually triggers the libtess bug. Old test was loading a font that didn't exist in test assets anyway. Also cleaned up the normalization loop and removed the extra screenshots that got committed by mistake
.
|
|
Hey @davepagurek @perminder-17 can you pls look into this, thanks. |


Resolves #8186
Changes
This PR fixes tessellation artifacts that occur when drawing shapes with multiple contours where consecutive vertices have nearly identical coordinates (differing by ~1e-8 or similar small amounts). This commonly happens when using
font.textToContours().test/unit/visual/cases/webgl.js:Implementation Details
Modified
_tesselateShape()insrc/webgl/p5.RendererGL.Immediate.js:1e-6(epsilon) of each other are normalized to use the exact same valueAdded comprehensive unit test in
test/unit/webgl/p5.RendererGL.js:Technical Background
This workaround addresses a numerical precision issue in libtess, which is a JavaScript port of SGI C code from the 1990s. When consecutive vertices have coordinates that are almost (but not exactly) equal, libtess produces glitchy tessellation output. This issue is particularly likely to occur with contours automatically sampled from fonts via
font.textToContours().Screenshots of the change
Before:
After (with this fix):
PR Checklist
npm run lintpasses