Hi,
I am playing around with some animations that should show extrusion profiles appear by sliding a plane. Basically reproducing what Clipping plane does if I was moving the plane along the extrusion.
My first go-to was some kind of Split or Boolean operation (difference or intersection), but I think that would be way more expensive and slower than whatever is done with the Clipping Plane command. Am I wrong?
Can you tell me how the clipping plane works and is there something exposed in the API I could use to recreate the same effect?
Are you actually cutting/splitting the geometry or is it just a visual (camera) effect?
By the way, I would like to recreate this in the Conduit, inside DrawForeground…I do not need to make any changes to the document (like you are not making any changes with the Clipping Plane I assume).
I had attempted this in Python but never got it hooked up. I assumed there was some kind of enabling of clipping planes or other additional setting I needed to get it working for display conduits.
This was my attempt using a planar surface in the scene as a test “cut plane” to visualize:
Is there something more specific needed to “add objects” to the clipping plane conduit?
import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
from Rhino.Display import DisplayConduit
from System.Drawing import Color
class ClippingPlaneConduit(DisplayConduit):
def __init__(self, plane):
super(ClippingPlaneConduit, self).__init__()
self.plane = plane
self.debug_section_color = Color.Blue
self.debug_section_mat = Rhino.Display.DisplayMaterial(Color.Blue)
self.debug_section_mat.Transparency = 0.6
def DrawForeground(self, e):
e.Display.EnableDepthTesting(False)
e.Display.EnableClippingPlanes(True)
e.Display.AddClippingPlane(self.plane.Origin, self.plane.Normal)
# Ensure plane_srf is a valid Brep
if not plane_srf or not isinstance(plane_srf, Rhino.Geometry.Brep):
return
# Convert Brep to Mesh for visualization
plane_mesh = Rhino.Geometry.Mesh.CreateFromBrep(plane_srf)
if plane_mesh:
e.Display.DrawMeshShaded(plane_mesh[0], self.debug_section_mat)
# Extract the actual corner points from the Brep's outer loop
brep_faces = plane_srf.Faces
if brep_faces.Count > 0:
face = brep_faces[0] # Assuming a single face Brep
plane_corners = face.ToNurbsSurface().Points
# Draw bounding box from actual Brep
bbox = plane_srf.GetBoundingBox(True)
e.Display.DrawBoxCorners(bbox, self.debug_section_color, 1, 6)
# Extract Brep edges as polylines for visualization
plane_edges = []
for edge in plane_srf.Edges:
plane_edges.append(edge)
# Draw edges
for polyline in plane_edges:
e.Display.DrawCurve(polyline, self.debug_section_color, 2)
# Draw direction indicators
e.Display.DrawDot(self.plane.Origin, "Direction", self.debug_section_color, Color.White)
e.Display.DrawArrow(Rhino.Geometry.Line(self.plane.Origin, self.plane.Origin + self.plane.Normal * 10), self.debug_section_color)
plane_srf_id = rs.GetObject("Choose a planar surface to use as clipping control", filter=rs.filter.surface, preselect=True)
if plane_srf_id:
plane_srf = rs.coercebrep(plane_srf_id)
plane = None
if plane_srf and plane_srf.Faces[0].TryGetPlane():
plane_tup = plane_srf.Faces[0].TryGetPlane()
plane = plane_tup[1]
if plane:
if "ClippingPlaneConduit" in sc.sticky:
sc.sticky["ClippingPlaneConduit"].Enabled = False
cp_conduit = ClippingPlaneConduit(plane)
cp_conduit.Enabled = True
sc.sticky["ClippingPlaneConduit"] = cp_conduit
print("Clipping plane display conduit updated and enabled.")
else:
print("Selected surface is not planar.")
else:
print("No surface selected.")
sc.doc.Views.Redraw()
But if I am not mistaken this is a global thing, no? If you set this it cuts everything in the scene?
The goal is to manipulate individual objects in the same manner…that is why I wonder what is under th hood of the clipping plane, so that o could apply it to individual objects with more control.
This is probably not the intended/correct way to implement the method (e.g. one should probably track/delete old ones), but extending this old GhPython example seems to only clip the local component conduit/display:
but I would love if someone from McNeel told us what is used under the hood to make the Clipping plane work…even as a concept.
I think I will go with some Split or Boolean Difference option if there is no answer. My guess is that the Clippling Plane only alters the view, deals with the Camera frustum or similar, (and does not alter the geometry)…otherwise it could not be so fast. Although it does cap all the cut solids nicely, so how does it do that? Maybe it is some combination…it creates a section, caps the solids and also adjusts the camera…would love to know in any case.
If it is mostly Camera adjustment then it is probably hard to constrain it to individual objects…and my guess is that they are using a system where it is hard to apply it do individual objects, otherwise thy would offer that option.
You are quite right.
With the plugin GHGL you can play a bit with that.
Related thread:
I tried to combine 2 meshes to create the visual effect of a solid boolean operation, but never managed to make buffers work at all
Anyway, you actually tell each and every pixel if to display on screen or not. When not, the “raycast” from the camera continue and search for the next geometry to display.
(my description probably sucks…)
Accessing this OpenGL coding through a c# or python script is not possible, as far as I understood past then.
Steve might answer you in detail…
Probably it does the same as above but in the the opposite way, using the mesh to discard the plane pixels when the raycast intercepted the mesh an even amount of times before reaching the plane…
Google “openGL depth peeling”.