Dot Net Rhino Add Mesh
Last changed: dale@mcneel.com-204.177.179.143

.
Developer.NET
VersionRhino 4

Question

I have a standalone C# application that automates Rhino by creating a Rhino4.Application object and then obtaining a reference to the RhinoScript COM object. I am able to perform simple operations, such as scripting commands via the Command method and adding lines via the AddLine method. But I am unable to use any RhinoScript method where I need to pass in an array of 3-D points, which in RhinoScript are really arrays of arrays of doubles. Is there a way to call RhinoScript's AddMesh method from C#?

Answer

Simple data types, such as integers and doubles are easly marshalled between .NET and COM because their values can be easily converted to the Object .NET data type. Array are a little more difficult to deal with, but not impossible. The .NET array classes have a ToArray member that will copy the elements of the array to a new Object array. A .NET Object array will marshall to COM as a SafeArray.

The following example demonstrates how to call RhinoScript's AddMesh method from a standalone application:

C#

    static void Main(string[] args)
    {
      ///////////////////////////////////////////
      // Create Rhino application object
      Console.Write("Creating Rhino object...");
      Rhino4.Application objRhino = new Rhino4.Application();
      if (objRhino == null)
      {
        Console.WriteLine("failed.");
        return;
      }
      else
      {
        Console.WriteLine("succeeded.");
      }


      ///////////////////////////////////////////
      // Retrieve RhinoScript object
      Console.Write("Retrieving RhinoScript object...");
      RhinoScript4.IRhinoScript objRhinoScript = null;
      int count = 0;
      System.Threading.Thread.Sleep(500);
      while (count < 10)
      {
        object obj = objRhino.GetScriptObject();
        if (obj != null)
        {
          objRhinoScript = (RhinoScript4.IRhinoScript)obj;
          if (objRhinoScript != null)
            break;
        }
        System.Threading.Thread.Sleep(500);
        count++;
      }


      if (objRhinoScript == null)
      {
        Console.WriteLine("failed.");
        return;
      }
      else
      {
        Console.WriteLine("succeeded.");
      }


      ///////////////////////////////////////////
      // Create mesh data
      Console.Write("Adding mesh object...");


      ///////////////////////////////////////////
      // Mesh vertices
      ArrayList vertices = new ArrayList();


      ArrayList v0 = new ArrayList();
      v0.Add(0.0);
      v0.Add(0.0);
      v0.Add(0.0);
      vertices.Add(v0.ToArray());


      ArrayList v1 = new ArrayList();
      v1.Add(10.0);
      v1.Add(0.0);
      v1.Add(0.0);
      vertices.Add(v1.ToArray());


      ArrayList v2 = new ArrayList();
      v2.Add(10.0);
      v2.Add(10.0);
      v2.Add(0.0);
      vertices.Add(v2.ToArray());


      ArrayList v3 = new ArrayList();
      v3.Add(0.0);
      v3.Add(10.0);
      v3.Add(0.0);
      vertices.Add(v3.ToArray());


      ///////////////////////////////////////////
      // Mesh faces
      ArrayList faces = new ArrayList();


      ArrayList f0 = new ArrayList();
      f0.Add(0);
      f0.Add(1);
      f0.Add(2);
      f0.Add(3);
      faces.Add(f0.ToArray());


      ///////////////////////////////////////////
      // Mesh normals
      ArrayList normals = new ArrayList();


      ArrayList n0 = new ArrayList();
      n0.Add(0.0);
      n0.Add(0.0);
      n0.Add(1.0);
      normals.Add(n0.ToArray());


      ArrayList n1 = new ArrayList();
      n1.Add(0.0);
      n1.Add(0.0);
      n1.Add(1.0);
      normals.Add(n1.ToArray());


      ArrayList n2 = new ArrayList();
      n2.Add(0.0);
      n2.Add(0.0);
      n2.Add(1.0);
      normals.Add(n2.ToArray());


      ArrayList n3 = new ArrayList();
      n3.Add(0.0);
      n3.Add(0.0);
      n3.Add(1.0);
      normals.Add(n3.ToArray());


      ///////////////////////////////////////////
      // Texture coordinates
      ArrayList textures = new ArrayList();


      ArrayList t0 = new ArrayList();
      t0.Add(0.0);
      t0.Add(0.0);
      textures.Add(t0.ToArray());


      ArrayList t1 = new ArrayList();
      t1.Add(1.0);
      t1.Add(0.0);
      textures.Add(t1.ToArray());


      ArrayList t2 = new ArrayList();
      t2.Add(1.0);
      t2.Add(1.0);
      textures.Add(t2.ToArray());


      ArrayList t3 = new ArrayList();
      t3.Add(0.0);
      t3.Add(0.1);
      textures.Add(t3.ToArray());


      ///////////////////////////////////////////
      // Vertex colors
      ArrayList colors = new ArrayList();
      colors.Add(0);
      colors.Add(0);
      colors.Add(0);
      colors.Add(0);


      ///////////////////////////////////////////
      // Call AddMesh


      // If you want to pass in everything, then do this:
      //
      // object obj_uuid_str = objRhinoScript.AddMesh(
      //   vertices.ToArray(), 
      //   faces.ToArray(),
      //   normals.ToArray(),
      //   textures.ToArray(),
      //   colors.ToArray()
      //   );


      // If you do not want to pass in optional argument,
      // then pass "System.Reflection.Missing.Value".
      //
      object obj_uuid_str = objRhinoScript.AddMesh(
        vertices.ToArray(), 
        faces.ToArray(),
        System.Reflection.Missing.Value,
        System.Reflection.Missing.Value,
        System.Reflection.Missing.Value
        );


      Console.WriteLine(obj_uuid_str.ToString());


      ///////////////////////////////////////////
      // Save the file
      Console.WriteLine("Saving test file.");
      objRhinoScript.Command("_-Save c:\\test.3dm", 0);


      Console.WriteLine("Done!");
    }