The RhinoDemo, 4 windows but the same HelixViewport3D

Anonymous 9 years ago 0
This discussion was imported from CodePlex

HDNguyen wrote at 2012-03-13 20:33:

Hi Objo

I am studying Helix and find it very good. I try also to extend the example RhinoDemo at the first place but without success. Could you help me ?

As you know the RhinoDemo has actually 4 windows with 4 not related HelixViewport3D. What I try to extend is the left window that contain the main HelixViewport3D and should show the HelixViewport3D with a FrontView, the right window shows the BackView, the bottom left shows the LeftView and the bottom right shows the RightView but of the same HelixViewport3D

Is it possible with WPF 3D in general and specifically with Helix ? What should we do so that we can have 2 or more windows show the same Viewport3D but with different camera look direction and camera positions ?

govert wrote at 2012-03-13 22:26:

You're seeing a place where the WPF design and the Helix Toolkit design does not fit together so well. I'd also love to hear Objo's response, but can give some background (filled with a painful amount of jargon).

In WPF there is a Visual tree, and every Visual (say a BoxVisual3D) can appear only once in the Visual tree. A Viewport3D (which has the Camera) is itself a Visual, and will display its Visual3D children, so those Visual3D children can appear in at most one Viewport3D. So if we want to see the same 'scene' from different Camera positions (in different Viewport3Ds), the different Cameras have to be looking at _different_ ModelVisual3Ds.

Now, different ModelVisual3Ds can display the same Model3D. This makes me prefer an approach which puts the geometry construction on the Model3D side, rather than to have the Visual3Ds build the mesh, as happens in the various Visual3D classes in the current Helix Toolkit.

For example, say you want a draw a Box that will have some fixed dimensions (Length x Width x Height) and you want to see it in different Viewport3Ds (like in the different RhinoDemo views). Then you certainly need to have at least one Visual3D of your box for each Viewport3D (say we have four Viewport3Ds) - this is just how WPF works. But the current design in the Helix Toolkit might lead you to make a BoxVisual3D with the right dimensions, which can then only be displayed once (in one Viewport3D). So you'll end up making four BoxVisual3Ds, each with the same dimensions etc., but representing a single box in the 'real' world.

One might prefer to have the four Visual3Ds share a single Model3D (probably a GeometryModel3D with a MeshGeometry, which could be textured etc.) That way there is one shared Box model, displayed through the four Visual3Ds. This would put the Mesh generation code (currently in the Tesselate methods of the XXXVisual3Ds) on something like a BoxModel3D (though you I don't think you can derive from GeometryModel3D that way - so maybe BoxModelBuilder3D) . This is to generate the meshes once for the 'real' Box object and then have them 'display' through different Visual3Ds - each Visual3D might now be a simple Visual3D, and no longer a model-specific Visual. Adding and using the interactivity of the UIElement3D can be tricky, because you now have to push interactions into the Model3D if they are to display in the different views. (Imagine you want to select one side of your Box).

So - this is a tricky issue, and the BoxVisual3D etc. design in Helix Toolkit at the moment doesn't really make this kind of multi-view interface easy. By moving the tesselation code out of the Visual3Ds, you'll be able to make a single Model3D (or rather a few Model3DGroups, each with many Models and various transforms) that are 'displayed' by a few very simple Visual3Ds into the different Viewport3Ds. The granularity of your Model / Visual breakdown might be determined by what kind of interactivity you need to support.

I think the current Helix Toolkit  Model / Visual design with the mesh being built in the Visual3D came from an early sample by one of the WPF3D developers, and it might have some other advantages like being able to instantiate those shapes in XAML. Here is one discussion from around the time WPF3D was implemented, http://blogs.msdn.com/b/danlehen/archive/2005/10/09/478923.aspx, with the follow-up example here http://blogs.msdn.com/b/danlehen/archive/2005/10/16/481597.aspx. But, with due respect, I think the ModelVisual3D-derived primitives approach is problematic, and in particular it makes something like the RhinoDemo very clumsy to implement.


objo wrote at 2012-03-14 00:32:

That's a great explanation from Govert. Thanks!

There should be no difference between using a Viewport3D and a HelixViewport3D, the same limitations apply. Use ModelVisual3D elements (not the Visual3D types in Helix toolkit) if you want to share the Model3D between different visual elements. And remember to Freeze() the Model3Ds. 

The RhinoDemo was mostly an experiment to create a user interface that looked close to the original, and define as much as possible of the user interface in XAML.

HDNguyen wrote at 2012-03-14 13:03:

Thank a lot, govert and objo

The explanation of govert is great. As i understand, for short, since a Viewport3D can have only 1 camera so when we want to get several views from different Camera positions, we must create the same amount of Viewport3Ds, so the problem is how to synchronize them

What do you think about the strategy: In the sample RhinoDemo I will grab and clone the children of the main Viewport3D, say the top right window, and add them as children to the Viewport3D of the other windows, another problem is also to override the methode OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved) to get them synchronized

Wait to hear your opinions