@D-W and I are working with Custom Render Meshes. All worked well until R8 SR23 broke it.
Now, only the Raytraced display mode calls the RenderMeshes override. All other display modes ignore it.
@dale, @stevebaer, @CallumSykes, we’ve scanned through the changelog but nothing obvious stands out:
The minimal example below should replace any object with a sphere. Only raytraced works as expected:
Rendered:
Raytraced:
using Rhino;
using Rhino.Display;
using Rhino.DocObjects;
using Rhino.Geometry;
using Rhino.PlugIns;
using Rhino.Render;
using Rhino.Render.CustomRenderMeshes;
using System;
using System.Collections.Generic;
namespace CRM_Demo
{
public class SphereRenderMeshProvider : RenderMeshProvider
{
public static SphereRenderMeshProvider Instance { get; private set; }
public Guid TargetObjectId { get; set; } = Guid.Empty;
private RenderMeshes _cachedRenderMeshes = null;
private uint _currentCRC = 0;
public SphereRenderMeshProvider()
{
Instance = this;
}
public override Guid ProviderId => new Guid("71731923-0978-45DD-9BA5-31C4EAAEDD8D");
public override string Name => "Sphere Replacer";
public override bool HasCustomRenderMeshes(
MeshType mt,
ViewportInfo vp,
RhinoDoc doc,
Guid objectId,
ref Flags flags,
PlugIn plugin,
DisplayPipelineAttributes attrs)
{
return objectId == TargetObjectId;
}
public bool UpdateRenderMeshes(RhinoObject rhinoObject, RhinoDoc doc)
{
#region dummy geometry & material
// Create a dummy sphere
BoundingBox bbox = rhinoObject.Geometry.GetBoundingBox(true);
if (!bbox.IsValid)
return false;
var sphere = new Sphere(bbox.Center, bbox.Diagonal.Length / 2.0);
Mesh sphereMesh = Mesh.CreateFromSphere(sphere, 32, 32);
if (sphereMesh == null)
return false;
sphereMesh.Normals.ComputeNormals();
var displayMaterial = new Material();
#endregion
var customRenderMesh = new Rhino.Render.CustomRenderMeshes.Instance();
customRenderMesh.Material = RenderMaterial.CreateBasicMaterial(displayMaterial, doc);
customRenderMesh.Mesh = sphereMesh;
uint hash = 0;
if (_cachedRenderMeshes != null)
hash = _cachedRenderMeshes.Hash + 10;
_cachedRenderMeshes = new RenderMeshes(doc, rhinoObject.Id, ProviderId, hash, (uint)Flags.IsDocumentObject);
_cachedRenderMeshes.AddInstance(customRenderMesh);
_currentCRC = rhinoObject.Geometry.DataCRC(0);
return true;
}
public override RenderMeshes RenderMeshes(
MeshType mt,
ViewportInfo vp,
RhinoDoc doc,
Guid objectId,
List<InstanceObject> ancestry,
ref Flags flags,
RenderMeshes previousPrimitives,
PlugIn plugin,
DisplayPipelineAttributes attrs)
{
if (!HasCustomRenderMeshes(mt, vp, doc, objectId, ref flags, plugin, attrs))
return null;
var rhinoObject = doc?.Objects.FindId(objectId);
if (rhinoObject.Geometry.DataCRC(0) != _currentCRC)
UpdateRenderMeshes(rhinoObject, doc);
return _cachedRenderMeshes;
}
}
}
using Rhino;
using Rhino.Commands;
using Rhino.Display;
using Rhino.Input.Custom;
namespace CRM_Demo
{
public class ReplaceWithSphereCommand : Command
{
public override string EnglishName => "ReplaceObjectWithSphereMesh";
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
if (SphereRenderMeshProvider.Instance == null)
{
RhinoApp.WriteLine("Sphere Render Mesh Provider failed to load.");
return Result.Failure;
}
var go = new GetObject();
go.SetCommandPrompt("Select object to replace with a sphere render mesh");
go.Get();
if (go.CommandResult() != Result.Success)
{
return go.CommandResult();
}
var objRef = go.Object(0);
var rhinoObject = objRef.Object();
var objectId = objRef.ObjectId;
if (rhinoObject != null)
{
var attributes = rhinoObject.Attributes.Duplicate();
attributes.SetDisplayModeOverride(DisplayModeDescription.GetDisplayMode(DisplayModeDescription.RenderedId));
doc.Objects.ModifyAttributes(rhinoObject.Id, attributes, true);
}
if (!SphereRenderMeshProvider.Instance.UpdateRenderMeshes(rhinoObject, doc))
return Result.Failure;
SphereRenderMeshProvider.Instance.TargetObjectId = objectId;
doc.Views.Redraw();
return Result.Success;
}
}
}

