New selection style

Here's the place for discussion related to coding in FreeCAD, C++ or Python. Design, interfaces and structures.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
wmayer
Founder
Posts: 20302
Joined: Thu Feb 19, 2009 10:32 am
Contact:

New selection style

Post by wmayer »

Hi to everybody,

in recent days I have extended the ViewProviderExt class in the Part module to support all display modes like the default ViewProviderPart class. There we only have a handful of shapes, i.e. one node for all faces, one node for all edges and one node for all vertices. Compared to the default view provider the rendering speed and user interaction is incredible fast. The slow-down of the default view provider comes from the fact that we use an own node for each element which especially makes user-interaction extremely slow.

To have a good comparison of the both you can run this piece of python code:

Code: Select all

from PartDesign.Scripts import Gear
App.ActiveDocument.addObject("Part::FeatureExt").Shape=App.ActiveDocument.Gear3D.Shape
If you hide "Part__FeatureExt" and rotate the view you will see that this is very slow and almost unusable. Now if you toggle the visibilities and rotate it's much, much faster. In the past Jürgen did already most of it but I have extended this by supporting all relevant display modes and fixed a couple of bugs.

The new thing is that selection is partially working. If you have CAD navigation enabled and click somewhere on an element you see the element name in the status bar. The idea behind is actually quite simple. With the SoDetail classes we have all what we need. For lines and points we can use the ready classes SoIndexedLineSet and SoPointSet. Only for faces we had to sub-class SoIndexedFaceSet to support segments/parts. In ViewProviderPartExt::getElement(const SoPickedPoint* pp) we can distinguish which type (face, edge or vertex) was picked and get its element id directly from the SoDetail sub-classes.

So, the next steps will be to wire this with our selection framework which is actually easy and to give some user feedback in the 3d view, i.e. to highlight the element. This, however, is much harder because we have to find a way to render only a part of a shape node with a different color to highlight it -- preferably drawing to the front buffer to be fast. Any ideas how this can be achieved?

Another point we should take into account: the new selection uses a single SoFCUnifiedSelection node as root in the scene graph. This node is implemented to run a pick action for every mouse movement. This however causes a noticeable slow-down if you have e.g. a huge mesh in the document. With the old approach we are able to disable selection on object-side to avoid performance problems. However, with this global selection node this is not longer possible because it runs the slow ray pick action independent of selection is disabled on object side or not.

There is also a design flaw in SoFCUnifiedSelection because the access to the View3DInventorViewer class is hard-coded. However, this can lead to some problems when loading an existent .iv file. The cleaner way is to implement an SoElement sub-class and define the viewer instance in the actualRedraw() method.

Any comments are welcome.

Cheers,
Werner
User avatar
jriegel
Founder
Posts: 3369
Joined: Sun Feb 15, 2009 5:29 pm
Location: Ulm, Germany
Contact:

Re: New selection style

Post by jriegel »

First of all - great you picked it up!

My plan for the Selection was the following:

First subclass a SoSeparator and use them for the root separator of the ViewProviders. But this subclass
has an pointer to the ViewProvider it belongs to. This would allow the SoFCUnifidSelection node to search
up some steps the path of the selection hit and find this special Separator (cause of the type). Should be the second or third node
up and there fore pretty fast. Then a virtual method of the ViewProvider is called with the const SoPickedPoint*.
The default behaviour would be the selection of the whole object as default. That would automatically make
the selection usable for all ViewProviders with no additional node or programming (I think mostly for the Python ones).
Also we get ride of changing graph wile traversal, cause the traversal is finished. So we could even alter the tree as
selection feedback.

More sophisticated ViewProviders can overwrite this method and use the pick-detail to set sub-elements selected or do nothing
at all. This special Separator is also a solution to your mesh problem. We can parametrize it so, it dont route special actions (filter).
That gives us (aka our ViewProviders) full control about the actions we want in our subtree of coin.

About the selection highlighting I thought a lot. One method would be the ViewProvider delivers a line set for the selection which get
drawn by the Viewer on the FrontBuffer. Thats the way Catia do it. A Face get highlighted by the wire not by the actual surface.
But that will always needs a lot of additional code to generate for all sub-elements and the
object a line set... For the main stuff that would be feasibly, cause we would do it only once. But for the extension writers it will
add a lot of complexity. Also we often got problems with wacky OpenGl implementations and the Front-Buffer is more tricky in Coin.

