We are drawing some objects using a Display Conduit. It is working well and we call:
def PreDrawObjects(self, drawEventArgs):
for part in self.machineMeshParts:
drawEventArgs.Display.DrawObject(part.geometry, part.xform)
Right now the geometry is a mesh object imported from a 3DM file into Rhino. After importing we get it using ObjectsByName().
We’d rather not do that. Instead we’d like to directly read the 3DM file and bring the objects into memory. We don’t want to create Rhino objects first (we draw them ourselves so having Rhino hang on to them is wasteful).
Anyone have thoughts on how we can do this (using RhinoCommon methods or any other).
Having some trouble actually drawing the objects I load into memory. Here’s my (as simple as I could make it) test program:
import rhinoscriptsyntax as rs
import scriptcontext
import Rhino
import System
import System.Drawing
def Main():
# Get the pathname to open
pathname = "C:\\Users\\Mark Meier\\Desktop\\3DMFileDrawTest\\Test.3dm"
pathname = pathname.replace("\\", "/")
print pathname
# Open it and get the objects
drawObjs = Load3DMFile(pathname)
# Make the display conduit object for drawing
dc = DisplayConduit(drawObjs)
dc.Enabled = True
rs.Redraw()
rs.GetPoint("Enter a point") # only way I could think to pause...
dc.Enabled = False
def Load3DMFile(pathname):
f3dm = Rhino.FileIO.File3dm.Read(pathname)
if (f3dm):
objs = f3dm.Objects
return objs
class DisplayConduit(Rhino.Display.DisplayConduit):
def __init__(self, objs):
# Store the objects we are to draw
self.drawObjs = objs
# Get the bounding box for all the objects passed
self.drawObjsBBox = Rhino.Geometry.BoundingBox(Rhino.Geometry.Point3d(-1,-1,-1), Rhino.Geometry.Point3d(1,1,1))
for item in self.drawObjs:
bbox = item.Geometry.GetBoundingBox(False)
if (bbox):
self.drawObjsBBox.Union(bbox)
# Init the material to draw with
self.material = Rhino.Display.DisplayMaterial()
self.material.Diffuse = System.Drawing.Color.OrangeRed
self.material.IsTwoSided = True
self.material.Shine = 0.8
def CalculateBoundingBox(self, calculateBoundingBoxEventArgs):
calculateBoundingBoxEventArgs.BoundingBox.Union(self.drawObjsBBox)
def PreDrawObjects(self, drawEventArgs):
drawEventArgs.Display.DrawBox(self.drawObjsBBox, System.Drawing.Color.White)
for item in self.drawObjs:
if item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Curve:
drawEventArgs.Display.DrawCurve(item.Geometry, System.Drawing.Color.Green)
elif item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Brep:
drawEventArgs.Display.DrawBrepWires(item.Geometry, System.Drawing.Color.Red)
elif item.Geometry.ObjectType == Rhino.DocObjects.ObjectType.Mesh:
drawEventArgs.Display.DrawMeshWires(item.Geometry, System.Drawing.Color.Blue)
drawEventArgs.Display.DrawMeshShaded(item.Geometry, self.material)
if (__name__ == "__main__"):
Main()
If I look at this in the debugger I can see the objects are loading. And I can see the bounding box calculation is working. And I can see the object types are what I expect. What I can’t see is the objects being drawn in the viewports, Doh!
Anyone have experience doing this - I’m not sure what I’m missing.
Thanks!
Mark
PS: My test file contains a sphere, a mesh of that sphere, and two curves.
I notice in the Mesh Drawing Example they don’t do it in the python code sample. But they do it in the C# sample.
Even if I do that I can’t zoom extents. Rhino reports “Unable to zoom - no objects are visible.”. Shouldn’t my bounding box call then incorporate my drawing into the bounding box computations?
I’m trying to figure out the best way to Transform these in-memory Mesh objects before I draw them.
I’ve seen the method:
DisplayPipeline.DrawObject(RhinoObject, Transform)
That’s okay, but I can’t specify a material as I can in a draw method such as:
DisplayPipeline.DrawMeshShaded(Mesh, DisplayMaterial)
Is there a method appropriate for transforming meshes? Then I could transform it and draw it with the above method. I can’t seem to find it but perhaps I’m missing something obvious (I hope I am).
Is it at all possible to draw using the other shading methods that are available in the viewport as when using real Rhino objects? I’m thinking of Technical, Artistic, Pen, etc. I’m guessing not but I feel compelled to ask because it would be really nice
Okay, so for now I’ve “baked” the objects into real Rhino objects at the end so they can be rendered nicely.
For anyone curious the post below contains some screen captures of our app running and full source code for loading 3dm files, drawing these in memory objects using a Display Conduit, and then baking them into real Rhino objects. The code is surprisingly simple.
This is very interesting, but what is the main benefit of doing this?
Is it to visualize the movement of the CNC cutting of an object, without having to load the robot arm into the document? Or can Rhino “draw” these objects faster than real Rhino objects?
Yes, initially we were posing the robot which was drawn as Rhino objects. Memory climbed like crazy (usually making Rhino crash after a while) and it was very slow. Using the display conduit keeps the memory from growing and it is MUCH faster.
Animating objects by replacing instances in the Rhino document is usually not the best way to go since copies of the objects are constantly being made and placed on the undo stack. Any sort of animation is typically done with something like a conduit that Mark implemented.