Hi @mh_eos,
Thanks for the detailed writeup and the images — that makes the goal clear.
Short answer: there’s no supported public Rhino 8 C++ SDK path for publishing a transient, topology-refined analysis mesh onto an existing CRhinoBrepObject. Your findings are all accurate. Here’s what’s going on and what I’d do instead.
Don’t put the refined mesh in the source Brep
ON_BrepFace::SetMesh(ON::analysis_mesh, ...) is not a runtime-only slot:
- Brep face analysis meshes are written to the 3dm. Rhino’s writer only has a switch for render meshes — analysis meshes are always saved when present. So your mesh ends up in your users’ files.
- It wouldn’t survive anyway. When the display needs analysis meshes it compares the cached mesh’s
ON_MeshParameters against the document’s analysis mesh settings. Yours won’t match, so Rhino treats the face as unmeshed, re-meshes it, and replaces your mesh.
So no, that route can’t be made runtime-only, and I wouldn’t recommend it even temporarily.
UpdateVertexColors will never do what you need
Correct — it hands you the object’s meshes as const, and the only thing the pipeline picks up afterwards is m_C. Rhino does have an internal hook that lets a visual analysis mode take over an object’s shaded draw completely, which is exactly what you’d want, but it isn’t part of the public SDK. I’ve made a note to look at exposing it.
What I’d do: a command plus a custom display conduit
Draw the refined mesh yourself from a CRhinoDisplayConduit:
- Support
SC_DRAWOBJECT. When the object being drawn is one you’re analyzing, set m_pChannelAttrs->m_bDrawObject = false and draw your locally refined, hard-banded mesh instead.
- The document object is never touched — UUID, runtime class, attributes, history, grips, Gumball, selection and Undo all behave exactly as before, and nothing is serialized.
- You own the cache. Key it on object id plus a geometry hash, rebuild from a
CRhinoDoc replace/modify event watcher, and clear it when your mode ends. Atomic replacement and clearing are then entirely under your control.
- A command that toggles the conduit on and off (or a modeless panel) is the natural wrapper.
Face-interior picking — you don’t need the refined mesh for it
This is the part I’d change in your design. CRhinoBrepObject::Pick switches to mesh (face-interior) picking whenever the object has a shaded visual analysis mode enabled, even in a Wireframe viewport — that behavior exists specifically so zebra and draft-angle objects pick sensibly in wireframe. And the pick runs against the object’s ordinary render mesh; Rhino’s own Draft Angle Analysis does exactly the same thing.
So:
- Register a
CRhinoVisualAnalysisMode for your plug-in with false_color_style (or texture_style) so IsShaded() returns true.
- Enable it on the source object with
CRhinoObject::EnableAnalysisMode(your_id, true). That call is const and only touches the object’s runtime analysis-mode list plus a redraw hint — no document Modified flag, no Undo record, no events, nothing written to the 3dm.
You then get native face-interior picking, preselection, highlighting and the What/Properties naming for free. The triangulation used for the pick differs slightly from your refined display mesh, but it’s the same underlying surface, so hits land where the user expects.
One thing to watch out for
Your current combination can’t work as-is: when a visual analysis mode is active on an object, Rhino skips custom render meshes entirely for the shaded draw, and a mode’s DrawBrepObject/DrawMeshObject overrides are only called for wireframe-style modes. So IRenderMeshProvider and a VAM will fight each other. Use the conduit for viewport drawing, and keep IRenderMeshProvider for Rendered/Raytraced, which goes through the RDK.
Hope this helps — let me know how it goes.
– Dale