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

Allow three degrees of freedom in viewing a 3D object #615

Open
gwhitney opened this issue Mar 2, 2024 · 24 comments
Open

Allow three degrees of freedom in viewing a 3D object #615

gwhitney opened this issue Mar 2, 2024 · 24 comments

Comments

@gwhitney
Copy link

gwhitney commented Mar 2, 2024

Currently, a View3D allows the view azimuth and elevation to be controlled, but there does not appear to be a way to "roll" the view. We are considering using JSXGraph to revive the interactive diagrams in David Joyce's online Euclid's Elements (see https://mathcs.clarku.edu/~djoyce/java/elements/elements.html). In some of the 3D constructions, it is very useful to have full freedom in orienting the diagram, to help understand what is going one. Therefore, we would propose to allow all degrees of freedom in orienting the view of a View3D object, and would like to know if that enhancement would be a change that the maintainers of JSXGraph would perceive favorably.

If so, we are certainly willing to propose pull requests to implement such a feature. One approach would be to address #573 simultaneously: one natural interpretation of arbitrary drag events (on the "background" of a View3D object) would often include a "roll" component in the implied transformation to the 3D coordinates. So by allowing arbitrary background drags and interpreting them in this way, it would be possible to rotate the 3D view into an arbitrary orientation (possibly needing multiple drags to achieve an exact desired orientation).

@alfredwassermann
Copy link
Member

Thank you very much for suggesting this feature. Actually, it is already implemented and just has to be integrated into the code. My plan is to do it this week, before releasing the next version. However, for comparison, I encourage you to send a pull request, too.

In the 1990s, the site of David Joyce was the inspiration for me to start working on displaying math in the web browser.
So, I would be very happy to see it revived.

@gwhitney
Copy link
Author

gwhitney commented Mar 4, 2024

Well, we had not yet really gotten into the code; we are just looking for a starting point where we could begin to contribute and to get to know the code, and wanted to make sure our efforts would be welcome. We hadn't really started on implementing a third degree of freedom in orientation. If you are close on this feature, perhaps we should begin with an independent item where we can contribute without duplicating effort. I will open a new issue for the next item on our list of features needed to re-enable Joyce's constructions, to get your feedback.

(We already have a development browser extension that uses GeoGebra to revive all of Joyce's pages; you can send me a personal communication if you are interested in trying it. But GeoGebra is impossible to package into a published extension, because of how it's delivered, which is why we need to switch to your much lighter-weight package. Thanks for creating JSXGraph.)

@alfredwassermann
Copy link
Member

It is good that we waste efforts to simultaeously do the same thing. Let's go for the Sphere3D!

@alfredwassermann
Copy link
Member

Done with v1.8.0

@gwhitney
Copy link
Author

gwhitney commented Mar 8, 2024

Ooh, I was all excited to see it in action, but as you likely know even though the API reference now says v1.8.0, the examples are still running off of https://jsxgraph.org/docs/static/jsxgraphcore.js which is still v1.7.0.

@alfredwassermann
Copy link
Member

I'm pretty sure that this is a browser cache issue.

@gwhitney
Copy link
Author

Ah, right, because the file name of the javascript file isn't changing when you update versions.

@gwhitney
Copy link
Author

However, I am pretty sure there are still only two degrees of freedom in manipulating the view: as far as I can tell, when the x-axis is pointing straight at you, the z-axis must be pointing straight up; there doesn't seem to be any way to "roll" the view so that the z-axis is horizontal to the left and the y-axis is straight up, for example (with the x-axis still straight at you).

We would be happy to investigate adding the third degree of freedom into the manipulation of the view. If that's of interest to you, please do feel free to reopen this issue.

@alfredwassermann
Copy link
Member

You are completely right. So long we only addressed the part related to "free" dragging. However, I don't understand your suggestion above to include the missing rotation in the $yz$-plane by watching for a "roll component" in the gesture. Another possible solution could be the the following handling of input devices?

  • keyboard: arrow keys with an additional key pressed.
  • touch screen: two finger rotation gesture
  • Mouse device: require an additional key pressed.

@gwhitney
Copy link
Author

The reason that there are only two degrees of freedom available with the current drag interface is that the current interpretation of a drag is always vertical motion <-> elevation and horizontal motion <-> azimuth. If on the other hand you interpret any drag "naturally" as rotating an imaginary marble that you have grabbed at your down click point so that the corresponding point on the marble moves as close to your drag destination as possible, you now have access to all the rotations you need to achieve any orientation (although not in a single drag, since any one drag only has two degrees of freedom; we are implicitly using the noncommutativity of $SO_3$ here). For example, visit https://rufus31415.github.io/sandbox/3d-viewer/ and click the STL button at the left and select the skeleton, and play around with dragging: you will find you soon can relatively easily and intuitively put it in any orientation you want: looking right at you, lying horizontally but still looking right at you, feet straight at you but arm pointing in any direction you like, etc. This is the dragging mode I recommend for all 3D interaction (except possibly when there is a "horizon" that should be constrained to be horizontal, but that does not seem true in the setting of a general 3D geometric construction). That's what we would propose to implement in JSXGraph, at least as an option if not the default.

It might be wisest to go in two steps: first add a "roll" slider on the right in addition to the existing elevation and azimuth sliders, which would work independently of the existing sliders and current dragging behavior; then in a second PR change (or add an option to change) the dragging behavior.

Let us know what makes sense to you. Thanks!

@alfredwassermann
Copy link
Member

Now I understand! I browsed through the literature and found essentially these algorithms:

  • Hanson in Graphics Gems III
  • Chen
  • Shoemake
  • Bell

Nowadays, this handling of 3D scenes is mostly called virtual trackball. What algorithm do you suggest Hanson, Shoemake or Bell? Should I add it or do you want to do it?

One more question: In v1.8.0 we quietly added central projection as an option (We did not announce it because 3D point dragging is not yet implemented for this option). What kind of 3 degree of freedom handling do you suggest for central projection?

@alfredwassermann
Copy link
Member

Since the view3D event handling needs some refactoring to implement the 3 degrees of freedom, I will do it this week.

@Vectornaut
Copy link

Vectornaut commented Mar 19, 2024

What algorithm do you suggest

The one I'll recommend in the next comment isn't one of the four you mentioned. I see it as a descendant of Shoemake's ARCBALL.

For anyone following along, here are references for the rotation interfaces that @alfredwassermann mentioned, and some quick descriptive notes. I found the references in:

Method references and notes

Hanson's rolling-ball method

"The Rolling Ball" (in Graphics Gems III)

  • "[I]f you place your hand flat on top of a ball and move your hand in small horizontal circles, the ball will actually rotate about the vertical axis in the opposite direction. The rolling-ball algorithm for controlling spatial orientation is implemented [...] using the mouse [...] to emulate the actions of the palm of the hand."

Chen's Virtual Sphere controller

"A study in interactive 3-D rotation using 2-D control devices", with a correction in "Virtual trackballs revisited"

  • "Up-and-down and left-and-right movement at the centre of the circle is equivalent to "rolling" the imaginary sphere at its apex and produces rotation about the $x$-axis and $y$-axis respectively. Movement along (or completely outside) the edge of the circle is equivalent to rolling the sphere at the edge and produces rotation about $z$. The amount of rotation is adjusted so that a full sweep of the mouse across the circle rotates the object 180 degrees about the corresponding axis in the $x$, $y$ plane; a full circle around the outside rotates the object 360 degrees about $z$."

Shoemake's ARCBALL

"ARCBALL: A User Interface for Specifying Three-Dimensional Orientation Using a Mouse"

  • The mouse-down and mouse-up positions are projected to the front face of the trackball sphere and interpreted as the start and end of a geodesic arc.
  • "We give the user graphical feedback as the mouse is dragged, by drawing a "rubber-band" arc from the initial point to the current point, and updating a picture of the scene to show the rotation of the body or camera."

Bell's trackball

Described second-hand in "Virtual trackballs revisited"

  • "[V]ery similar to the virtual trackball implemented by Shoemake [26]. The difference is the function mapping points in the image plane to 3D points. While Shoemake maps the points onto a sphere, Bell maps them onto a surface made by combining a sphere and a hyperbola: if the 2D point is close to the center of the screen, the surface is a sphere, else it is a hyperbola."

@Vectornaut
Copy link

Vectornaut commented Mar 19, 2024

I'm pretty happy with the rotation interface I used in these slides. It's used with central projection there, but it should work with parallel projection too. Here's how it works.

  • The model you're rotating comes with a chosen rotation center.
  • When you grab a point on the model, you can drag it along a sphere around the rotation center.
  • As you drag, the cursor traces out a path on the sphere.
  • The sphere rotates so that:
    • The point you grabbed always stays under the cursor.
    • The sphere is always rotating along a great circle tangent to the path of the cursor.

I think of this as an infinitesimal version of Shoemake's ARCBALL. Every time a "mouse moved" event fires, you use ARCBALL to move the grabbed point from the last cursor position to the current one.

@alfredwassermann
Copy link
Member

Thanks a lot! However, in the above example sometimes the object (sculpture) is rotated, sometimes the viewport is rotated. Meanwhile, I made some progress with Bell's virtual trackball. Here is an example. Please, tell me your opinion! So far it only works for parallel projection, but this is just a matter of code organization.

For people coming here later: that test site might be unavailable in a few weeks from now.

@Vectornaut
Copy link

Vectornaut commented Mar 19, 2024

Thanks a lot! However, in the above example sometimes the object (sculpture) is rotated, sometimes the viewport is rotated.

Do you mean that the sculpture sometimes rotates in the opposite direction from what you expect? In this implementation, the only thing you can grab is the pink cubical cage that bounds the sculpture (which should become visible when you mouse over). If you grab a cage edge on the far side of the sculpture, the rotation could be confusing if you think you're grabbing the visible face of the sculpture.

This behavior could be changed with some work. I just didn't have time to change it, and I wasn't confident that any of the alternatives I had in mind would actually be better.

Meanwhile, I made some progress with Bell's virtual trackball. Here is an example. Please, tell me your opinion!

Whoa, this is really cool! The model doesn't rotate the way I expect, but I can't tell whether the problem is in my expectations or in the way the code runs on my browser.

If I load the page, click with my cursor over the center of the sphere, and drag toward the bottom of the screen, what rotation should I see? I expect the model to rotate along a great circle perpendicular to the screen, but it instead seems to rotate along the 0 meridian (drawn in blue stroke color).

@alfredwassermann
Copy link
Member

You are right, it does not yet do exactly what the user expects. Here is an example which I would like to have...

@gwhitney
Copy link
Author

Here is an example which I would like to have...

I agree, that example of mouse rotation interface is quite intuitive and allows all three degrees of freedom. Another tiny issue with the demo you put up (https://jsxgraph.uni-bayreuth.de/~alfred/jsxdev/3D/drag.html) is that if my click happens to lie directly atop the displayed axes, then the drag does nothing; the orientation of the display remains fixed. I understand that it this gesture may be interpreted as my trying to change the position of something that is fixed, but still it feels inconsistent with the fact that if I drag starting just a tiny bit off the axis, then the display does rotate. Just my two cents and please let us know if you would like any other concrete support from me and @Vectornaut on this subproject. Thanks!

@Vectornaut
Copy link

[...] if my click happens to lie directly atop the displayed axes, then the drag does nothing; the orientation of the display remains fixed. I understand that it this gesture may be interpreted as my trying to change the position of something that is fixed, but [...]

I also impulsively dragged over the displayed axis, and was momentarily confused when it didn't work.

One way to avoid this might be to give the View3D box specific handles (draggable points or lines), like other objects have. Dragging the handles could rotate the View3D around its center. This could be combined with any virtual trackball method; the handles would just control where you can initially grab the trackball.

I like the idea of making the corners of the box draggable. Since the view box clips most objects, this should ensure that there are always one or two handles visible, away from other objects.

@alfredwassermann
Copy link
Member

Now, dragging over the axis works. It is a good suggestion to add 3D handles. This is a job for our student's project in this summer term.

@gwhitney
Copy link
Author

Now, dragging over the axis works.

Indeed. Now really the only hitch is that the direction the visualization rotates does not visually match the direction the mouse pointer is moving on screen, making it a bit challenging to navigate to a desired orientation...

@Vectornaut
Copy link

Would it be useful for me to work on the virtual trackball next week? I'm in a good position to do this, because I've been studying the View3D internals for an upcoming pull request. I don't want to duplicate the summer student's effort, though.

@alfredwassermann
Copy link
Member

Yes. This would be very helpful!
Unfortunately, our student 's project did come into existence this summer :-(

@Vectornaut
Copy link

Awesome—I'll put the virtual trackball on my to-do list.

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

No branches or pull requests

3 participants