I have a set of 10k .obj files with the exact same topology – just different vertex locations. I have been using pancake to import obj files which temporarily loads the mesh file into the Rhino active doc before adding it to a tree in Grasshopper. Its a sequential operation and really slow with anything over 1k files.
With so many files (and a workstation with 32 cores) I am hoping to read obj files in Parallel using System.Threading.Tasks.Parallel.For().
The problem here is that the FileIO.FileOBJ.Read function reads to a Rhino doc and I have no way to trace which obj file is which mesh in the RhinoDoc when running a parallel process like this.
I may be approaching the problem entirely wrong. Im looking for some general architectural advice on how to approach a parallelized obj read operation.
Following up here, I ended up taking a different route and read the lines of the obj file directly.
It currently only handles verts and faces but could be adjusted to handle normals, vertex colors, UV mapping, etc. This cut the import time from 7 minutes for 4.6k meshes down to 1 minute (adding garbage collection took it from 2 to 1 minute). In my book, that’s a success.
If anyone wants to use this code, you’re welcome to it.
If anyone wants to suggest improvements or alternative methods, I’d love to hear them!
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
private void RunScript(List<string> paths, ref object meshes)
{
Mesh[] meshes_tmp = new Mesh[paths.Count];
Parallel.For(0, paths.Count, index =>
{
var faces = new List<MeshFace>();
var verts = new List<Point3d>();
using(var sr = new StreamReader(paths[index]))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] s = line.Split(' ');
if(s[0] == "v")
{
//Print(vs[1]);
verts.Add(new Point3d(System.Convert.ToDouble(s[1]), System.Convert.ToDouble(s[2]), System.Convert.ToDouble(s[3])));
}
if(s[0] == "f")
{
string[] fs = line.Split(' ');
if(fs.Length == 4)
{
faces.Add(new MeshFace(int.Parse(s[1])-1, int.Parse(s[2])-1, int.Parse(s[3])-1));
}
else{
//Print(fs.Length.ToString);
faces.Add(new MeshFace(int.Parse(s[1])-1, int.Parse(fs[2])-1, int.Parse(s[3])-1, int.Parse(s[4])-1));
}
}
}
}
Mesh mesh = new Mesh();
mesh.Vertices.AddVertices(verts);
mesh.Faces.AddFaces(faces);
//mesh.RebuildNormals();
meshes_tmp[index] = mesh;
verts = null;
faces = null;
mesh = null;
});
meshes = meshes_tmp;
}
1 Like