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

Optical axis should look like it's passing through things. #283

Closed
pixelzoom opened this issue Dec 22, 2021 · 19 comments
Closed

Optical axis should look like it's passing through things. #283

pixelzoom opened this issue Dec 22, 2021 · 19 comments

Comments

@pixelzoom
Copy link
Contributor

pixelzoom commented Dec 22, 2021

Factored out of #125, because the optical axis is a separate project.

We want it to look like the optical image passes through the object, image, and projection screen. So it should be partially occluded by opaque things that are in front of it.

Here's am old mockup, from #125 (comment), showing the optical axis passing through the (old) projection screen:

image

And in #125 (comment), I said:

Splitting each object, image, and projection screen into 2 Nodes is going to be quite a mess. I'm speaking from experience, since I did this in Faraday's Electromagnetic Lab.

I'm going to investigate another approach, where the optical axis and rays are split into multiple Nodes. The optical axis seems straightforward, the rays wil be tricky.

@pixelzoom
Copy link
Contributor Author

pixelzoom commented Dec 22, 2021

The commit above uses 2 copies of OpticalAxisNode. One is in the far background, the other is in front of the object, image, and projection screen. The one in front uses a clipArea to show only the part of the optical axis that is in front.

This approach handles the object, real image, and projection screen. But it has these known problem:

  • Does not address the virtual image
  • Is buggy when the object is to the left of the focal point

So I'm going to have to rethink this...

@pixelzoom
Copy link
Contributor Author

pixelzoom commented Dec 22, 2021

Here are some screenshots showing how the optical axis passes through the object, real image, and projection screen respectively.

Note that the real image is transparent, so you can see the axis through it. Based on previous design discussions, I'm not sure that this was anticipated, so @arouinfar @kathy-phet FYI.

screenshot_1469

screenshot_1470

screenshot_1471

@pixelzoom
Copy link
Contributor Author

pixelzoom commented Dec 22, 2021

@arouinfar How do you want the F and 2F points to behave in situations where they are located at a position on the axis that is occluded by the object, image, or projection screen? Example cases are shown below. Dynamically adjusting the rendering order for the points (so that they are occluded by the object, image, projection screen) is possible, but not easy, might be distracting, and it could be confusing if these points disappear. And I definitely don't want to be trying to show a partial point, for example as the point passes "through" the object.

I need a reply with high priority, because this affects whether I continue with the current approach, or have to switch to something else.

screenshot_1474

screenshot_1472

@pixelzoom pixelzoom removed their assignment Dec 22, 2021
@pixelzoom pixelzoom changed the title Optical axis should pass through object, image, and projection screen. Optical axis should look like it's passing through things. Dec 22, 2021
pixelzoom added a commit that referenced this issue Dec 22, 2021
@pixelzoom
Copy link
Contributor Author

pixelzoom commented Dec 22, 2021

Notes from Zoom meeting with @arouinfar:

  • This approach is looking good.

  • An approach of splitting each object into foreground and background Nodes would have 2 major problems: a confusing Studio tree (or confusing code to fix the confusing Studio tree), and possibly a vertical seam in the transparent real/virtual image.

  • F and 2F points should always be in the foreground. We do not want them to be occluded.

  • These 2 checklist items are caused by the same problem:

  • Does not address the virtual image
  • Is buggy when the object is to the left of the focal point
  • For the real & virtual image, would like the part of the optical axis that's occluded by the image to be more transparent. Add a mask behind the right half of the real image (left half of virtual image), filled with the background color, and with a bit of transparency (e.g. opacity: 0.95).

  • For rays in Rays should look like they're passing through things. #125:

    • For real image, use this same approach.
    • For virtual image, do nothing. Do not want the rays to look like they're going through the (solid) object.
    • For projection screen, do nothing, the current look is desired.
  • None of this is relevant for the arrow representation, because it's a flat 2D representation.

@pixelzoom
Copy link
Contributor Author

pixelzoom commented Dec 22, 2021

In the above commit, I added support for virtual image. This requires a clipArea composed of 2 rectangles. From the code:

// For a source object and virtual image, clipArea is 2 rectangles.
// The first rectangle is between the object and optic.
// The second rectangle is between the image and left edge of the picture frame.

Next up is adding the mask to make the optical axis appear more "faint" where it's occluded by the image.

