McNeel Wiki
Drawing Meshes
edit · print · help · all topics
Main Pages

AccuRender

Bongo

Brazil r/s

Developer

Flamingo

Penguin

Rhino Blogs

Rhino

Rhino Labs

Search

Languages

Česky

Deutsch

English

Español

Français

Italiano

Polish

日本語

한국어

中文(繁體)

 
.
Developer.NET
SummaryDemonstrates how to draw a mesh using a display conduit.

Question

Is it possible to create, in .NET, some graphic objects which are not Rhino objects?

Answer

Yes. The solution is to use a display conduit to draw. For an overview of display conduits, See Display Conduit Introduction.

Example

In the following we will dynamically draw a mesh. The first thing we need a display conduit to draw the mesh for us. Considering the following class:

C#

  public class DrawBlueMeshConduit : MRhinoDisplayConduit
  {
    private OnMesh m_mesh = null;
    private OnColor m_drawing_color = null;
    private MDisplayPipelineMaterial m_material = null;
    private OnBoundingBox m_mesh_bbox = null;


    public DrawBlueMeshConduit(OnMesh mesh)
      : base(new MSupportChannels(MSupportChannels.SC_CALCBOUNDINGBOX | MSupportChannels.SC_PREDRAWOBJECTS), false)
    {
      // set up as much data as possible so we do the minimum amount of work possible inside the
      // actual display code
      m_mesh = mesh;
      m_drawing_color = OnColor.FromColor(System.Drawing.Color.Blue);
      m_material = new MDisplayPipelineMaterial();
      m_material.m_FrontMaterial.m_diffuse = m_drawing_color;
      if (m_mesh != null && m_mesh.IsValid())
        m_mesh_bbox = m_mesh.BoundingBox();
    }


    public override bool ExecConduit(ref MRhinoDisplayPipeline dp, uint nChannel, ref bool bTerminate)
    {
      if (m_mesh_bbox == null)
        return true;


      // this is called every frame inside the drawing code so try to do as little as possible
      // in order to not degrade display speed. Don't create new objects if you don't have to as this
      // will incur an overhead on the heap and garbage collection.


      if (nChannel == MSupportChannels.SC_CALCBOUNDINGBOX)
      {
        // Since we are dynamically drawing geometry, we needed to override
        // SC_CALCBOUNDINGBOX. Otherwise, there is a good chance that our
        // dynamically drawing geometry would get clipped.


        // Union the mesh's bbox with the scene's bounding box
        m_pChannelAttrs.m_BoundingBox.Union(m_mesh_bbox);
      }
      else if (nChannel == MSupportChannels.SC_PREDRAWOBJECTS)
      {
        // Time to draw our mesh


        // Get the active viewport
        MRhinoViewport vp = dp.GetRhinoVP();
        if (vp.DisplayMode() == IOn.display_mode.wireframe_display)
        {
          // If the viewport is in wireframe, draw a wireframe mesh
          dp.DrawWireframeMesh(m_mesh, m_drawing_color);
        }
        else
        {
          // Otherwise, draw a shaded mesh
          dp.DrawShadedMesh(m_mesh, m_material);
        }
      }
      return true;
    }
  }

