-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Fix camera tilt function to prevent orientation flipping #7598
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking this on, I think your approach looks good! Two things before merging:
- Since the pan/tilt/etc functions have been a tad buggy in the past, do you think we can add a unit test to check the result of the up vector after a tilt?
- Like your other recent PR, I assume this applies to p5 2.0 as well. Once this one is ready, could you also make a second PR into the
dev-2.0
branch?
src/webgl/p5.Camera.js
Outdated
@@ -2448,17 +2448,33 @@ p5.Camera = class Camera { | |||
rotatedCenter[1] += this.eyeY; | |||
rotatedCenter[2] += this.eyeZ; | |||
|
|||
// Compute new up vector to prevent flipping | |||
let forward = createVector( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The global createVector
function isn't available in instance mode, can we import the vector class directly and do new Vector(...)
here instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the review . I’ll refactor the code to avoid createVector while still keeping it clean and readable
Yes @davepagurek . I the unit tests have been added. It verifies the correctness of the up vector by computing the expected values after tilt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks @Forchapeatl! I'll merge this in, then could you also copy the changes into a PR for dev-2.0
?
I'm glad that the workaround I suggested when I originally reported the tilt bug proved to be of use. To be honest, I assumed that there would be a more efficient way of recalculating the up vector which is why I didn't attempt to apply the fix myself - that and the fact that I do not have a good understanding of the p5 library internals and do not know how to go about applying a fix anyway. Thanks so much Forchapeatl for bothering! However I have noticed one small inefficiency with the fix as it stands in the codebase. There are a couple of unnecessary calls to Vector.normalize() on intermediate vectors. Only the final version of the up vector needs to be normalized since only the directions of the intermediate cross products matter and these are unaffected by the magnitudes of the input vectors. |
Just spotted another small inefficiency and even a potential problem with the accepted fix. Currently:
This means that:
Would it not be better to have:
EDIT - It looks like the code I've quoted from Camera.js is not the final version as it still includes calls to createVector(). I'm still finding my way around GitHub so please forgive me if my comments above have already been addressed. |
Thank you for pointing out those inefficiencies! You're absolutely right about the unnecessary addition/subtraction of the eye coordinates and the delayed _rotateView(a, x, y, z) {
let centerX = this.centerX;
let centerY = this.centerY;
let centerZ = this.centerZ;
// move center by eye position such that rotation happens around eye position
centerX -= this.eyeX;
centerY -= this.eyeY;
centerZ -= this.eyeZ;
const rotation = p5.Matrix.identity(this._renderer._pInst);
rotation.rotate(this._renderer._pInst._toRadians(a), x, y, z);
// Apply the rotation matrix to the center vector
/* eslint-disable max-len */
const rotatedCenter = [
centerX * rotation.mat4[0] + centerY * rotation.mat4[4] + centerZ * rotation.mat4[8],
/* eslint-enable max-len */
// Translate the rotated center back to world coordinates
rotatedCenter[0] += this.eyeX;
rotatedCenter[1] += this.eyeY;
rotatedCenter[2] += this.eyeZ;
// Rotate the up vector to keep the correct camera orientation
/* eslint-disable max-len */
const upX = this.upX * rotation.mat4[0] + this.upY * rotation.mat4[4] + this.upZ * rotation.mat4[8];
const upY = this.upX * rotation.mat4[1] + this.upY * rotation.mat4[5] + this.upZ * rotation.mat4[9];
const upZ = this.upX * rotation.mat4[2] + this.upY * rotation.mat4[6] + this.upZ * rotation.mat4[10];
/* eslint-enable max-len */
this.camera(
this.eyeX,
this.eyeY,
this.eyeZ,
rotatedCenter[0],
rotatedCenter[1],
rotatedCenter[2],
upX,
upY,
upZ
);
} I was also able to avoid the createVector() call for the forward vector, as I'm now just working directly with the individual X, Y, and Z components. |
@franolichdesign Would you like to summit the fix on |
Unless I'm mistaken (which is quite possible!) I think some new issues have been introduced in the refactored code:
|
@franolichdesign , Please tell me your optimized approach . I am having a hard time visualizing this comment |
@franolichdesign or please maybe help me with a test snippet where this refactored code fails. |
Thanks for taking a look into this more! I haven't taken a close look at that implementation since it was unchanged in this PR, what bits are missing?
I think the call to
This is a good point, and worth updating in a follow-up PR if you (or @Forchapeatl) are interested in taking that on! |
@Forchapeatl Thank you so much for the kind offer to guide me through the process for submitting a fix. Unfortunately, I'm currently not able to set up my old laptop to test any code changes before submitting a fix (I desperately need to get a new computer!) My suggested alterations to the fix, including your nice optimization for calculating the up vector, would give:
I hope that my use of the p5.Vector() constructor is correct and would work in instance mode. |
Thank you @franolichdesign |
@Forchapeatl Do you have time to test and submit the latest changes? If not, how do we highlight these proposed changes so that another contributor can find and submit them? Should I raise another issue including the new code? |
Yes , please do , If no one takes it up , then I will do it during the weekend. Thank you for the reminder @franolichdesign |
Resolves #7377
Changes:
p5.Camera.tilt()
did not update the up vector.Screenshots of the change:
before
AwesomeScreenshot-3_13_2025.9_54_32AM.mp4
after
AwesomeScreenshot-3_13_2025.9_59_50AM.mp4
snippet
PR Checklist
npm run lint
passes