Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#22123 closed defect (fixed)

Update Three.js template

Reported by: paulmasson Owned by:
Priority: major Milestone: sage-7.5
Component: graphics Keywords:
Cc: novoselt Merged in:
Authors: Paul Masson Reviewers: Andrey Novoseltsev
Report Upstream: N/A Work issues:
Branch: 48b47ed (Commits, GitHub, GitLab) Commit:
Dependencies: Stopgaps:

Status badges

Description (last modified by paulmasson)

This addresses three issues:

1) HTTPS is used to access the current CDN

2) Transparency is only set for opacity less that unity and the unnecessary depth write test is removed

3) A transparency issue for scenes with multiple objects is fixed by reseting mesh positions appropriately. This issue exists in the current implementation threejs on the cell server for objects created from IndexFaceSet

Change History (16)

comment:1 Changed 5 years ago by paulmasson

  • Authors set to Paul Masson
  • Component changed from PLEASE CHANGE to graphics
  • Type changed from PLEASE CHANGE to defect

comment:2 Changed 5 years ago by paulmasson

  • Branch set to u/paulmasson/update_three_js_template

comment:3 Changed 5 years ago by paulmasson

  • Cc novoselt added
  • Commit set to 79a7152bbf43fa662c7e62d32edfa7cce73db3d1
  • Description modified (diff)
  • Status changed from new to needs_review

New commits:

79a7152Update template

comment:4 Changed 5 years ago by paulmasson

  • Status changed from needs_review to needs_work

comment:5 follow-up: Changed 5 years ago by novoselt

So - what else needs work for these issues?

Regarding embedding this template as iframe - perhaps it would be better to have a visible border of the plot, given that it changes mouse behaviour? Nothing drastic, thin gray line would suffice.

comment:6 in reply to: ↑ 5 Changed 5 years ago by paulmasson

Replying to novoselt:

So - what else needs work for these issues?

Nothing for the issues already identified, but there is an outstanding transparency issue that I just figured out how to fix yesterday. I changed the status of the ticket so that no one would need to review it twice. The solution to this third issue is a bit involved and I want to clean up the code before pushing it here.

Regarding embedding this template as iframe - perhaps it would be better to have a visible border of the plot, given that it changes mouse behaviour? Nothing drastic, thin gray line would suffice.

The embedding is controlled server side so you can make that change any time. This ticket will only touch JavaScript.

comment:7 Changed 5 years ago by git

  • Commit changed from 79a7152bbf43fa662c7e62d32edfa7cce73db3d1 to 48b47ed3adf973b1dc66a4e75b4ae60326cce278

Branch pushed to git repo; I updated commit sha1. New commits:

48b47edReset mesh positions to fix transparency

comment:8 Changed 5 years ago by paulmasson

  • Description modified (diff)
  • Status changed from needs_work to needs_review

comment:9 Changed 5 years ago by paulmasson

For future reference, the rendering of transparent objects in Three.js is controlled by the position of the mesh. Two objects with the exact same center will render in the order in which they are added to the scene, so that one will always occlude the other. This will be a problem with intersecting planes and Jmol will always be more adept at handling this. One workaround will be to split planes into two parts along the line of intersection and add them to the scene as separate objects.

comment:10 Changed 5 years ago by novoselt

How could one implement it in a sensible way? Compute intersections of all sub-pieces on adding plots?

Perhaps it would make more sense to subdivide all planes into smaller pieces, or at least have some option for this?

comment:11 Changed 5 years ago by paulmasson

My comment was meant as an advisory to the end user and I can add something like it to the documentation for this viewer if desired. I should have been clearer since there are really two issues:

1) Compact objects need to have different positions for transparency to render properly.

2) Intersecting extended objects will have transparency issues even with different positions. It will be most immediately noticeable for planes but will exist for other objects, such as cylinders. This is an issue with WebGL in general, not just Three.js.

By the time the objects get to Three.js they're just vertices and faces, so the splitting would have to happen in Python, at least in implicit_plot3d and parametric_plot3d. Again, this is only for transparent objects as seen from certain angles, so I think we should wait and see how much of a problem it is for end users before making any complicated changes.

In any case, that's beyond the scope of this ticket.

comment:12 follow-up: Changed 5 years ago by novoselt

  • Reviewers set to Andrey Novoseltsev
  • Status changed from needs_review to positive_review

OK, it does improve the transparency situation! Can you please clarify multiplication by -1?

Continuing overall discussion - do I understand correctly that say several nested cylinders with the same parameters except for radius will not be drawn correctly ever??? And WebGL has no interest in fixing this situation? If so, what can be a sensible automatic workaround? Break all complicated objects into something like 1000 little triangles so that they almost never will intersect and when they do, defects will be small? Or we just hope that such situations are rare? Even a simple cube looks strange with opacity - as you rotate it it is obvious that facets are different! And they aren't exactly intersecting each other, just touching.

