Clipping planes (section view)
OCCT provides Graphic3d_ClipPlane — clipping at the OpenGL level, without modifying geometry.
Existing difference() for sectioning is a modelling operation; clipping planes are purely visual.
Key API (via OCC.Core)
| Class/Method | Role |
|---|---|
Graphic3d_ClipPlane(gp_Pln) |
Clipping plane from a geometric plane |
plane.SetOn() / SetOff() |
Toggle |
plane.SetCapping(True) |
Fill the cut surface with a color |
plane.SetCappingColor(Quantity_Color) |
Capping fill color |
V3d_View.AddClipPlane(plane) |
Apply to entire viewport |
V3d_View.RemoveClipPlane(plane) |
Remove from viewport |
PrsMgr_PresentableObject.AddClipPlane(plane) |
Apply to a single AIS object |
V3d_View.SetClipPlanes() |
Replace all planes at once |
Two approaches
| Approach | Scope | Capping | Complexity |
|---|---|---|---|
Per-view (V3d_View.AddClipPlane) |
All AIS objects | Single color for all | Low |
Per-object (AIS_ColoredShape.AddClipPlane) |
Per AIS object | Different per object | High |
Storage
BcadStategets clipping plane state:clip_plane_on: bool,clip_plane_axis: int(0=X, 1=Y, 2=Z),clip_plane_pos: float,clip_plane_capping: bool- GUI stores in
settings.confunder[general](likefn_polygon_threshold)
IPC protocol (rqq.py)
| Request | Parameters | Action |
|---|---|---|
RQ_SET_CLIP_PLANE |
axis, position, on |
Create/reposition plane |
RQ_REMOVE_CLIP_PLANES |
— | Remove all planes |
RQ_SET_CAPPING |
on, color |
Toggle/set capping |
GUI (main_window.py)
ImGui panel (or toolbar section):
- Checkbox "Show section"
- Axis selector (X/Y/Z) — radio buttons
- Slider for position (0.0–1.0 of bounding box diagonal)
- Checkbox "Capping"
- Color picker for capping color
Implementation steps (worker side)
Viewer3d.set_clip_plane(axis: int, pos: float, on: bool)inboccviewer.py:- Remove existing clip planes from
V3d_View - If on: create
gp_Plnfrom axis + pos, wrap inGraphic3d_ClipPlane, callView.AddClipPlane(plane)
- Remove existing clip planes from
Viewer3d.remove_clip_planes()— iterate and remove allViewer3d.set_capping(on: bool, color: tuple)— set on active plane- Handle in
worker_engine.py— new branch forRQ_SET_CLIP_PLANEetc. - Update image → send
RP_ACK
Texture mapping
Textures are an extension of per-face appearance, logically part of color().
The same propagation machinery that handles _face_colors handles textures —
they are just another attribute of a face's material.
Storage
# scl_shape.py — single dict, value is (color, texture_path) pair
_face_material: dict[int, tuple[Quantity_ColorRGBA | None, str | None]]
# (None, None) → default material
# (color, None) → solid color (current behaviour)
# (None, path) → pure texture, no tint
# (color, path) → modulated texture (color × texture)
Propagation
All existing propagation functions treat _face_material as opaque. The dict
value is carried through without inspection:
| Function | Mechanism | Change |
|---|---|---|
_map_colors(builder, sources) |
Generated(), Modified(), IsSame() |
Also carries _face_material values |
_map_unified_colors(unifier, ...) |
ShapeUpgrade_UnifySameDomain history |
Same |
_adjacency_fill_colors(...) |
Edge-adjacency fill for _offset_3d |
Same |
transform_shape() |
Re-hash faces through TShap |
Updates both tuple elements |
transform_gtrsh() |
Same for grouped transforms | Same |
| extrude/revolve/loft/offset | Source face → all result faces | Carries (color, path) pair |
Display
_display_main_face_colors in scl_shape.py expands:
color |
texture |
Action |
|---|---|---|
None |
None |
Default (no custom attributes) |
color |
None |
SetCustomColor(face, color) — existing path |
None |
path |
AIS_ColoredDrawer → ShadingAspect → Aspect → SetTextureMap(map) + SetTextureMapOn(), modulate off |
color |
path |
Both SetCustomColor() and SetTextureMap(), modulate on |
OCCT mechanism per face: ```python from OCC.Core.Graphic3d import Graphic3d_Texture2D, Graphic3d_AspectFillArea3d from OCC.Core.AIS import AIS_ColoredDrawer
drawer = AIS_ColoredDrawer() shading = drawer.ShadingAspect() aspect = shading.Aspect() # Graphic3d_AspectFillArea3d aspect.SetTextureMap(Graphic3d_Texture2D(path)) aspect.SetTextureMapOn()
if color is also set:
ais_shp.SetCustomColor(face, color)
aspect.EnableTextureModulate() -- default is on
aspects_map.Bind(face, drawer) ```
Language syntax
// Solid color (existing)
color("red") cube(10);
// Pure texture (no tint)
color(texture="wood.png") cube(10);
// Modulated texture (tinted by color)
color("red", texture="checker.png") cube(10);
// Color + alpha + texture
color(c="red", alpha=0.5, texture="marble.png") sphere(5);
textureparameter: path to PNG/JPG (file resolution likesurface())- If file not found → warning, fallback to color or default
- OpenSCAD ignores
texture=→ warning about unknown parameter + color shown
Face material propagation through booleans
union() {
color("red", texture="wood.png") cube(10);
color("blue") cube(5);
}
_fuse_parts → _map_colors maps source faces to result faces.
Each source face's (color, texture) is looked up by hash and assigned via
Generated()/Modified()/IsSame() to the corresponding result face.
If a result face is new (no history) → (None, None) → default.