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

Solves issue #4214 #6734

Merged
merged 19 commits into from
Mar 12, 2024
Merged

Solves issue #4214 #6734

merged 19 commits into from
Mar 12, 2024

Conversation

Garima3110
Copy link
Member

@Garima3110 Garima3110 commented Jan 12, 2024

Changes:
Solves issue #4214

I have tried implementing the linePerspective() method to solve this issue.
@davepagurek Please let me know is this the right approach for its implementation or not.
I would love to have suggestions to this.
Thanks a lot!

Sample sketch:
https://editor.p5js.org/Garima3110/sketches/p8jRwB5dw

PR Checklist

@perminder-17
Copy link
Contributor

Thank you for your efforts, Garima. I apologize if I misunderstood your approach, but I have a concern about the linePerspective() function. It seems that the issue with the misbehavior of strokeWeight occurs after the perspective() function is called, right? In your sketch, it seems to happen by default when we remove the linePerspective(true/false) method. Additionally, when we use linePerspective(true/false), setting it to true seems to work well in your sketch. However, if someone sets linePerspective to false, it should use the default perspective camera. Perhaps we could implement something like this? Currently, when we use false, the stroke misbehaves in both cases, with and without the perspective call.

Actual

when linePerspective(false) with and without perspective
stroke actual

Maybe it should be like

stroke expected

I think opting for this approach could be the most straightforward, as opposed to delving into intricate calculations for a custom perspective. However, I'm not entirely certain if this is the correct solution. I apologize if my approach doesn't prove effective.

@Garima3110
Copy link
Member Author

I think opting for this approach could be the most straightforward, as opposed to delving into intricate calculations for a custom perspective. However, I'm not entirely certain if this is the correct solution. I apologize if my approach doesn't prove effective.

Thanks a lot @perminder-17 for your inputs. I'll just look into what's going wrong in here and get back to you soon!

* @example
* @todo
*/
p5.prototype.linePerspective = function (enable) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add a second overload to this function that has no parameters and returns the current value? Similar to frameRate

Copy link
Member Author

Choose a reason for hiding this comment

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

@davepagurek do you want me to validate its parameters too or this would work fine?

p5.prototype.linePerspective = function (enable) {
  if (enable !== undefined) {
    // Set the line perspective if enable is provided
    this._renderer._curCamera.useLinePerspective = enable;
  } else {
    // If no argument is provided, return the current value
    return this._renderer._curCamera.useLinePerspective;
  }
};

Copy link
Contributor

Choose a reason for hiding this comment

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

Validating parameters would be great too! Looks good so far.

