Skip to content
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

Update computeNormals() to support smooth shading for buildGeometry() outputs #6553

Merged

Conversation

capGoblin
Copy link
Contributor

Resolves #6494

Update computeNormals to support smooth shading feature for buildGeometry outputs by incorporating vertex deduplication. Additionally, a new setting object, roundToPrecision, to enable rounding of vertex coordinates, addressing potential slight differences in calculations.

Changes:

  • Added support to smooth shading for buildGeometry() outputs by vertex deduplication.
  • Introduced the roundToPrecision setting for precise vertex coordinate rounding.
  • Updated inline function docs for the both shadingType and settings object params

PR Checklist

@capGoblin
Copy link
Contributor Author

I've revised the function documentation to accommodate the optional parameters. Definitely need feedback or suggestions for improvement on that.
And any other changes needed for the code?

Copy link
Contributor

@davepagurek davepagurek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work so far, this is looking good! Just a few comments to clean up the code a bit and explain to users how to use the feature.

* face.
* @method computeNormals
* @param {String} [shadingType] (optional) Shading type ('FLAT' for flat shading or 'SMOOTH' for smooth shading) for buildGeometry() outputs.
* @param {Object} [settings={ roundToPrecision: 3 }] (optional) Additional settings object with rounding precision for vertex coordinates when shadingType is 'SMOOTH'.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can try to match the style used for the options object in textToPoints?

* @param {Object} [options] object with sampleFactor and simplifyThreshold
THe type is just Object and the name is just the name, and above the parameters, they list all the options it can include and the default values.

* @chainable
*/
computeNormals() {
* computes smooth normals per vertex as an average of each
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we're augmenting this method's docs, a quick capitalization fix:

Suggested change
* computes smooth normals per vertex as an average of each
* Computes smooth normals per vertex as an average of each

src/webgl/p5.Geometry.js Show resolved Hide resolved
// loop through each vertex and add uniqueVertices
for (let i = 0; i < vertices.length; i++) {
const vertex = vertices[i];
const key = `${vertex.x.toFixed(roundToPrecision)},${vertex.y.toFixed(roundToPrecision)},${vertex.z.toFixed(roundToPrecision)}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have this big string here and then again on line 220. Maybe to make sure they're always in sync, we can put something like this above (maybe around line 200):

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

...so then here we could do const key = getKey(vertex) (and something similar on line 220)

*/
computeNormals() {
* computes smooth normals per vertex as an average of each
* face.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add a sentence or two explaining how this works, so that users will know what to expect from it? I think the information would be:

  • Normals are calculated for each face, and each vertex's normal is the average of its connected face normals
  • Flat shading leaves duplicated vertices disconnected, while smooth shading reconnects duplicated vertices so their face normals average together (or some other way of explaining this difference that makes sense to you)

computeNormals() {
* This function calculates normals for each face, where each vertex's normal is the average of the normals of all faces it's connected to.
* i.e computes smooth normals per vertex as an average of each face.<br>
* When using 'FLAT' shading, vertices are disconnected/duplicated i.e each face has its own copy of vertices.<br>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now for other methods like createFramebuffer (https://p5js.org/reference/#/p5/createFramebuffer), rather than passing in the string 'FLAT', we create a variable in constants.js like const FLAT = 'flat' and then in the code, check if the parameter is equal to constants.FLAT. That way users can pass it in as just FLAT (without quotes). Do you think we can do that for flat/smooth too for consistency?

*/
computeNormals() {
* This function calculates normals for each face, where each vertex's normal is the average of the normals of all faces it's connected to.
* i.e computes smooth normals per vertex as an average of each face.<br>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally in other docs, rather than explicitly adding a <br>, we just add a blank line between paragraphs (well, blank except for the * from the doc comment.) Maybe we can do this here too?

* helix = buildGeometry(() => {
* beginShape();
*
* for (let i = 0; i < TWO_PI * 3; i += 0.1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, this example kind of looks smooth just because there are a lot of triangles and the canvas is small. Maybe we can use a larger step size (0.6?) to make the flat shading more apparent?

* let radius = 20;
* let x = cos(i) * radius;
* let y = sin(i) * radius;
* let z = i * 10;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

orbitControl feels a bit off on this one right now because the z values aren't centered around 0, maybe we could use something like let z = map(i, 0, TWO_PI * 3, -30, 30);?

* fill(150, 200, 250);
* lights();
* orbitControl();
* model(helix);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would also be good to add an initial rotation (maybe rotateX(PI*0.2)) so you can see immediately that this is 3D. Maybe same for the other example too

*
* @method computeNormals
* @param {String} [shadingType] shading type ('FLAT' for flat shading or 'SMOOTH' for smooth shading) for buildGeometry() outputs.
* @param {Object} [options] object with roundToPrecision property.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than describing roundToPrecision here, can we describe the options in the descriotions above similar to how this doc does it? https://p5js.org/reference/#/p5/createFramebuffer

Copy link
Contributor

@davepagurek davepagurek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, thanks for all your updates!

@davepagurek davepagurek merged commit 7246a60 into processing:main Nov 17, 2023
2 checks passed
@capGoblin capGoblin deleted the enhancement/computeNormals-deduplication branch November 17, 2023 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow p5.Geometry::computeNormals() to work with buildGeometry() outputs
2 participants