Measurement modes used to render per-face content (one GeometryModel3D per
B-rep face). On a large assembly (64k faces measured) that is 64k draw calls,
and WPF re-walks the whole visual tree every frame, so orbiting in a
measurement tool was severely laggy while plain browse mode (which renders the
merged mesh, one model per file) stayed smooth.
Render the merged mesh whenever not sectioning (browse AND measure), and
resolve the picked B-rep face from the hit triangle's vertex index via
_mergedFaceRanges + ResolveMergedFace (binary search over per-face vertex-start
boundaries recorded at import — BuildMergedMesh appends faces in order with no
vertex welding, so the ranges are exact and stay valid across translation).
Per-face FacesContent is now rendered only in section mode (needs cut
geometry). WPF 3D hit testing is geometric and does not cull back faces, so
single-sided merged meshes still pick hole inner walls.
Also subscribe camera-interaction suspension to HelixViewport3D.CameraChanged
(control-level routed event) in addition to Camera.Changed, so it can't be
orphaned if Helix replaces the camera instance.
Verified: orbit in measure mode is now as smooth as browse; circle/face/edge/
angle/face-distance and section measurements unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The project has no runtime or compile-time secrets (offline desktop
tool, no DB/API keys), so the secret/ folder held only example launch
scripts that were never used. Remove it and the related .gitignore
rules; trim references in ARCHITECTURE.md and CLAUDE.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Gizmo now renders in a separate transparent Viewport3D overlaid on
the main view, so the manipulator is never occluded inside solid
parts and is always grabbable from any angle
- Overlay camera follows the main camera (position/dir/FOV/near-far)
on every change; raw Viewport3D lets empty-area clicks pass through
so orbit / zoom / measurement still work; IsHitTestVisible bound to
GizmoEnabled. Mouse-up handled on the overlay (handledEventsToo),
with _gizmoBakePending guarding against double-bake
- Window title shows version (STPViewer V0.3.1)
- Remove the two test STEP models from the repo (customer part
numbers) -> moved to For_AI/ (gitignored); add *.stp/*.step to
.gitignore so CAD files never get committed again
- Docs updated (ARCHITECTURE Phase 11, CLAUDE.md, README)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- New "操作器" toggle: select a file in the tree and a 3-axis gizmo
appears at its center -- XYZ arrows (TranslateManipulator) to move
along an axis regardless of view angle, and rotation rings
(RotateManipulator) to rotate any angle about an axis
- Manipulators bind to a proxy ModelVisual3D; the proxy's transform
is mirrored to all target BodyVisuals during drag (GPU-side, temp)
- On release the accumulated transform is baked into B-rep via
TransformRoot (deferred with Dispatcher.BeginInvoke to avoid
reentrancy with the manipulator's own mouse-up handling); the
gizmo re-centers on the new bounds
- Temporary transforms are cleared with Transform3D.Identity, never
null (HelixToolkit GetTransform crashes on null child.Transform)
- Selecting another file retargets the gizmo; removing the target
hides it
- Docs updated (ARCHITECTURE Phase 10, CLAUDE.md, README)
Known limitation: gizmo handles are occluded inside solid parts
(WPF single depth buffer). Next: always-on-top overlay viewport.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drag mode set BodyVisual.Transform = null when clearing the temporary
offset on release. HelixToolkit Viewport3DHelper.GetTransform adds
child.Transform to a GeneralTransform3DGroup without a null check, so
the next FindHits after any drag threw ArgumentException and crashed.
Clear the temporary transform with Transform3D.Identity instead.
Root cause confirmed by decompiling HelixToolkit.Wpf GetTransform.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- New Drag mode (hand cursor): left-press a part and drag to move
its whole file along the screen plane; release to commit
- During drag only a temporary TranslateTransform3D is applied
(GPU-side, smooth even on 430k-triangle assemblies); on release
the offset is baked into B-rep + meshes + edges via TranslateRoot,
so measurement accuracy is unaffected
- Merged-mesh hit-testing via _mergedMap (browse rendering active
in drag mode); edges suspended while dragging
- Mouse capture keeps drag alive outside the window; lost capture
commits at current position
- Right-button rotate / wheel zoom / Shift+left pan unchanged
- Rename small test model to test.stp; docs updated
(ARCHITECTURE Phase 9, CLAUDE.md conventions, README)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>