GetMesh() returns Null

Hi guys!

I have a problem (small probability that it’s Rhino bug).

I have function for export geometry.

f3dm = Rhino.FileIO.File3dm.Read(RhinoDocument.Path);

foreach (Rhino.FileIO.File3dmObject o in f3dm.Objects)
            {
                ExportedObject exportedObject = new ExportedObject();
                List<ExportedMesh> eM = new List<ExportedMesh>();
                exportedObject.Meshes = eM;
                //specify if object is solid or passable (door, window).
                SetObjectType(o, exportedObject);

                switch (o.Geometry.ObjectType)
                {
                    case Rhino.DocObjects.ObjectType.Brep:
                        Rhino.Geometry.Brep brep = o.Geometry as Rhino.Geometry.Brep;
                        if (brep != null)
                            foreach (Rhino.Geometry.BrepFace bf in brep.Faces)
                                AddMeshToExportedObject((bf.GetMesh(Rhino.Geometry.MeshType.Any)), o.Attributes.MaterialIndex, o.Attributes.LayerIndex, exportedObject);
                        break;
                    case Rhino.DocObjects.ObjectType.Mesh:
                        Rhino.Geometry.Mesh mesh = o.Geometry as Rhino.Geometry.Mesh;
                        AddMeshToExportedObject(mesh, o.Attributes.MaterialIndex, o.Attributes.LayerIndex, exportedObject);
                        break;
                    case Rhino.DocObjects.ObjectType.Extrusion:
                        Rhino.Geometry.Extrusion extr = o.Geometry as Rhino.Geometry.Extrusion;
                        if (extr != null)
                            AddMeshToExportedObject(extr.GetMesh(Rhino.Geometry.MeshType.Any), o.Attributes.MaterialIndex, o.Attributes.LayerIndex, exportedObject);
                        break;
                    case Rhino.DocObjects.ObjectType.Surface:
                        Rhino.Geometry.Surface srf = o.Geometry as Rhino.Geometry.Surface;
                        if (srf != null && srf.ToBrep() != null)
                            foreach (Rhino.Geometry.BrepFace bf in srf.ToBrep().Faces)

                                AddMeshToExportedObject(bf.GetMesh(Rhino.Geometry.MeshType.Any), o.Attributes.MaterialIndex, o.Attributes.LayerIndex, exportedObject);
                        break;
                    default:
                        //Debug.Log("Can't open " + o.Geometry.ObjectType.ToString() + " geometry type");
                        break;

It works good, but sometimes next lines in different cases begin to return null.`

extr.GetMesh(Rhino.Geometry.MeshType.Any)

What concretely i did:

  1. Open Rhino
  2. Create new document
  3. Make new extrusion with this tool
  4. Click “export geometry” (start code above)
  5. Verify that GetMesh returns null.

Properties say that extrusion is ok. Nothing wrong with it.

and

  1. Open Rhino
  2. Open existing model
  3. Click export geometry
  4. Verify that GetMesh DOESN’T return Null
  5. Add extrusion
  6. Click export geometry again
  7. Verify that GetMesh of all objects of model returns null.

Looks like adding extrusion “broke” model. Because after deleting the extrusion, export geometry (for all objects) still returns null. After reopening model problem stayed.

I did some magic (that doesn’t apply logically); changed render mode. and after this sometimes GetMesh return NOT NULL in place where before changing render mode returned null. But it doesn’t always work and I can’t consider it as a fix.

Render meshes for Breps and Extrusions are created when needed. Thus, if you never shade your model, then render meshes won’t be created and, thus, won’t be saved in the 3DM file.

Does this help/

1 Like

So, first I have to shade model and than GetMeshes… I’ll try. Thanks for the advice

I tried to change Viewport displayMode and display mode of object

 private void ObjectsDisplayMode(File3dmObject rO)
        {
            Guid viewportId = RhinoDocument.Views.ActiveView.ActiveViewportID;
            ObjectAttributes attr = rO.Attributes;
            var previouseDisplayMode = RhinoDocument.Views.ActiveView.ActiveViewport.DisplayMode;
            var dm = RhinoDocument.Views.ActiveView.ActiveViewport;
     
            if (attr.HasDisplayModeOverride(viewportId))
            {
                attr.RemoveDisplayModeOverride(viewportId);
            }
            else
            {
                Rhino.Display.DisplayModeDescription[] modes = Rhino.Display.DisplayModeDescription.GetDisplayModes();
                Rhino.Display.DisplayModeDescription mode = null;
           
                for (int i = 0; i < modes.Count(); i++)
                {
                    if (String.Equals(modes[i].LocalName, "Shaded"))
                    {
                        mode = modes[i];
                    }
                }

                dm.DisplayMode = mode;

                if (mode != null)
                    attr.SetDisplayModeOverride(mode, viewportId);
            }
            RhinoDocument.Objects.ModifyAttributes(rO.Attributes.ObjectId, attr, false);
            RhinoDocument.Views.Redraw();
        }

but it didn’t help.

But if I change display mode in Rhino by hands - it work correctly sometimes (not always).
I feel that you are right, but don’t understand what I did wrong??..

I dont know how it works but I think it starts creating the meshes when they are drawn. Try adding: RhinoDocument.Views.Redraw(); after dm.DisplayMode = mode; Does this work?

P.S. Does

if (String.Equals(modes[i].LocalName, "Shaded"))
{
                        mode = modes[i];
}

find something?

if (String.Equals(modes[i].LocalName, "Shaded"))
{
                        mode = modes[i];
}

Yeap, I checked. It finds mode, I need and works.

I understood, that correctly creates meshes for objects, when I FIRSTLY change display mode of viewport by hands, and AFTER this create object.

I dont know how it works but I think it starts creating the meshes when they are drawn. Try adding: RhinoDocument.Views.Redraw();

tried. Didn’t help :cry:

Oke this is weird:

So if I do this:

  Protected Overrides Function RunCommand(ByVal doc As RhinoDoc, ByVal mode As RunMode) As Result
            Dim Modes As Rhino.Display.DisplayModeDescription() = Rhino.Display.DisplayModeDescription.GetDisplayModes()
            Dim DispMode As Rhino.Display.DisplayModeDescription = Nothing
            For Each m In Modes
                If m.EnglishName = "Shaded" Then
                    DispMode = m
                End If
            Next
            If DispMode Is Nothing Then
                Return Result.Cancel
            End If

            RhinoDoc.ActiveDoc.Views.ActiveView.ActiveViewport.DisplayMode = DispMode
            RhinoDoc.ActiveDoc.Views.ActiveView.Redraw()

            Dim obj As New List(Of Guid)
            For Each Sel As Rhino.DocObjects.RhinoObject In RhinoDoc.ActiveDoc.Objects.GetSelectedObjects(False, False)
                obj.Add(Sel.Id)
            Next

            Dim mList As New List(Of Geometry.Mesh)
            For Each o In obj
                Dim objRef As New DocObjects.ObjRef(o)
                Dim br As Geometry.Brep = objRef.Brep
                For Each f In br.Faces
                    Dim m As Geometry.Mesh = f.GetMesh(MeshType.Any)
                    mList.Add(m)
                    doc.Objects.AddMesh(m)
                Next
            Next
            MsgBox(mList.Count)
            Return Result.Success
        End Function

I tested this on a cube

If I run the first time doc.Objects.AddMesh(m) does nothing, BUT mList contains 6 meshes.
When I run the 2nd time (then Im already in shaded mode) 6 meshes are added and the list contains 6 meshes.

Why did it not add the 6 meshes the first time?

I tried delete object, than change viewport, than add object.

  private void ObjectsDisplayMode(File3dmObject rO)
    {
        var dm = RhinoDocument.Views.ActiveView.ActiveViewport;
        var r  = rO;
        RhinoDocument.Objects.Delete(rO.Attributes.ObjectId,false);

        Extrusion e =  r.Geometry as Rhino.Geometry.Extrusion; //in this example this is extrusion 100%

        if (attr.HasDisplayModeOverride(viewportId))
        {
            attr.RemoveDisplayModeOverride(viewportId);
        }
        else
        {
            Rhino.Display.DisplayModeDescription[] modes = Rhino.Display.DisplayModeDescription.GetDisplayModes();
            Rhino.Display.DisplayModeDescription mode = null;
       
            for (int i = 0; i < modes.Count(); i++)
            {
                if (String.Equals(modes[i].LocalName, "Shaded"))
                {
                    mode = modes[i];
                }
            }

            dm.DisplayMode = mode;
            RhinoDocument.Views.Redraw();
         RhinoDocument.Objects.Add(e);
         RhinoDocument.Views.Redraw();
}

Probably it’s sensless. Didn’t work))) :smile:

I don’t have any idea, why first time it returned null.((

Oke the first time there are still no meshes xD Didnt check if Dim m As Geometry.Mesh = f.GetMesh(MeshType.Any) was succesfull but the first time I try there are still no meshes…

btw. Why not use Geometry.Mesh.CreateFromBrep() where it does not create a mesh?

Hmmmm, I’m not very clear understand what did you mean, I’m trying to figure out with it. (Need a little time).

I figured it out.

try the combination of Redraw and RhinoApp.Wait()

private void ObjectsDisplayMode(File3dmObject rO)
        {
            Guid viewportId = RhinoDocument.Views.ActiveView.ActiveViewportID;
            ObjectAttributes attr = rO.Attributes;
            var previouseDisplayMode = RhinoDocument.Views.ActiveView.ActiveViewport.DisplayMode;
            var dm = RhinoDocument.Views.ActiveView.ActiveViewport;
     
            if (attr.HasDisplayModeOverride(viewportId))
            {
                attr.RemoveDisplayModeOverride(viewportId);
            }
            else
            {
                Rhino.Display.DisplayModeDescription[] modes = Rhino.Display.DisplayModeDescription.GetDisplayModes();
                Rhino.Display.DisplayModeDescription mode = null;
           
                for (int i = 0; i < modes.Count(); i++)
                {
                    if (String.Equals(modes[i].LocalName, "Shaded"))
                    {
                        mode = modes[i];
                    }
                }

                dm.DisplayMode = mode;
                RhinoDocument.Views.Redraw();
                Rhinoapp.Wait();

                if (mode != null)
                    attr.SetDisplayModeOverride(mode, viewportId);
            }
            RhinoDocument.Objects.ModifyAttributes(rO.Attributes.ObjectId, attr, false);
            RhinoDocument.Views.Redraw();
        }

This way Rhino wait till the meshes are created and then continue.

I came to the same conclusion. Rhino don’t have time to create meshes.

It needs to be saved after redrawing.

I did it this way

private void SetShadedDisplayMode(RhinoDoc RhinoDocument)
{
    var dm = RhinoDocument.Views.ActiveView.ActiveViewport;

    Rhino.Display.DisplayModeDescription[] modes = Rhino.Display.DisplayModeDescription.GetDisplayModes();
    Rhino.Display.DisplayModeDescription mode = null;

    for (int i = 0; i < modes.Count(); i++)
    {
        if (String.Equals(modes[i].LocalName, "Shaded"))
        {
            mode = modes[i];
        }
    }

    dm.DisplayMode = mode;
    RhinoDocument.Views.Redraw();
    RhinoApp.Wait();
    Rhino.RhinoApp.RunScript("Save", true);
}

I want to say the biiiiiiigest THANKS.
You are very smart and helped me a lot.

Save is not really needed :wink: As long as you redraw and wait :slight_smile:

No problem, was fun figuring out what was going wrong xD

OK, my comment about shading the model was really meant for end users. Since you are working in a plug-in in Rhino, you can problematically generate render meshes by calling RhinoObject.CreateMeshes. Here is an example.

https://github.com/dalefugier/SampleCsCommands/blob/master/SampleCsMeshBrep.cs