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

Add ArrowVisualizer #97

Merged
merged 7 commits into from
Apr 19, 2019
Merged

Add ArrowVisualizer #97

merged 7 commits into from
Apr 19, 2019

Conversation

tkoolen
Copy link
Collaborator

@tkoolen tkoolen commented Mar 27, 2019

(On top of #96).

Adds an ArrowVisualizer type, which enables easy visualization of 3D arrows consisting of a cylinder for the shaft and a cone for the head.

I took inspiration from MechanismVisualizer, in that ArrowVisualizer is basically a cheap-to-construct abstraction layer around a Visualizer (in this case two Visualizers) with a higher-level interface for setting the transforms.

One issue is that this doesn't work with AnimationVisualizer quite yet, because the transformations I'm computing aren't rigid transformations, and so trying to extract out just the translation and rotation doesn't work. @rdeits, what do you think about this? It's quite unfortunate that we have to decompose the transform in this way; can't we just set the matrix directly when creating animations? I guess we can extract out and set scale as well, but ideally I'd like to avoid going back and forth.


ArrowVisualizer(vis::AbstractVisualizer) = ArrowVisualizer(vis[:shaft], vis[:head])

function setobject!(vis::ArrowVisualizer, material::AbstractMaterial=defaultmaterial();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is kind of a non-standard method for this function. What do you think?

function settransform!(vis::ArrowVisualizer, base::Point{3}, vec::Vec{3};
shaft_radius=0.01,
max_head_radius=2*shaft_radius,
max_head_length=max_head_radius)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keyword arguments could also be properties of ArrowVisualizer. Do you think that's better?

@codecov-io
Copy link

codecov-io commented Mar 27, 2019

Codecov Report

Merging #97 into master will increase coverage by 1.55%.
The diff coverage is 93.1%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master     #97      +/-   ##
=========================================
+ Coverage   73.65%   75.2%   +1.55%     
=========================================
  Files          12      13       +1     
  Lines         334     363      +29     
=========================================
+ Hits          246     273      +27     
- Misses         88      90       +2
Impacted Files Coverage Δ
src/MeshCat.jl 30.43% <ø> (ø) ⬆️
src/lowering.jl 81.42% <0%> (-1.19%) ⬇️
src/arrow_visualizer.jl 100% <100%> (ø)
src/animation_visualizer.jl 81.25% <75%> (-0.9%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 43f206f...6f97e74. Read the comment docs.

@tkoolen
Copy link
Collaborator Author

tkoolen commented Mar 27, 2019

Hold on, I didn't get the transforms right.

@rdeits
Copy link
Owner

rdeits commented Apr 5, 2019

Sorry for not responding sooner to this! I think this is a great idea, and I've wanted a nicer way to draw arrows for quite a while. I do think, though, that we should try to make it compatible with the existing animation system.

I agree that it's awkward to have to decompose the transform, but I think it's an unavoidable part of dealing with three.js. Three.js only understands how to animate vectors and quaternions, not full transformation matrices. Fortunately, three.js already knows how to animate the "scale" property, so I think I can make this just work with a small tweak to the julia-side animation code. Let me see...

@tkoolen tkoolen force-pushed the tk/arrow-visualizer branch from 4f9524e to 3b70624 Compare April 6, 2019 23:36
@rdeits
Copy link
Owner

rdeits commented Apr 11, 2019

Ready to go?

@tkoolen
Copy link
Collaborator Author

tkoolen commented Apr 11, 2019

Yeah, as long as you're OK with the setobject! method signature and the settransform! kwargs.

@tkoolen tkoolen force-pushed the tk/arrow-visualizer branch from 3b70624 to f4db540 Compare April 11, 2019 15:30
@tkoolen
Copy link
Collaborator Author

tkoolen commented Apr 11, 2019

Actually, with animations, the interpolation seems to be a little problematic. For example:

image

Not sure if this is a bug or just a consequence of the interpolation method in combination with the fact that an arrow is not a single object.

As a workaround / way to debug, is there a way to completely disable interpolation on the three.js side?

@rdeits
Copy link
Owner

rdeits commented Apr 19, 2019

Ah, yeah, that's probably an effect of the interpolation. After all, linearly interpolating the shaft and head transforms independently isn't going to necessarily produce a rigid motion of the arrow.

I think it's possible to turn off interpolation in three.js, but I don't have an API for it. On the plus side, I think this is pretty easy to fix. The reason we don't see this problem in MeshCatMechanisms is that the mechanism's tree structure is reflected in the MeshCat tree structure, so subtrees always move together even if the interpolation is inaccurate. We should be able to do the same thing here: we can change the arrow visualizer from this:

shaft_vis
head_vis

into this:

arrow_vis
  | shaft_vis
  | head_vis

We then have to apply the arrow's translation, rotation, and length scaling to the whole arrow_vis, rather than applying it to the shaft and head independently. We'll also need to apply the inverse of the arrow scaling to the head so that it doesn't shrink and grow with the arrow.

If we do this right, the transform from shaft to head should stay rigid despite the interpolation.

@tkoolen
Copy link
Collaborator Author

tkoolen commented Apr 19, 2019

We then have to apply the arrow's translation, rotation, and length scaling to the whole arrow_vis

Ideally (as it is currently implemented), I want:

  • the arrowhead to always have the same shape, only scaling it (uniformly in all directions) when the height of the arrowhead is smaller than the length of the vector.
  • the radius of the shaft to be constant.

I feel the combination of these two features works better for arrows that vary in length a lot, and it's in conflict with naively transforming the whole thing, which would result in either arrows with a huge shaft radius which quickly engulf the whole scene, or weirdly stretched arrowheads.

@rdeits
Copy link
Owner

rdeits commented Apr 19, 2019

Yup, makes sense. I think tkoolen#3 handles all that. After all, I'm applying exactly the same total transformation in that PR that you were previously--the only difference is that by rearranging the visualizer, I'm giving three.js more information about how to animate it properly.

@tkoolen
Copy link
Collaborator Author

tkoolen commented Apr 19, 2019

Ah, great, yes, this looks like a good solution then.

@tkoolen
Copy link
Collaborator Author

tkoolen commented Apr 19, 2019

Good to go now from my perspective.

@rdeits rdeits merged commit 39a0e0d into rdeits:master Apr 19, 2019
@rdeits
Copy link
Owner

rdeits commented Apr 19, 2019

Excellent!

@tkoolen tkoolen deleted the tk/arrow-visualizer branch April 19, 2019 19:17
@dehann
Copy link
Contributor

dehann commented Apr 20, 2019

This is very cool!

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

Successfully merging this pull request may close these issues.

4 participants