| McNeel Wiki | |||||
| edit · print · help · all topics | |||||
Main Pages
Languages
| QuestionIs it possible to create, in .NET, some graphic objects which are not Rhino objects? AnswerYes. The solution is to use a display conduit to draw. For an overview of display conduits, See Display Conduit Introduction. ExampleIn 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 | |||||