So at the moment I think really to use the color settings of the objects and sub-elements and live with the redraw. We use that already for the
selection were every selection (or any other edit action) cause a redraw... Its not very elegant, but works under all circumstances.
The more sophisticated stuff we can implement later, even in parallel....

Another goal I thought of is get the view tree as uncluttered as posible. Removing this SoFCSelection nodes is one thing. But we should
also think to see if we insert Material and Transform nodes only if they actually needed. A Transform node with unity matrix only cost trafersal
time. The same if the matarial for lines, and face is the default one we can use one node in the viewer to set the default and the ViewProvider
only insert a Material if its really not the default. That keep the tree lean and export stuff works much better!

There is also a design flaw in SoFCUnifiedSelection because the access to the View3DInventorViewer class is hard-coded. However, this can lead to some problems when loading an existent .iv file. The cleaner way is to implement an SoElement sub-class and define the viewer instance in the actualRedraw() method.
Sounds good for me.

So that was my thoughts to that. Hope we get the 3D viewing leaner and faster.
Stop whining - start coding!
wmayer
Founder
Posts: 20302
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: New selection style

Post by wmayer »

First subclass a SoSeparator and use them for the root separator of the ViewProviders. But this subclass
has an pointer to the ViewProvider it belongs to. This would allow the SoFCUnifidSelection node to search
up some steps the path of the selection hit and find this special Separator (cause of the type). Should be the second or third node
up and there fore pretty fast.
The problem comes earlier already. It's this guiltless looking line that is causing the slow-down:

Code: Select all

const SoPickedPoint * pp = this->getPickedPoint(action);
This runs the generatePrimitives() method of an SoShape node and computes the intersection points and so on. Especially generatePrimitives() could be slow if you really have a huge mesh with several million of triangles. But maybe we can also fix this by adding an SoPickStyle node to allow selection only if desired.
Also we get ride of changing graph wile traversal, cause the traversal is finished. So we could even alter the tree as
selection feedback.
Do we have this for the selection stuff somewhere?
About the selection highlighting I thought a lot. One method would be the ViewProvider delivers a line set for the selection which get
drawn by the Viewer on the FrontBuffer. Thats the way Catia do it. A Face get highlighted by the wire not by the actual surface.
But that will always needs a lot of additional code to generate for all sub-elements and the
object a line set...
So, we can have a second SoIndexedLineSet where each line element handles the outer wire of a face and the free flying edges (not attached to a face) of a shape. And this node could be a child of an SoSwitch and only gets activated for highlighting purposes. I guess this can work this way.
But for the extension writers it will add a lot of complexity.
Actually not because for the main data structures shapes, meshes, FEM meshes and points we have the view providers that do most of the stuff. And Python writers they in general even don't need to implement a view provider. It gets only complicated if they want to implement really fancy things.
So at the moment I think really to use the color settings of the objects and sub-elements and live with the redraw.
I think if we have a much smaller scene graph a redraw won't be so expensive any more. And also the front-buffer stuff seems to only work on Win32 almost OK but fails on Win64 and Linux -- at least it's causing a lot of problems and odd behaviour there.
Removing this SoFCSelection nodes is one thing. But we should also think to see if we insert Material and Transform nodes only if they actually needed.
Sure, there might be a certain slow-down but I can't imagine that this is that grave. BTW, wasn't there a utility which measures the rendering speed of an Inventor file, removes all material nodes and re-measure it? so, before putting too much work on this we should test it if it's worth the effort.
When talking about materials there is an important point I forgot: With the new SoBrepFaceSet node we are able to assign an own color to each face. This was possible by implementing the "per part" logic which is missing in the SoIndexedFaceSet class.
User avatar
jriegel
Founder
Posts: 3369
Joined: Sun Feb 15, 2009 5:29 pm
Location: Ulm, Germany
Contact:

Re: New selection style

Post by jriegel »

The problem comes earlier already. It's this guiltless looking line that is causing the slow-down:

Code: Select all
const SoPickedPoint * pp = this->getPickedPoint(action);


This runs the generatePrimitives() method of an SoShape node and computes the intersection points and so on. Especially generatePrimitives() could be slow if you really have a huge mesh with several million of triangles. But maybe we can also fix this by adding an SoPickStyle node to allow selection only if desired.
Yes, but thats needed to do the selection and the preselection highlighthing. And as I mentioned. You can handle this action right above your mesh
in the special separator. So that action never reach you nodes.

Ok, we can only do a pick point on mouse press (as standard in inventor), but then a preselection highlighting is not possible.....
Also we get ride of changing graph wile traversal, cause the traversal is finished. So we could even alter the tree as
selection feedback.


