-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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 #7059 #7113
Solves issue #7059 #7113
Conversation
Please review the code , whenever some maintainer finds the time, Also if you have any idea or some sort of a suggestion, for what example code should i add for the inline documentation of |
Thanks for taking this on, the code looks good!
|
Yeah sure! @davepagurek |
@davepagurek Just wanted to know , I tried |
@Garima3110 |
|
Right I see, currently FES is still relying on the |
Actually just running |
@davepagurek Do the tests seem fine ? Please have a look and let me know if some changes need to be made. |
test/unit/core/environment.js
Outdated
test('worldToScreen for 3D context', function() { | ||
let worldPos = myp5.createVector(0, 0, 0); | ||
let screenPos = myp5.worldToScreen(worldPos); | ||
assert.isTrue(screenPos.x >= 0 && screenPos.x <= 100); |
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.
Do you think we can assert exact coordinates for the 3D tests like we do for the 2D tests instead of having a range like this? e.g. 50, 50 in this case, and I think 50, 100 in the second case?
test('worldToScreen for 2D context', function() { | ||
let worldPos = myp5.createVector(50, 50); | ||
let screenPos = myp5.worldToScreen(worldPos); | ||
assert.closeTo(screenPos.x, 50, 0.1); |
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.
This one is great! Can we add a test of rotation in 2D too?
I have added more tests , and made some changes according to the suggestions please have a look! |
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 making changes, and sorry for the delay! Got sick and then recovered in the mean time, but we're back now!
}); | ||
|
||
test('worldToScreen for a rotating cube in 3D', function() { | ||
myp5.push(); |
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.
This one doesn't assert anything so it might not work super well as a unit test, but this would be a cool example to have in the reference for this item! Maybe we could move it into the reference comments instead? (Same for the 2D case, having those as two examples would be great!)
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.
@limzykenneth in the 2.0 branch, is there an easy way to get a preview of how the docs will look, similar to grunt yui:dev
on the main branch?
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.
Not at the moment. The offline reference (which I also forked out here) can potentially help but it is not setup to work automatically yet.
test('worldToScreen with rotation in 2D', function() { | ||
myp5.push(); | ||
myp5.translate(50, 50); | ||
myp5.rotate(myp5.PI / 2); |
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.
I think since we translate before we rotate, the rotation doesn't end up actually affecting the position. If we rotate first, we should see an effect (I would expect (x, y) to become (y, -x) I think?)
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.
Wait, actually, ignore this -- it's only true if you're using (0,0) as your local coordinate. I see the offset by 10 does actually switch axes here!
|
||
test('worldToScreen with rotation in 3D', function() { | ||
myp5.push(); | ||
myp5.rotateY(myp5.PI / 2); |
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.
Similar comment here: just rotating won't affect the coordinates, so could we do a translation after this?
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.
actually, ignore that, as mentioned above, it should be ok as long as you're converting a nonzero coordinate. But it feels odd that the resulting coordinate would still be 50,50 since the untransformed example above also ends up at that. should this value be something else?
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.
actually, ignore that, as mentioned above, it should be ok as long as you're converting a nonzero coordinate. But it feels odd that the resulting coordinate would still be 50,50 since the untransformed example above also ends up at that. should this value be something else?
Maybe it should be 200,200
The default camera position in p5.js is at (0, 0, 800)
, looking towards the origin (0, 0, 0)
along the negative Z-axis. The camera's view is centered on the Z-axis, so any point on this axis is projected to the center of the screen.
rotateY(myp5.PI / 2)
rotates the point (50, 0, 0)
90 degrees around the Y-axis.
This rotation transforms the point (50, 0, 0)
into (0, 0, -50)
. After rotation, the point is 50 units in front of the origin along the negative Z-axis. After the rotation, the point (0, 0, -50)
is at a distance of 850 units from the camera (800 - (-50))
. The screen coordinates are calculated based on the projection of this point into the 2D view of the camera.
Since the rotated point lies directly on the Z-axis, its X and Y screen coordinates should map to the center of the canvas, so --> 200,200
What are your thoughts on this @davepagurek please let me know?!
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.
oh, I definitely didn't catch that this was a rotateY
-- I read it as just rotate
, which would have been around the z axis. That now explains why the local offset doesn't update the resulting screen x and y values. The 50,50 result now makes sense, since I think the canvas is only 100x100:
p5.js/test/unit/core/environment.js
Line 242 in 420067b
myp5.createCanvas(100, 100); |
So I think this result does actually make sense, and maybe we should just add one more test of rotation about the Z axis so that we can confirm that an example like the one you use in the 2D tests also works in WebGL.
* createVector(-50, 50, 50) | ||
* ]; | ||
* | ||
* push(); |
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.
How do you feel about moving this to draw()
and making the rotation change slowly over time?
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.
A great idea , will do this in a while.
* let rotationX = millis() / 1000; | ||
* let rotationY = millis() / 1200; | ||
* | ||
* rotateX(rotationX); |
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.
If we want to make sure the text itself isn't rotated, I think we might need to wrap the rotation + worldToScreen calls in a push/pop like you've got in the 2D mode example.
src/core/environment.js
Outdated
* noStroke(); | ||
* ellipse(pos.x, pos.y, 3, 3); // Draw points as small ellipses | ||
* fill(0); | ||
* text(`(${pos.x.toFixed(1)}, ${pos.y.toFixed(1)})`, pos.x, pos.y); |
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.
Are the screen coordinates relative to the top left? if so we may need to subtract width/2 and height/2 to keep these centered when drawing them in WebGL mode
src/core/environment.js
Outdated
* background(200); | ||
* | ||
* screenPos.forEach((pos, i) => { | ||
* text(`(${pos.x.toFixed(1)}, ${pos.y.toFixed(1)})`, pos.x, pos.y); |
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!
Sorry for the delay on this! I recently got the tests passing on the dev-2.0 branch, so if you pull that branch in your fork and merge it into this branch again, we can double-check that we get a green checkmark from the test runner and then merge if it looks good. |
While I continue troubleshooting the failed tests, I'm open to any suggestions you might have, @davepagurek! |
src/core/environment.js
Outdated
return new p5.Vector(screenCoordinates.x, screenCoordinates.y); | ||
} else { | ||
// Handle WebGL context (3D) | ||
const cameraCoordinates = renderer.uMVMatrix.multiplyPoint(worldPosition); |
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.
oh, maybe it's this -- we split up uMVMatrix
into uModelMatrix
and uViewMatrix
, and only update uMVMatrix
right before we draw a shape here:
Lines 579 to 584 in 4fbbaf5
_setMatrixUniforms() { | |
const modelMatrix = this._renderer.uModelMatrix; | |
const viewMatrix = this._renderer.uViewMatrix; | |
const projectionMatrix = this._renderer.uPMatrix; | |
const modelViewMatrix = (modelMatrix.copy()).mult(viewMatrix); | |
this._renderer.uMVMatrix = modelViewMatrix; |
Maybe we can refactor the bit that sets uMVMatrix
into a function on the renderer, like calculateCombinedMatrix()
, which gets called in _setMatrixUniforms
above, and then you can also call it here right before you make cameraCoordinates
?
Strange, all tests pass as I try this for the main branch but not here in the 2.0 branch. |
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.
I noticed a few places where it either wasn't accessing states
where it should, or was accessing it where it shouldn't, we can see if it works after this. The states
thing is new in the 2.0 branch so that's probably where the discrepancy is coming from, hopefully once that's fixed itll work again!
src/webgl/p5.Shader.js
Outdated
@@ -937,7 +937,7 @@ function shader(p5, fn){ | |||
const viewMatrix = this._renderer.states.uViewMatrix; | |||
const projectionMatrix = this._renderer.states.uPMatrix; | |||
const modelViewMatrix = (modelMatrix.copy()).mult(viewMatrix); | |||
this._renderer.states.uMVMatrix = modelViewMatrix; | |||
this._renderer.states.uMVMatrix = this._renderer.states.calculateCombinedMatrix(); |
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.
I think this method needs to be on the renderer and not the states:
this._renderer.states.uMVMatrix = this._renderer.states.calculateCombinedMatrix(); | |
this._renderer.states.uMVMatrix = this._renderer.calculateCombinedMatrix(); |
src/webgl/p5.RendererGL.js
Outdated
// Combines the model and view matrices to get the uMVMatrix | ||
// This method will be reusable wherever you need to update the combined matrix. | ||
calculateCombinedMatrix() { | ||
const modelMatrix = this.uModelMatrix; |
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.
I think this and the line below would need to access states
now:
const modelMatrix = this.uModelMatrix; | |
const modelMatrix = this.states.uModelMatrix; |
src/webgl/p5.RendererGL.js
Outdated
// This method will be reusable wherever you need to update the combined matrix. | ||
calculateCombinedMatrix() { | ||
const modelMatrix = this.uModelMatrix; | ||
const viewMatrix = this.uViewMatrix; |
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.
const viewMatrix = this.uViewMatrix; | |
const viewMatrix = this.states.uViewMatrix; |
Thanks for the clarification @davepagurek |
src/core/environment.js
Outdated
const modelViewMatrix = renderer.calculateCombinedMatrix(); | ||
const cameraCoordinates = modelViewMatrix.multiplyPoint(worldPosition); | ||
const normalizedDeviceCoordinates = | ||
renderer.uPMatrix.multiplyAndNormalizePoint(cameraCoordinates); |
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.
@davepagurek I have made some changes in the doc examples too, everything seems to work fine, please let me know if any other change needs to be done. |
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.
Sorry this took a while to review! In the process I finally figured out a way to preview the docs live in the p5.js-website repo 😅
Resolves #7059
Changes:
Here's a combined sketch that demonstrates the
worldToScreen
function in both 2D and WebGL contexts.https://editor.p5js.org/Garima3110/sketches/ilpG7v9Cw
Screenshots of the change:
PR Checklist
npm run lint
passes