How to load .obj files faster?

Hi :slight_smile: I’m loading 6 Mb of .obj files (18 files in total) and it takes a few seconds. It would be nice if it happened faster.

I tried the loader from HE_Mesh and also the plain loadShape(). The first one was slower, probably because I needed to convert the shape to PShape at the end. Maybe it’s the PShape construction not performing so great…

Any ideas on how to load PShapes faster? :slight_smile:

Hi @hamoid,

Would you mind sharing a sample from one of your .obj files? You might be able to strip away some of the checks for missing or malformed data if you know your .obj file will always format its faces consistently, ie., will not have missing v/vt/vn data. If you don’t have multiple .mtls or multiple groups per mesh, or don’t need mtl data at all, that may also simplify the matter.

An overview of the file spec from Wikipedia is here. I believe Processing core handles parsing to PShapeOBJs here. Not too familiar with HE Mesh, but looks like the parsing happens here. I’ve tried writing my own here with a custom Mesh class; it hasn’t been tested for robustness or speed, but may give an indication of what to look for or how to roll your own.

Since you’re familiar with Blender, you may want to go into where your add-ons are stored and look at the io for Wavefront obj to see how they do it.

Also, you won’t always be comparing apples to apples. A half edge data structure is not the same as the radial edge structure used in BMesh is not the same as a mesh designed to ship data to the renderer in OpenGL. The effort and time needed to convert from Wavefront .obj to a mesh depends on what kind of mesh you want to use in your project.


1 Like

Thanks for the ideas Jeremy :slight_smile: The meshes are simple with a list of v/vn/f generated in Blender. No mtls.
And they don’t change. Thanks for the links, they give me ideas. I could even just load the objs once, and save them in a custom format (serializing a PShape?) so I would skip the parsing in that case. I’ll give it a try :slight_smile:

Hi @hamoid

Not sure if it helps but normally I use saito.objloader library to import obj files. However, I haven’t run any tests on performance.

Best regards

1 Like

I had used LWJGL with their Assimp bindings to load OBJs in the past, saw your post and decided to try to use it with Processing. It seems to work fairly well. On this machine, it loads and converts to PShape the Sanford bunny (4.7Mb) in about 300ms and the dragon (64.3Mb) in about 1600ms from an NVMe M.2 drive.

If you try to use it and run into any trouble, I might be able to help. I just put the lwjgl and assimp libraries and their natives (lwjgl.jar,, lwjgl-assimp.jar, and lwjgl-assimp-natives-linux.jar) in the “code” folder alongside the sketch to get it to run.

  System.setProperty("jogl.disable.openglcore", "false");

  Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
    public void run() {
      println(" ");

import org.lwjgl.*;
import org.lwjgl.assimp.Assimp;
import org.lwjgl.assimp.AIMesh;
import org.lwjgl.assimp.AIVector3D;

PShape test;

void setup() {
  size(1920, 1080, P3D);
  long time = millis();
  test = assimpObjToPShape(sketchPath("dragon.obj"));
  println(millis() - time);

void draw() {
  translate(width * 0.5, height * 0.5, 800);


PShape assimpObjToPShape(String file) {
  AIVector3D.Buffer verts = AIMesh.create(
    Assimp.aiImportFile(file, 0).mMeshes().get(0))
  PShape ret = createShape();
  int count = verts.remaining();
  for(int a=0; a<count; a++) {
    AIVector3D cur = verts.get(a);
    ret.vertex(cur.x(), cur.y(), cur.z());
  return ret;