Export obj from GH using RhinoCompute + python

Hi,

I wish to generate objects in Grasshopper and export a mesh file format from python using Rhino Compute.

I manage to generate the mesh and retrieve the 3dm file, but if I export the mesh as obj with a C# script in Grasshopper I get the following error message that’s returned from the gh.EvaluateDefinition method:

‘Could not find a part of the path ‘C:\Users\jridd\MeshA01.obj’. (line: 0): component “C#” (1e56110f-3c5c-4e61-a9c7-84197f93d1ff)’.

Obviously since you perform the calculations on the compute server this directory on my pc cannot be found, but is there some way to do this in another way? Below are a snip of the python script and printscreen of the Grasshopper file.

McNeel Developers if you read this, many thanks for this amazing development.

import compute_rhino3d.Util
import compute_rhino3d.Grasshopper as gh
import rhino3dm
import json

compute_rhino3d.Util.authToken = *** my token ***
move_tree = gh.DataTree("RH_IN:num")
move_tree.Append([0], [5]) # Here it adds the radius to the sphere
trees = [move_tree]
output = gh.EvaluateDefinition('firsttest.ghx', trees)
print(output) 

What is the code in your C# component? Sharing the definition would be helpful

Hi Steve, thanks for your response. The code is as below. I replaced if(in_run) by if(true) so I didn’t have to click the button to trigger the script. When I run the GH script using the UI it runs fine, but exectuted with Rhinocompute in python it cannot find the filepath (C:\Users\jridd…) anymore.

  private void RunScript(bool in_run, List<Mesh> in_mesh, string in_name, string in_path, ref object A)
  {
    if(true) {
      path = System.IO.Path.GetDirectoryName(in_path) + "\\" + in_name + ".obj";
      int faceCount = 0;
      using(StreamWriter writer = new StreamWriter(path)) {
        for(int n = 0; n < in_mesh.Count; n++) {
          List<String> vert = new List<String>();
          List<String> face = new List<String>();

          in_mesh[n].Faces.ConvertQuadsToTriangles();
          BoundingBox bbox = in_mesh[n].GetBoundingBox(true);

          for(int i = 0; i < in_mesh[n].Vertices.Count; i++) {
            vert.Add(String.Format("v {0} {1} {2}", -in_mesh[n].Vertices[i].X, in_mesh[n].Vertices[i].Z, in_mesh[n].Vertices[i].Y));
          }

          for(int i = 0; i < in_mesh[n].TextureCoordinates.Count; i++) {
            double tx = in_mesh[n].TextureCoordinates[i].X;
            double ty = in_mesh[n].TextureCoordinates[i].Y;
            vert.Add(String.Format("vt " + tx.ToString("F6") + " " + ty.ToString("F6")));
          }

          for(int i = 0; i < in_mesh[n].Normals.Count; i++) {
            vert.Add(String.Format("vn {0} {1} {2}", -in_mesh[n].Normals[i].X, in_mesh[n].Normals[i].Z, in_mesh[n].Normals[i].Y));
          }

          for(int i = 0; i < in_mesh[n].Faces.Count; i++) {
            MeshFace f = in_mesh[n].Faces.GetFace(i);
            int fa = f.A + 1 + faceCount;
            int fb = f.B + 1 + faceCount;
            int fc = f.C + 1 + faceCount;
            string fas = fa.ToString();
            string fbs = fb.ToString();
            string fcs = fc.ToString();
            face.Add(String.Format("f " + fas + "/" + fas + "/" + fas + " " + fbs + "/" + fbs + "/" + fbs + " " + fcs + "/" + fcs + "/" + fcs));
          }

          for(int i = 0; i < vert.Count; i++) {
            writer.WriteLine(vert[i]);
          }

          writer.WriteLine("");
          writer.WriteLine("g " + in_name + n.ToString());

          for(int i = 0; i < face.Count; i++) {
            writer.WriteLine(face[i]);
          }
          faceCount += in_mesh[n].Vertices.Count;
        }
      }
    }
    A = path;
  }

Hello. I would suggest you use the built in Rhino.FileIO.FileObj: FileObj Class
You can write the contents of a headless RhinoDoc or an array of meshes.

You can also generate a temporary file name with System.IO.Path.GetTempFileName(); Path.GetTempFileName Method (System.IO) | Microsoft Docs

which will have a .tmp extension. You can change the extension with System.IO.Path.ChangeExtension() Path.ChangeExtension(String, String) Method (System.IO) | Microsoft Docs