@pixelzoom
Copy link
Contributor Author

pixelzoom commented Jan 3, 2022

The remaining bit of work here from #283 (comment) is:

  • For the real & virtual image, would like the part of the optical axis that's occluded by the image to be more transparent. Add a mask behind the right half of the real image (left half of virtual image), filled with the background color, and with a bit of transparency (e.g. opacity: 0.95).

The most straightforward way to create the mask would be to use scenery.Image hitTestPixels: true and getSelfImage, which should return the Shape for the mask. But that feature of Image appears to be broken, and has in fact never been used, see phetsims/scenery#1333. I'll wait to hear from @jonathanolson before deciding if I need to investigate a workaround.

@pixelzoom
Copy link
Contributor Author

In the above commit, I'm using Image getSelfShape with hitTestPixels: false for now. This results in a rectangular mask, as show by the red stroke in the screenshot below with ?debugMask. This doesn't behave correctly above/below the non-transparent part of the image, but we'll live with it until @jonathanolson fixes phetsims/scenery#1333.

screenshot_1489

@pixelzoom
Copy link
Contributor Author

@arouinfar This can be reviewed before phetsims/scenery#1333 is resolved. Just keep in mind that the image mask is currently a rectangle, not the shape of the picture frame. The current opacity of the image mask is 0.8. Let me know if you'd like to see more or less of the occluded optical axis. Note that this opacity will also affect how much of the occluded rays are seen.

@pixelzoom
Copy link
Contributor Author

pixelzoom commented Jan 6, 2022

There's a mirror case that is incorrect. See the Object in the screenshot below. Back to me to fix this.

screenshot_295

@pixelzoom pixelzoom assigned pixelzoom and unassigned arouinfar Jan 6, 2022
@arouinfar
Copy link
Contributor

Thanks @pixelzoom. The optical axis looks good in the screenshots (thanks for showcasing all of the permutations!) and in master.

Things can sometimes look a little strange when the object and image are close to one other, such as in this case:
image

Steps to reproduce:

  1. Lens screen, select concave lens
  2. Move object as close as possible to the lens
  3. Set index of refraction to the maximum value

I think this is an acceptable edge case, but I wanted to bring it to your attention in case there's something else going on with the clipping regions.

@pixelzoom
Copy link
Contributor Author

The problem demonstrated in the scenario shown in #283 (comment) is that the implementation is using the nominal width of the framed Image to compute the clipArea. It needs to use scale width of the framed Image. There's a TODO related to this in

 const halfFrameWidth = 34; //TODO get this from sourceObject.boundsProperty, or from sourceObjectNode

I'll work on correcting that.

@pixelzoom
Copy link
Contributor Author

The scenario in #283 (comment) has been fixed, see screenshot below. Any remaining weirdness should be related to phetsims/scenery#1333, so I'll leave this open until that issue is fixed. Labeling as on-hold.

screenshot_1502

@pixelzoom
Copy link
Contributor Author

pixelzoom commented Jan 18, 2022

In the above commit, I've added a workaround for the bug in phetsims/scenery#1333. I'm explicitly creating shapes that match the "framed object" images. Tracking removal of that workaround in #296.

@arouinfar please review in master. If it looks OK, assign back to me.

@arouinfar
Copy link
Contributor

Looks good in master, back to you @pixelzoom.

@arouinfar arouinfar assigned pixelzoom and unassigned arouinfar Jan 18, 2022
@pixelzoom
Copy link
Contributor Author

#296 tracks remaining work, so closing this issue.

@pixelzoom
Copy link
Contributor Author

pixelzoom commented Jan 20, 2022

For posterity... At 1/20/22 design meeting, @ariel-phet asked about an approach where the optical axis is drawn in foreground/background segments. I initially went down that path, then discovered that the dashed pattern of the line would move around. So as you dragged the Object, the axis appeared to scroll. I could have tried resolving that using lineDashOffset, but it seemed a little too fiddly/brittle.

@pixelzoom
Copy link
Contributor Author

For the record... After "scenes" were introduced in #217, it became possible to use a different approach when the selected object is a light source. Instead of using clipArea, a foreground copy of the optical axis is drawn from the left edge of the screen to its intersection with the projection screen. Because the left edge is the same as the background optical axis, there's no movement of the dash pattern. This implementation has better performance, and appears in 397a6e1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants