"Solid" clipping plane

Have some feature requests, feedback, cool stuff to share, or want to know where FreeCAD is going? This is the place.
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
looo
Posts: 2913
Joined: Mon Nov 11, 2013 5:29 pm

Re: "Solid" clipping plane

Postby looo » Fri Apr 21, 2017 2:23 pm

again some references:

coin adds the clipPlane here:
https://github.com/looooo/coin3d/blob/m ... p#L131L144

the plane gets removed when this function is called:
https://github.com/looooo/coin3d/blob/m ... pp#L87L100

The easiest way to implement the caping is to:
1. copy SoClipPlane.h, SoClipPlaneElement.h, SoGLClipPlaneElement.h and the coresponding cpp files.
2. rename Clip to Cap
3. add the gl-stuff for rendering the the cap to SoGLClipPlaneElement::addToElt

Maybe it would be also possible to implement by SubClassing a SoSeparator. But there is the need to get the traversal-end event (pop) and I have no idea how to get this end-event...
please help with my conda-packaging efforts: https://liberapay.com/looooo/
looo
Posts: 2913
Joined: Mon Nov 11, 2013 5:29 pm

Re: "Solid" clipping plane

Postby looo » Sat Apr 22, 2017 6:58 am

using a SoCallback works also in FreeCAD: (still only python code + some changes in pivy to make the SoCallback work with freecad)
gear_cap.png
gear_cap.png (15.15 KiB) Viewed 1422 times
but selection makes some problems...
selection_problem.png
selection_problem.png (19.17 KiB) Viewed 1422 times
Is there a way to disable the selection for some renderBelowPath calls?
please help with my conda-packaging efforts: https://liberapay.com/looooo/
pablogil
Posts: 756
Joined: Wed Nov 26, 2014 3:19 pm
Location: Badajoz (Spain)
Contact:

Re: "Solid" clipping plane

Postby pablogil » Sat Apr 22, 2017 8:47 am

Very interesting! It's almost done

Cheers
Dark and Light stylesheets v2.0 to theme your FreeCAD UI, more information here
looo
Posts: 2913
Joined: Mon Nov 11, 2013 5:29 pm

Re: "Solid" clipping plane

Postby looo » Sat Apr 22, 2017 9:33 pm

Yes, after playing with the stencil-buffer another time, the problem with the selection is gone.
Currently the algorithm has some problems with the sketcher (crash) and there are still some small artifacts with lines... Also I do not know how to draw the capping-plane. Somehow the size has to be specified.

Code: Select all

import sys
from PySide import QtGui
from pivy import coin
from OpenGL.GL import *

handled=False

class CapPlane():
    def __init__(self, node):
        self.node = node
    def stencilBuffer(self, action):
        glEnable(GL_CLIP_PLANE0)
        glEnable(GL_STENCIL_TEST);
        glClear(GL_STENCIL_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE)
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
        # Draw Front faces and decrease stencil-buffer
        # where the front_face is drawn
        glStencilFunc(GL_ALWAYS, 0, 0);

        glDisable(GL_DEPTH_TEST)
        glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT)
        glCullFace(GL_FRONT)
        self.node.GLRenderBelowPath(action)
        # draw the back_face to the stencil-buffer
        # decrease the stencil buffer where the back-face is drawn
        glCullFace(GL_BACK)
        glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT)
        self.node.GLRenderBelowPath(action)
        # Draw a quad aligned with the stencil plane,
        # but set the stencil test to reject pixels unless the stencil is set.
        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)
        glEnable(GL_DEPTH_TEST)
        glDisable(GL_CLIP_PLANE0)
        glStencilFunc(GL_NOTEQUAL, 2, ~0)
        glStencilFunc(GL_NOTEQUAL, 0, ~0)
        glColor3f(0.8, 0.8, 0.8)
        glDisable(GL_CULL_FACE)
        glDisable(GL_LIGHTING)
        glBegin(GL_QUADS)
        glVertex3fv([-10000,-10000, 3])
        glVertex3fv([ 10000,-10000, 3])
        glVertex3fv([ 10000, 10000, 3])
        glVertex3fv([-10000, 10000, 3])
        glEnd()
        glEnable(GL_LIGHTING)
        glDisable(GL_STENCIL_TEST)
        glEnable(GL_CLIP_PLANE0)
        glClear(GL_STENCIL_BUFFER_BIT)
        glDisable(GL_CULL_FACE)

def myCallbackRoutine(cap, action):
    global handled
    if not action.isOfType(coin.SoGLRenderAction.getClassTypeId()):
        return
    if not handled:
        handled = True
        cap.stencilBuffer(coin.SoGLRenderAction.constructFromAction(action))
        handled = False

view = Gui.ActiveDocument.ActiveView
sg = view.getSceneGraph()
myCallback = coin.SoCallback()
cap = CapPlane(sg)
myCallback.setCallback(myCallbackRoutine, cap)

plane = coin.SbPlane(coin.SbVec3f(0,0,1), coin.SbVec3f(0,0,3))
clip = coin.SoClipPlane()
clip.plane = plane
sg.insertChild(clip, 2)
sg.insertChild(myCallback, 3)
selection_works.png
selection_works.png (28.34 KiB) Viewed 1368 times
please help with my conda-packaging efforts: https://liberapay.com/looooo/
HoWil
Posts: 840
Joined: Sun Jun 14, 2015 7:31 pm
Location: Austria

Re: "Solid" clipping plane

Postby HoWil » Sun Apr 23, 2017 9:20 am

Looks nice,
Is this possible without blocking the Task-panel as the original clipping tool does?
This could be very usefull for FEM-wb for selecting inner solids and faces.
Please see also https://forum.freecadweb.org/viewtopic. ... 50#p151950 to get an impression what I need sometimes in FEM-wb.
BR,
HoWil
looo
Posts: 2913
Joined: Mon Nov 11, 2013 5:29 pm

Re: "Solid" clipping plane

Postby looo » Sun Apr 23, 2017 10:21 am

HoWill wrote:Is this possible without blocking the Task-panel as the original clipping tool does?
Maybe the SoClipPlanManip node could be useful. I think drawing the cap is not that important for this task.

Code: Select all

from pivy import coin
sg = Gui.ActiveDocument.ActiveView.getSceneGraph()
clip_plane = coin.SoClipPlaneManip()
sg.insertChild(clip_plane, 0)
# sg.removeChild(clip_plane, 0)
please help with my conda-packaging efforts: https://liberapay.com/looooo/
User avatar
yorik
Site Admin
Posts: 11565
Joined: Tue Feb 17, 2009 9:16 pm
Location: São Paulo, Brazil
Contact:

Re: "Solid" clipping plane

Postby yorik » Sun Apr 23, 2017 6:33 pm

very interesting progresses looo! Didn't think there was something liek that available at coin level already...
looo
Posts: 2913
Joined: Mon Nov 11, 2013 5:29 pm

Re: "Solid" clipping plane

Postby looo » Mon Apr 24, 2017 3:57 pm

yorik wrote:very interesting progresses looo! Didn't think there was something liek that available at coin level already...
it isn't yet available with coin. My code implement the capping at opengl-level. But it is very nice that this is possible from python...

I have done some further tests, but didn't find a way to remove the artifacts... I think this isn't a problem of the stencil-buffer algorithm. But maybe there is a way to get rid of the artifacts (use the shaded render mode for the stencil renderings)

I also had a look how the clipping-plane is implemented in osg. And I think there approach (every separator can enable a clipping-plane) is more suited for CAD.

Does FreeCAD already use a subclass of a SoSeparator for shapes? If not I would suggest to do so and implement the "CAD-clipping" at the separator-level. The idea is to have clipping planes defined in a separator somewhere near the root-separator and CAD-Separators to implement the glEnable(GL_CLIP_PLANE0) and glDisable(GL_CLIP_PLANE0)...
The CAD-Sparator then gets two bool-value for the clip-type shell/solid, on/off. In SoSeparator::GLRenderInPath the planes get enabled and regarding the clip-style the stencil-buffer-algorythm will be used or not.
In SoSeparator::GLRenderOffPath the plane gets disabled. Maybe a SoAction can be used to enable/disable the clip-planes for all separator.

questions:
1: If I implement this in FreeCAD, is it possible to have this SoSeparator-subclass available from python, and use it like a pivy-node?
2: Can I switch the rendermode for the two stencil-buffer-renderings? And how to achieve that? (It seems the rendermode with only polygons, doesn't show any artifacts.)
please help with my conda-packaging efforts: https://liberapay.com/looooo/
wmayer
Site Admin
Posts: 14887
Joined: Thu Feb 19, 2009 10:32 am

Re: "Solid" clipping plane

Postby wmayer » Mon Apr 24, 2017 5:25 pm

1: If I implement this in FreeCAD, is it possible to have this SoSeparator-subclass available from python, and use it like a pivy-node?

Code: Select all

from pivy import coin
type=coin.SoType.fromName("SoFCSelection") # FreeCAD specific type
type.isBad() # => 0, i.e. OK
node=type.createInstance()
looo
Posts: 2913
Joined: Mon Nov 11, 2013 5:29 pm

Re: "Solid" clipping plane

Postby looo » Tue Apr 25, 2017 7:48 am

thanks, this is perfect.

Tested the python code posted above in windows, and there no artifacts are visible... but somehow the line picking is affected.
please help with my conda-packaging efforts: https://liberapay.com/looooo/