comment:13 in reply to: ↑ 12 ; follow-up: Changed 5 years ago by paulmasson

Replying to novoselt:

OK, it does improve the transparency situation! Can you please clarify multiplication by -1?

The method center() returns the vector used to center vertices in their own frame of reference, so moving the entire object needs to happen in the opposite direction.

Continuing overall discussion - do I understand correctly that say several nested cylinders with the same parameters except for radius will not be drawn correctly ever???

No, but the process will be difficult to automate. The is an additional parameter named renderOrder that can be manually attached to objects to help in these sorts of situations. It would be easy enough to add the feature but would take some explaining for people to understand why it might help.

And WebGL has no interest in fixing this situation?

Part of the reason to use Three.js is avoid having to learn too much about WebGL, but I guess now I'm committed to getting more details. I do know that the depth buffer that tracks object position does not respect transparency and that's the source of the problem. Here's an example that I think encapsulates that: rotate the planes vertically and you see how the transparency of each half shifts based on which one's center is closest to the front of the scene.

I don't yet know more details of the implementation, but I assume a choice had to be made to get 3D rendering to work at all in the browser, where resources are more limited than with a Java desktop environment. That might change as browsers gain calculational power.

If so, what can be a sensible automatic workaround? Break all complicated objects into something like 1000 little triangles so that they almost never will intersect and when they do, defects will be small?

That is possible, but would probably crash the browser. I can try testing it for possible future use. We should also look at how Jmol passes objects to JavaScript, even though it doesn't use WebGL.

Or we just hope that such situations are rare?

I think waiting for some feedback from users would be appropriate. My interest till now has been with opaque objects and WebGL is great for that. Let's see how important opacity is in practice.

Even a simple cube looks strange with opacity - as you rotate it it is obvious that facets are different! And they aren't exactly intersecting each other, just touching.

This is partly a result of the existing lighting. In order to get things started I just put lights above and below the frame, but we can change the default lighting. The current threejs implementation has lights from six directions IIRC: does it look better to you for a single cube?

comment:14 Changed 5 years ago by vbraun

  • Branch changed from u/paulmasson/update_three_js_template to 48b47ed3adf973b1dc66a4e75b4ae60326cce278
  • Resolution set to fixed
  • Status changed from positive_review to closed

comment:15 in reply to: ↑ 13 Changed 5 years ago by novoselt

  • Commit 48b47ed3adf973b1dc66a4e75b4ae60326cce278 deleted

Replying to paulmasson:

Replying to novoselt:

And WebGL has no interest in fixing this situation?

Part of the reason to use Three.js is avoid having to learn too much about WebGL, but I guess now I'm committed to getting more details. I do know that the depth buffer that tracks object position does not respect transparency and that's the source of the problem. Here's an example that I think encapsulates that: rotate the planes vertically and you see how the transparency of each half shifts based on which one's center is closest to the front of the scene.

Great example!

If so, what can be a sensible automatic workaround? Break all complicated objects into something like 1000 little triangles so that they almost never will intersect and when they do, defects will be small?

That is possible, but would probably crash the browser. I can try testing it for possible future use. We should also look at how Jmol passes objects to JavaScript, even though it doesn't use WebGL.

Note that Jmol actually has some WebGL implementation as well, maybe they have a workaround/solution - it is experimental and I never looked at it myself.

Even a simple cube looks strange with opacity - as you rotate it it is obvious that facets are different! And they aren't exactly intersecting each other, just touching.

This is partly a result of the existing lighting. In order to get things started I just put lights above and below the frame, but we can change the default lighting. The current threejs implementation has lights from six directions IIRC: does it look better to you for a single cube?

That was a complaint about transparency. Lighting-wise I think it would be nice to have different lights from different directions, not the same flood from everywhere. Try to rotate these spheres. For the old one the only reason you can notice rotation is that it is not a sphere, it has some corners. Your variant clearly shows where are top and bottom, but not left-right. I find it confusing and even with less contrived examples the lighting is kind of "flat". Now I noticed that jmol's version also has visible rotation only due to defects of the surface, but it is the most pleasing one, IMHO. And a big difference seems to be that jmol rotates everything keeping (a single?) light fixed, while threejs rotates objects together with lights. Is it possible to have fixed lights in threejs? That's is ideal for our applications, I think - you kind of have an object under a desk lamp, and rotate it to see different sides.

comment:16 Changed 5 years ago by paulmasson

Moving lighting discussion to #22261

Note: See TracTickets for help on using tickets.