vispy / vispy

Main repository for Vispy
http://vispy.org
Other
3.33k stars 618 forks source link

Improvements to cameras #647

Closed almarklein closed 9 years ago

almarklein commented 9 years ago

I already made some changes to the cameras in #612, and I have some further ideas for improvements.

1) Bounds The Visual class has a bounds method which subclasses must implement to expose their "coverage area". We should use these to automatically set the camera to show all the content in the scene. The SubScene object hasa get_scene_bounds() method that calculates the total bounds of the scene. The camera uses this when camera.reset() is called. A reset takes place the first time that a camera is associated with a viewbox. This means that if you first put visuals in the scene, and then assign a camera, things Just Work.

2) Zoom direction We should decide whether scrolling up or down zooms in. Similarly zooming with RMB. These two should also be consistent.

3) scale_factor on all cameras. In #612 I gave the BaseCamera a scale_factor property, which is initially determined from the range (in set_range), but can subsequently be modified to modify the scale. For the turntable camera this directly corresponds to zooming. For the Fly camera this determines the speed of the vessel. I did not apply this to the PanZoomCamera yet, but it should also directly correspond to zooming. Actually, I think we could bind the scroll wheel to this attribute in the base camara class.

4) center on all cameras. All camera's have some aspect of the center. The center of rotation for turntable, the center of the visible area for panzoom, and for the fly camera the position of the vessel. The center can be determined in set_range()

5) fov on all camera. Some visuals (like Volume), need this info, is convenient that its always there. Correction: Only PerspectiveCamera and derived classes need this parameter.

6) Multiple cameras / multiple scenes. Would be good to make it easy to have multiple cameras in one scene, and also to have one camera be used by multiple scenes. Both now works per #612.

7) aspect ratio of the scene. The scene or viewbox should have an aspect_ratio property, which is a 3-element tuple that defines the scaling of each dimension. Negative values indicate flipping of that dimension. Camera's should deal with this, and e.g. plots should be zoomable in two dimensions (unless this is disabled). I got this working pretty well in visvis (and I remember it was painful to implement :( )

Checklist (for what we agree on):

almarklein commented 9 years ago

@lcampagn and I had a gitter chat about this: here are some conclusions (Luke, please correct me if I am wrong or missed something):

almarklein commented 9 years ago

We also discussed the scale factor and bounds. An alternative to camera.set_range(), might be that the viewbox provides a means to get the total bounds for all objects in the scene, and that the camera queries this information when it wants to reset.

almarklein commented 9 years ago

All features are implement in #612, see example/scene/one_scene_four_cameras.py. Only the data aspect needs some work to get really right.

campagnola commented 9 years ago

1) I like set_range because 'bounds' and 'limits' somewhat imply a region that the camera should be confined to (the user may not move the camera outside this range). For automatically viewing certain visuals there is already PanZoomCamera.auto_zoom(visual), which is used by the plot functions. I might prefer camera.auto_range() to match set_range, though. Then viewbox.auto_range() would just be a shortcut for camera.auto_range(viewbox.scene).

2) Wheel up should zoom in; that is the standard I have seen in most applications. It should also be easily configurable (but we can worry about that later). If there are platforms with different expectations (OSX, I'm looking at you) then we could also make the default behavior platform-dependent.

Will have a look at the new example..

almarklein commented 9 years ago

Maybe I should have updated this post: set_range and auto_zoom are both gone. Instead, camera.reset() gets the bounds of the scene and sets the camera settings appropriately. Reset is called automatically the first time it is associated with a viewbox.

I always get confused what "scrolling up" means. But see the example and let me know whether it does what you expect :)

campagnola commented 9 years ago

Here's my current list of comments:

Non-issues:

Major issues:

Minor issues:

larsoner commented 9 years ago

Thanks for bringing this up -- it looks like a couple of PRs (#611 and #612) depend on sorting out these issues, so it would be good to work them out.

-

Not fond of reset(): it's not obvious what "resetting" a camera should do. I would prefer to be explicit. Possiblities:

I like "auto_view", since it automatically sets the view to encapsulate the whole scene.

I agree it is more explicit than "reset". It could take a scene or a single visual as an argument, although starting with a scene seems like a good / most widely used starting point.

-

I am not convinced it is worthwhile to have one camera in multiple views.

I also don't have any use cases in mind for two cameras.

I agree something like a "get_state" and "set_state" that return and take some object / state to set up the cameras would work well. To start you might have to always do "camera2.set_state(camera1.get_state())" at the end of each draw call. If users clamor for a way of automating this relationship, we can think about doing a publisher/subscriber framework or something. But if it cleans up the code to remove it, I'm happy to assume YAGNI or let users manually do it to start with.

-

Not fond of scale_factor.

I agree that your idea of using "zoom" as a relative operation is intuitive. If scale_factor is necessary for some application or Almar is really attached to it, maybe it could be rebranded as "zoom_factor" or something. :)

I'll let Almar comment on the minor issues since they seem more directly relevant to his / your implementations of cameras.

Cheers, Eric

almarklein commented 9 years ago

I like having BaseCamera.fov (=0 for PanZoomCamera)

Funny, I thought you were the one being against that at some point :)

Sure, we can rename reset()

I'll have a look how the code will look like when we allow just one viewbox per camera. I like your idea of syncing cameras instead. It also feels less awkward (as opposed to having a camera that is in two scenes at the same time).

The scale factor is sort of a generalization of a zoom factor. I did not call it zoom because the exact value and interpretation depends on the camera. E.g. in the fly camera it is used to establish a notion of the scale of the scene. In case of of per-axis zooming (as the panzoom camera can do), the scale factor applies to the first axis, and the aspect_ratio determines how the other axises (axi?) relate to it.

Having a zoom function with a relative value makes a lot of sense, especially since the specific value of scale_factor might seem a bit arbitrary to the user. I also do not see a user explicitly specify the scale_factor, but he/she might store and reset it, or set it from another camera.

is _center_loc relative to the local coord system? That's something we need to figure out.. Should cameras be moved like camera.pos = or camera.transform.translate = ?

It is relative to the parent coord system (in most cases the root of the subscene). Cameras adjust their own transform, so users should not use camera.transform directly.

Zooming is much less sensitive in PanZoom camera

Indeed, I played with these. Zooming of panzoom and Turntable should now be consistent. I think it was previously rather sensitive, but I can turn it up a bit if you want.

I'll have a go at this when I can find some time next week.

almarklein commented 9 years ago

Ok, I fixed most issues mentioned by Luke:

Remaining points:

larsoner commented 9 years ago

This sounds reasonable to me, and I don't have any strong opinions on the last few points. Are these changes part of #612, or are they on a different branch (volume2)?

almarklein commented 9 years ago

The are in #612. We still need a decision on camera.zoom().

almarklein commented 9 years ago

@lcampagn happy?

larsoner commented 9 years ago

FWIW I don't mind camera.scale_factor *= x, actually, so I'm okay with not having .zoom() now.

campagnola commented 9 years ago

Haven't had time to look at the camera changes yet, but I still see some issues in the examples (grid, viewbox, isosurface).

dirtyfish commented 7 years ago

view.set_camera('turntable', mode='perspective', up='z', distance=2,azimuth=30., elevation=65.) would now be?