@@ -329,7 +329,7 @@ p5.Shader = class {
this.setUniform('uPerspective', 1);
} else {
// strokes have uniform scale regardless of distance from camera
this.setUniform('uPerspective', 0);
this.setUniform('uPerspective', this._renderer._curCamera.useLinePerspective ? 1 : 0);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice!

@@ -488,7 +505,7 @@ p5.Camera = class Camera {
this._renderer = renderer;

this.cameraType = 'default';

this.useLinePerspective = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you think calling perspective() should set this to true and calling ortho() or frustum() should set this to false? A user could then override it with linePerspective(), but still match the defaults we have now.

Copy link
Member Author

@Garima3110 Garima3110 Jan 29, 2024

Choose a reason for hiding this comment

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

Yes maybe, I think it makes sense to associate the behavior of linePerspective() with the type of camera projection being used. If you're using perspective(), which simulates realistic perspective, having linePerspective() set to true by default aligns well with that mode. Similarly, when using ortho() or frustum(), which do not simulate realistic perspective, setting linePerspective() to false by default is appropriate.
This way, the default behavior aligns with the common expectations of how lines should behave based on the chosen camera projection.
let me know what's your take on this.
Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that makes sense! we can mention in the documentation for linePerspective that perspective(), ortho(), and frustum() all change the value of linePerspective, so you can call it after those calls to override it.

@Garima3110
Copy link
Member Author

Garima3110 commented Jan 29, 2024

Yeah sure! I’ll just do that and get back to you soon. thanks a lot for the review.

@Garima3110
Copy link
Member Author

@davepagurek Sorry to directly ping you here, but its just to tell you that I had made the changes suggested by you. Please review them whenever you find time . No hurries at all !
Thanks a lot..!

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.

Nice work! Just some minor comments on the docs formatting to be more consistent.

* consistent appearance.
*
* You can override the default behavior by explicitly calling `linePerspective()` after
* using perspective(), ortho(), or frustum(). This allows you to customize the line
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 do these as inline code too for consistency:

Suggested change
* using perspective(), ortho(), or frustum(). This allows you to customize the line
* using `perspective()`, `ortho()`, or `frustum()`. This allows you to customize the line

*
* @method linePerspective
* @memberof p5.prototype
* @param {boolean} enable - Set to `true` to enable line perspective, `false` to disable.
* @return {boolean} The boolean value representing the current state of linePerspective().
Copy link
Contributor

Choose a reason for hiding this comment

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

For other p5 methods that could either be a setter or a getter, we just do one of them in the doc comment (e.g. here, having a @param and no @return) and then adding a second doc comment right after the first with the alternate overload (e.g. a @return with no @param.) An example of that is here:

/**
* @method frameRate
* @return {Number} current frame rate.
*/

Can we do the same thing here too?

this._renderer._curCamera.useLinePerspective = enable;
p5._validateParameters('linePerspective', arguments);

if (!this._renderer._curCamera) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you encounter something in testing where where this wasn't defined out of curiosity?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, actually I got this on the console initially when i didn't write this if block :
image
For the sketch: sketch1.js
Sketch link: https://editor.p5js.org/Garima3110/sketches/p8jRwB5dw

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that's just happening because your setup is:

function setup() {
  createCanvas(400, 400);
  stroke(255);
  strokeWeight(2);
}

Doing createCanvas(400,400,WEBGL) causes the error to go away. Maybe rather than creating a camera in this if statement, we can throw an error saying that the method needs to be called in WebGL mode?

@Garima3110
Copy link
Member Author

@davepagurek I have made the changes as suggested. Please have a look , and let me know of any other change. Thank you!

@@ -329,7 +329,7 @@ p5.Shader = class {
this.setUniform('uPerspective', 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

I was testing out the example and realized that we still force perspective when using a default camera. Maybe we can take out this if statement and just use the else branch?

this._renderer._curCamera.useLinePerspective = enable;
p5._validateParameters('linePerspective', arguments);

if (!this._renderer._curCamera) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that's just happening because your setup is:

function setup() {
  createCanvas(400, 400);
  stroke(255);
  strokeWeight(2);
}

Doing createCanvas(400,400,WEBGL) causes the error to go away. Maybe rather than creating a camera in this if statement, we can throw an error saying that the method needs to be called in WebGL mode?

* perspective based on your specific requirements.
*
* @method linePerspective
* @memberof p5.prototype
Copy link
Contributor

Choose a reason for hiding this comment

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

I think elsewhere we tend to use he following syntax to say that it's a global p5 method:

Suggested change
* @memberof p5.prototype
* @for p5

* }
*
* function mousePressed() {
* perspective(PI/12, width/height, 1, 10000);
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this isn't the default camera perspective any more, when you click, both the perspective in the lines and for the overall image changes. Maybe it would show the difference more clearly if we just call linePerspective(false) without also changing the perspective of the scene?

@Garima3110
Copy link
Member Author

Thanks @davepagurek .I’ll work on these suggestions and get back to you soon!

@Garima3110
Copy link
Member Author

Garima3110 commented Feb 26, 2024

@davepagurek , Here's the sketch with the latest build including the changes you suggested:
https://editor.p5js.org/Garima3110/sketches/p8jRwB5dw
Please have a look. Thankyou!

@Garima3110
Copy link
Member Author

Garima3110 commented Feb 26, 2024

Doing createCanvas(400,400,WEBGL) causes the error to go away. Maybe rather than creating a camera in this if statement, we can throw an error saying that the method needs to be called in WebGL mode?

I am not exactly sure how to go about it , as I think directly writing this won't do the job:

  if (!this._renderer===constants.WEBGL) {
    throw new Error('linePerspective() must be called in WebGL mode.');
  }

It would be great if you could guide me through the process whenever you find time.
Thanks a lot..!

@davepagurek
Copy link
Contributor

Something pretty close to that! I think the way you would check would be:

if (!(this._renderer instanceof p5.RendererGL)) {
  throw new Error('linePerspective() must be called in WebGL mode.');
}

@Garima3110
Copy link
Member Author

Garima3110 commented Feb 27, 2024

image

Great! It works as expected. Thanks @davepagurek
And let me know for any further changes to this.

@davepagurek
Copy link
Contributor

Some last thoughts about the examples: right now it's a bit unclear what the difference is. How do you feel about:

  • Changing the rotation a bit (I tried rotateY(PI/24)) so you can see the cubes getting smaller into the distance more clearly in the small canvas size
  • Adding setAttributes({ antialias: true }) after creating the canvas to get a bit better line quality
  • Maybe making mouse click toggle back and forth rather than just turning off perspective? e.g. linePerspective(!linePerspective())
Screen.Recording.2024-02-27.at.11.50.39.AM.mov

@Garima3110
Copy link
Member Author

  • Changing the rotation a bit (I tried rotateY(PI/24)) so you can see the cubes getting smaller into the distance more clearly in the small canvas size
  • Adding setAttributes({ antialias: true }) after creating the canvas to get a bit better line quality
  • Maybe making mouse click toggle back and forth rather than just turning off perspective? e.g. linePerspective(!linePerspective())

Great suggestions @davepagurek I have made the changes please have a look!

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.

Awesome, thanks for all the changes! The examples look great, I think this is good to go.

@davepagurek davepagurek merged commit 9fce4ec into processing:main Mar 12, 2024
2 checks passed
@Garima3110
Copy link
Member Author

Awesome, thanks for all the changes! The examples look great, I think this is good to go.

Thanks a lot @dave for the help while working on this! Learnt a lot.

@Garima3110 Garima3110 deleted the stroke-weight branch May 31, 2024 08:28
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.

3 participants