Do we have this for the selection stuff somewhere?
No, not explicitly. That was part of the old (non frontbuffer) selection node. But we can do that in the ViewProvider base class. Simply temporary overwrite the color...
Stop whining - start coding!
wmayer
Founder
Posts: 20302
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: New selection style

Post by wmayer »

Yes, but thats needed to do the selection and the preselection highlighthing. And as I mentioned. You can handle this action right above your mesh in the special separator. So that action never reach you nodes.
The difference between SoFCUnifiedSelection and SoFCSelection is that the first one is global while the latter is local, i.e. bound to a certain view provider. Thus it is possible to simply switch off the selection for this view provider and you're fine. But you can't switch off the selection for the global node because then the whole selection mechanism won't work any more. But as said above using an SoPickStyle and setting it to unpickable should also work.
No, not explicitly. That was part of the old (non frontbuffer) selection node. But we can do that in the ViewProvider base class. Simply temporary overwrite the color...
You don't change the scene graph itself but only push a color onto the stack. Actually this isn't a bad idea because you can't change the material if there is no node, you don't have to worry about undoing the change and you can make sure to have consistent highlight and selection colors. If the view provider does this then each of them can do very different things.
User avatar
jriegel
Founder
Posts: 3369
Joined: Sun Feb 15, 2009 5:29 pm
Location: Ulm, Germany
Contact:

Re: New selection style

Post by jriegel »

The difference between SoFCUnifiedSelection and SoFCSelection is that the first one is global while the latter is local, i.e. bound to a certain view provider. Thus it is possible to simply switch off the selection for this view provider and you're fine. But you can't switch off the selection for the global node because then the whole selection mechanism won't work any more. But as said above using an SoPickStyle and setting it to unpickable should also work.
Thats also OK.
Stop whining - start coding!
wmayer
Founder
Posts: 20302
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: New selection style

Post by wmayer »

Now I made a big step forward in highlighting for the pre-selection. Selection is not yet done but will work more or less as pre-selection.
Again, you can test the above gear example because it shows you quite well the differences in speed for the pre-selection.
About the selection highlighting I thought a lot. One method would be the ViewProvider delivers a line set for the selection which get
drawn by the Viewer on the FrontBuffer. Thats the way Catia do it. A Face get highlighted by the wire not by the actual surface.
But that will always needs a lot of additional code to generate for all sub-elements and the
object a line set...
I tried to show the outer wire of a face for pre-selection and got it (partially) working. But the effort to realize this is much higher than showing the face in another color because you need some extra fields to know which edges belong to a face and I also find this confusing because when selecting a circular face you don't really know if you pre-selected the face or its wire. That's why I again implemented the current behaviour to highlight the face. This is also the way FreeCAD users know and changing this behaviour may lead to some confusion of the community as well.

The pre-selection (and later selection logic) is part of the shape node itself, i.e. SoBrepFaceSet and SoBrepLineSet because since SoFCUnifiedSelection is now a global, single node this cannot handle this anymore.
Technically it works that SoFCUnifiedSelection applies an SoHighlightElementAction to the root node of the view provider it found inside handleEvent(). The SoHighlightElementAction then is handled by SoBrep[Face|Edge]Set getting the information it needs to prepare some data for its rendering.

So, when you compare the gear example again you'll see how fast the pre-selection now is. It's so fast that I think we even don't need anymore the optimization to render to the front-buffer.
User avatar
jriegel
Founder
Posts: 3369
Joined: Sun Feb 15, 2009 5:29 pm
Location: Ulm, Germany
Contact:

Re: New selection style

Post by jriegel »

I also find this confusing because when selecting a circular face you don't really know if you pre-selected the face or its wire
There you have to don't care. In all CAD system there is no wire selection. Its basically all the same. In FreeCAD you cant select wires so far
and I never missed it...

The preselection highlighting works like a charm! Good job!
Stop whining - start coding!
wmayer
Founder
Posts: 20302
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: New selection style

Post by wmayer »

There you have to don't care. In all CAD system there is no wire selection. Its basically all the same. In FreeCAD you cant select wires so far and I never missed it...
Of course I wanted to say edge, not wire :D
The preselection highlighting works like a charm! Good job!
Thanks!
wmayer
Founder
Posts: 20302
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: New selection style

Post by wmayer »

The new selection style is now supposed to be finished. Have a look on it if you find any errors or crashes there.
Post Reply