Get Render Mesh From Block Instance?

Hello,

I’m using the new Rhino8 GetMeshes method elsewhere which works well for getting a brep’s render mesh but does not seem to work for block instances?

                elif isinstance(geom, Rhino.Geometry.Brep):
                    rhino_obj = obj_ref.Object() 
                    render_meshes = rhino_obj.GetMeshes(Rhino.Geometry.MeshType.Render)
                    all_meshes.extend(render_meshes or [])

Does anyone have a pointer for getting the render mesh from a block? I’ve been scouring these forums and web with no luck on this topic.

I continually get confused with how to access geometry of Instance Definitions from an instance reference…

Here’s a failed code excerpt attempting this:

                    elif isinstance(obj, Rhino.Geometry.InstanceReferenceGeometry):
                        try:
                            # Get the InstanceObjects associated with the InstanceReferenceGeometry
                            instance_definition_parent = obj.ParentIdefId  # Get the parent GUID
                            # Ensure the instance definition exists
                            if instance_definition_parent:
                                # Get all objects associated with the instance definition
                                # objects = instance_definition_parent.GetObjects()
                                obj_ref = Rhino.DocObjects.ObjRef(instance_definition_parent)
                                print(f"obj_ref: {obj_ref}")
                                rhino_obj = obj_ref.Object()  # Get the actual RhinoObject
                                print(f"rhino_obj: {rhino_obj}")
                                geom = rs.coercegeometry(instance_definition_parent)
                                # geom = obj_ref.Geometry()
                                print(f"Block Geom: {geom}")
                                # render_meshes = obj_ref.GetMeshes(Rhino.Geometry.MeshType.Render)
                                # objects = rhino_obj.GetObjects()
                                # print(f"objects: {objects}")
                                # geom = obj_ref.Geometry()  # Get the geometry (Brep, Mesh, etc.)
                                
                                
                                # if geom:
                                #     return geom
                                # else:
                                #     Rhino.RhinoApp.WriteLine("No objects found in the block instance definition.")

                            # if objects:
                            #     # Get the render meshes of the Instance Definition Objects
                            #     render_meshes = objects.GetMeshes(Rhino.Geometry.MeshType.Render)
                                
                                if render_meshes:
                                    # If meshes are found, draw them
                                    for mesh in render_meshes:
                                        e.Display.DrawMeshShaded(mesh, material)
                                
                        except Exception as ex:
                            Rhino.RhinoApp.WriteLine(f"Error getting render meshes for block instance: {ex}")

All of my print statements trying to get an object, geometry, mesh etc. all return none

I can explode the block recursively to get the brep and meshes but this is slow for detailed blocks. I Simply want to get the render mesh of the block for display conduit purposes…

Thank you in advance!

EDIT:
Made a little progress…

                    elif isinstance(obj, Rhino.Geometry.InstanceReferenceGeometry):
                        try:
                            obj_id = obj.ParentIdefId

                            all_meshes = []
    
                            """Test"""
                            # Get the InstanceDefinition from the ParentIdefId
                            instance_definition = scriptcontext.doc.InstanceDefinitions.FindId(obj_id)
                            print(f"instance_def: {instance_definition}")
                            
                            # Check if the instance definition was found
                            if instance_definition:
                                print(f"instance_def: {instance_definition}")
                                # Get all objects in the instance definition (block geometry)
                                objects = instance_definition.GetObjects()
                                print(f"idef objects: {objects}")

                                if objects:
                                    for geom in objects:
                                        # print(f"geometry: {geometry}")
                                        if isinstance(geom, Rhino.Geometry.Mesh):
                                            all_meshes.append(geom)
                                        elif isinstance(geom, Rhino.Geometry.Brep):
                                            rhino_obj = geom.Object()
                                            render_meshes = rhino_obj.GetMeshes(Rhino.Geometry.MeshType.Render)
                                            all_meshes.extend(render_meshes or [])
                                        elif isinstance(geom, Rhino.Geometry.Rhino.Geometry.InstanceReferenceGeometry):
                                            print(f"{geom} is a nested block instance reference")
                                        # else:
                                        #     print("Could Not Draw Geometry In Objects")
                                print(f"all_meshes:{all_meshes}")
                                if all_meshes:
                                    e.Display.DrawMeshShaded(all_meshes, material)

                        except Exception as ex:
                            Rhino.RhinoApp.WriteLine(f"Error getting render meshes for block instance: {ex}")

I now have the instance definition of the block but still not extracting its geometry with the GetObjects method…

Here a script to get all meshes of block instances, ensuring nested block instances also work

#! python 3

import scriptcontext as sc
import Rhino

def get_meshes(o : Rhino.DocObjects.InstanceObject):
    meshes = list()
    # get the instance definition
    idef = o.InstanceDefinition
    xform = o.InstanceXform
    for io in idef.GetObjects():
        # if we have a nested block instance, get the meshes for that
        if io.ObjectType == Rhino.DocObjects.ObjectType.InstanceReference:
            ms = get_meshes(io)
        # or just get meshes from the object at hand
        else:
            ms = io.GetMeshes(Rhino.Geometry.MeshType.Render)
        # apply block instance transformation to get
        # mesh into world space with the block transform. Otherwise
        # we get the mesh located where it was when the block definition
        # was initially created
        for m in ms:
            m.Transform(xform)
        meshes.extend(ms)
    # done
    return meshes


all_meshes = list()
# go over all objects in document
for o in sc.doc.Objects:
    if o.ObjectType == Rhino.DocObjects.ObjectType.InstanceReference:
        # get meshes from instance reference (block instance)
        meshes = get_meshes(o)
        all_meshes.extend(meshes)

print(all_meshes)
1 Like

Awesome, thank you @nathanletwory ! The need for passing the transform was something I hadn’t considered, thanks for the comments in the code also