VB.NET

 Public Class DrawBlueMeshConduit
  Inherits MRhinoDisplayConduit


  Private m_mesh As OnMesh = Nothing
  Private m_drawing_color As OnColor = Nothing
  Private m_material As MDisplayPipelineMaterial = Nothing
  Private m_mesh_bbox As OnBoundingBox = Nothing


  Public Sub New(ByVal mesh As OnMesh)
    MyBase.New(New MSupportChannels(MSupportChannels.SC_CALCBOUNDINGBOX Or MSupportChannels.SC_PREDRAWOBJECTS), False)


    ' set up as much data as possible so we do the minimum amount of work possible inside the
    ' actual display code
    m_mesh = mesh
    m_drawing_color = OnColor.FromColor(System.Drawing.Color.Blue)
    m_material = New MDisplayPipelineMaterial()
    m_material.m_FrontMaterial.m_diffuse = m_drawing_color
    If (m_mesh IsNot Nothing AndAlso m_mesh.IsValid()) Then
      m_mesh_bbox = m_mesh.BoundingBox()
    End If
  End Sub


  Public Overrides Function ExecConduit(ByRef pipeline As RMA.Rhino.MRhinoDisplayPipeline, ByVal channel As UInteger, ByRef terminate As Boolean) As Boolean
    If (m_mesh_bbox Is Nothing) Then Return True


    ' this is called every frame inside the drawing code so try to do as little as possible
    ' in order to not degrade display speed. Don't create new objects if you don't have to as this
    ' will incur an overhead on the heap and garbage collection.
    If (channel = MSupportChannels.SC_CALCBOUNDINGBOX) Then
      ' Since we are dynamically drawing geometry, we needed to override
      ' SC_CALCBOUNDINGBOX. Otherwise, there is a good chance that our
      ' dynamically drawing geometry would get clipped.


      ' Union the mesh's bbox with the scene's bounding box
      m_pChannelAttrs.m_BoundingBox.Union(m_mesh_bbox)
    ElseIf (channel = MSupportChannels.SC_PREDRAWOBJECTS) Then
      ' Time to draw our mesh


      ' Get the active viewport
      Dim vp As MRhinoViewport = pipeline.GetRhinoVP()
      If (vp.DisplayMode() = IOn.display_mode.wireframe_display) Then
        ' If the viewport is in wireframe, draw a wireframe mesh
        pipeline.DrawWireframeMesh(m_mesh, m_drawing_color)
      Else
        ' Otherwise, draw a shaded mesh
        pipeline.DrawShadedMesh(m_mesh, m_material)
      End If
    End If
    Return True
  End Function
 End Class

Here we have an MRhinoDisplayConduit derived class. The constructor of the class requires that we define when we want Rhino to call our display conduit. In this case, we want to be called to be called to ensure the drawing bounding box is the correct size (MSupportChannels.SC_CALCBOUNDINGBOX) and when Rhino is drawing visible, non-highlighted objects (MSupportChannels.SC_PREDRAWOBJECTS). All MRhinoDisplayConduit derived class are required to override the ExecConduit abstract member function. This is were all of the action will take place.

To use the above class, we can write a simple command, such as the following that creates a meshed sphere and then draws it with our conduit:

C#

  public override IRhinoCommand.result RunCommand(IRhinoCommandContext context)
  {
    // Define the sphere
    OnSphere sphere = new OnSphere();
    MArgsRhinoGetSphere args = new MArgsRhinoGetSphere();
    IRhinoCommand.result rc = RhUtil.RhinoGetSphere(args, ref sphere);
    if (rc != IRhinoCommand.result.success)
      return rc;


    // Create a mesh sphere
    OnMesh mesh = RhUtil.RhinoMeshSphere( sphere, 10, 10 );
    if( mesh == null )
      return IRhinoCommand.result.failure;


    // Create an instance of our conduit
    DrawBlueMeshConduit conduit = new DrawBlueMeshConduit(mesh);
    // Enable the conduit - don't for get to regen
    conduit.Enable();
    context.m_doc.Regen();


    // Pause so the user can see our work
    MRhinoGetString gs = new MRhinoGetString();
    gs.SetCommandPrompt("Press <Enter> to continue");
    gs.AcceptNothing();
    gs.GetString();


    // Disable the conduit - don't for get to regen
    conduit.Disable();
    context.m_doc.Regen();


    return IRhinoCommand.result.success;
   }

VB.NET

  Public Overrides Function RunCommand(ByVal context As RMA.Rhino.IRhinoCommandContext) _
    As RMA.Rhino.IRhinoCommand.result
    ' Define the sphere
    Dim sphere As New OnSphere()
    Dim args As New MArgsRhinoGetSphere()
    Dim rc As IRhinoCommand.result = RhUtil.RhinoGetSphere(args, sphere)
    If (rc <> IRhinoCommand.result.success) Then Return rc


    ' Create a mesh sphere
    Dim mesh As OnMesh = RhUtil.RhinoMeshSphere(sphere, 10, 10)
    If (mesh Is Nothing) Then Return IRhinoCommand.result.failure


    ' Create an instance of our conduit
    Dim conduit As New DrawBlueMeshConduit(mesh)
    ' Enable the conduit - don't for get to regen
    conduit.Enable()
    context.m_doc.Regen()


    ' Pause so the user can see our work
    Dim gs As New MRhinoGetString()
    gs.SetCommandPrompt("Press <Enter> to continue")
    gs.AcceptNothing()
    gs.GetString()


    ' Disable the conduit - don't for get to regen
    conduit.Disable()
    context.m_doc.Regen()
    conduit.Dispose()
    Return IRhinoCommand.result.success
  End Function
rename · changes · history · subscriptions · lost and found · references · file upload