Grasshopper Mesh Rendering Preview in C#

Hi,
I am trying to create look out of my component similar to the one from the Custom Preview Component. As you can see from my images below, my geometry is transparent is not casting shadows. Any ideas on how I should be doing it?

public override void DrawViewportMeshes(IGH_PreviewArgs args)
{
    if (BuildingGeometries == null) { return; }
    Material material = new Material();
    material.ReflectionColor = Color.LightGray;
    Rhino.Display.DisplayMaterial renderMaterial = new Rhino.Display.DisplayMaterial(material);

    foreach (Brep brep in BuildingGeometries)
    {
        Mesh[] meshes = Mesh.CreateFromBrep(brep, MeshingParameters.Default);
        foreach (Mesh mesh in meshes)
        {
            args.Display.DrawMeshShaded(mesh, renderMaterial);
        }
    }
}

Custom Preview

My Current Preview

Best,
M

Custom Preview does not use the display pipeline to draw geometry, in rendered viewports it will add meshes to the rendering pipeline.

From what I understand I need to implement a CustomMeshProvider as per this link (https://github.com/mcneel/rhino-developer-samples/blob/53f7108408fd4905e48bda566d15bd87458c7369/rhinocommon/cs/SampleCsRdk/TestCustomMeshProvider.cs) After that, I will need to run BuildCustomMeshes method in order to append the geometry to the render view.

If that is the case, I have been trying to extract the RenderPrimitiveList object from a RhinoObject but I am getting null values. Here is a simple snippet of me trying to get the RenderPrimitiveList. When I run this command I do have an active view with Render view on.

//Get Rhino Object
List<RhinoObject> objects = Rhino.RhinoDoc.ActiveDoc.Objects.GetObjectList(typeof(ExtrusionObject)).ToList();
RhinoObject rhinoObject = objects.First();

//Get View information
Rhino.Display.RhinoView view = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView;
ViewportInfo viewportInfo = new ViewportInfo(view.ActiveViewport);            
Rhino.Display.DisplayPipelineAttributes displayPipelineAttributes = view.DisplayPipeline.DisplayPipelineAttributes;

//Get Render mesh
int number = rhinoObject.CreateMeshes(MeshType.Render, new MeshingParameters(), true);
Mesh[] meshes = rhinoObject.GetMeshes(MeshType.Render);

//Get RenderPrimitiveList
bool willRender = rhinoObject.SupportsRenderPrimitiveList(viewportInfo, displayPipelineAttributes);
RenderPrimitiveList renderPrimitiveList = rhinoObject.GetRenderPrimitiveList(viewportInfo, displayPipelineAttributes);

Any help would be much appreciated.

Best,

@andy can you help out? You know more about this api and how to use it correctly than anyone else.

Some help here? I am also interested in using the rendered view from GH components.

Nope - you just need to create a class derived from CustomMeshProvider, give it a public constructor and you should find that your BuildCustomMeshes function is called automatically.

In the case of Grasshopper meshes, you should only supply meshes when RenderPrimitiveList.RhinoObject is null.

Hello @andy, could you please post a code example of how to do that in a compiled component? I’m trying to do what you wrote here but when I create the derived class I am asked to implement the abstract methods WillBuildCustomMeshes, BuildCustomMeshes, and the Name field, and I do not know what I am supposed to write in the methods bodies (other than returning a boolean). I looked also into Miguel’s link but it’s for Rhino plug-ins. Even a basic example of a simple component that creates a sphere internally and pushes it to the render pipeline correctly would be of great help. Let’s say that I have this code:

public class MyCustomPreview : GH_Component
{
public MyCustomPreview()
: base("MyustomPreview", "MyCPRW", "description", "myTab", "mySection")
{}

protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
        {}
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
        {}
    protected override void SolveInstance(IGH_DataAccess DA)
    {
     Sphere sphere = new Sphere((new Point3d(0.0, 0.0, 0.0), 10.0);
     Mesh renderSphere = Mesh.CreateFromSphere(sphere, 100, 100);
     }
}

How do I display that sphere in a Rendered view using the Rendering pipeline?

Thank you very much in advance,

Alessio

PS: I’ve searched the forum and the web for quite a while for how to do it, without any luck. Any help is highly appreciated

@andy, I’m using your suggestion and it works great – with one exception. Whenever my component shares the canvas with a CustomPreview component (with Render enabled), my render-pipeline meshes disappear. They reappear when the CustomPreview Render option is turned off.

Is there something I should be doing in my class (derived from CustomMeshProvider2) or elsewhere to avoid this fate? It would be great if the components played nice together.

Hello @sarg, I tried to implement @andy 's suggestion too, but when I create the derived class from CustomMeshProvider2 I am asked to implement the abstract methods WillBuildCustomMeshes, BuildCustomMeshes, and the Name field - and I do not know what I am supposed to write in the methods bodies (other than returning a boolean).

May I ask you how did you implement the derived class? Did you have to instantiate it and call the instantiation from somewhere (SolevInstance, BeforeSolveInstance, DrawViewportMeshes, elsewhere)?

Thank you very much in advance,

Alessio

Hi @ale2x72,

As @DavidRutten mentions here, the class derived from CustomMeshProvider2 has to be registered to a Rhino plug-in, not a GH add-on. I happen to have both, so I’m registering to the RHP during OnLoad(). Once referenced, the mesh provider is automatically called by Rhino, per @andy’s note.

As for the overrides, WillBuildCustomMeshes() determines which objects your provider is responsible for (return obj == null if you don’t want to interfere with Rhino doc objects). BuildCustomMeshes() determines the meshes and materials provided to the render pipeline (using objMeshes.Add()). Since the call isn’t made by a GH_Component instance, you need to find another way to communicate what should be rendered – e.g. by maintaining a separate singleton class with up-to-date collections of preview geom / visibility states.

This approach “works” on its own, but – at least in my implementation – appears to be in conflict with the CustomPreview component, so I can’t suggest it as a fully-fledged solution quite yet.

1 Like

Thank you very much, that makes everything a lot clearer to me. Now I’m not sure if in my case it’s worth all the effort to make a Rhino plug-in just for that…

Hello @sarg and @andy could you attach a GH example, please!

@ThomasE You might want to check out this post as well: Grasshopper Raytraced Display Pipeline - #7 by enmerk4r

1 Like

Thank you for the link @ale2x72 but recently I jumped to c# and I don´t get it
could you share an example for the c# editor in GH :pray:t2:
@enmerk4r

// <Custom additional code> 
public class CustomPreviewComponent : Grasshopper.Kernel.Components.GH_CustomPreviewComponent
  {
    public override void AppendRenderGeometry(GH_RenderArgs args)
    {
    }
  }

@ThomasE unfortunately, this works only for compiled components and not for scripted ones.