Obj texture framerate hit

I’m finding that using a texture on an imported .obj is leading to a severe slow down in my sketch.

The obj is one part of a PShape Group, it is loaded and added to the Group in setup().
It is then used by a Class which is being instanced up to 150 times at the moment (but will likely increase)

The obj itself does not seem to cause the slowdown it is the use of the texture, i.e if i delete the texture ref from the .mtl file there are no problems and my sketch runs at 60fps happily.

The texture originally was 512x512, reducing this down to 32x32 has made no apparent difference to the framerate hit.

Is this fps hit just to be expected when working with this many textured objects in processing or am I missing something ?

1 Like

Hi @mala,

Would getTessellation help? (I seem to recall a PShape loaded from an object is itself a group with a child for each face). See https://github.com/processing/processing/issues/2508 and https://github.com/processing/processing/issues/2873 .

1 Like

Thank you :+1:

That has helped with the framerate hit, though also seems to have raised more questions :laughing:

The documentation for getTessellation() is a bit sparse to put it mildly, though from what I can guess it may just copy everything over from one PShape to another ?

I now have an odd problem with the texture, it seems that using getTessellation does not copy over texture or perhaps UV info from the imported obj.
So in order to see the texture I need to use setTextureMode and setTexture(PImage) using an imported copy of the original .mtl texture.
This works, but I’ve also discovered something rather odd… If I delete the image file name from the .mtl file then the other imported PImage copy of the texture is no longer rendered ?! UV issue ?

Not directly connected to issue I’m having here, but IMHO the parseOBJ code really needs to be rewritten/updated.
The splitting of an obj into a child object for every face does not really make any sense to me.
Given that nowadays we have the likes of Blender that anyone can create and export UV’ed and textured 3D objects from easily and for free, I think it would make sense to allow processing users easier & fuller access to obj data.
For example if I create a multi object 3D model in Blender and export, the resulting .obj file contains object names that seperate the data for each child object of the file, these are ignored by processing’s parseOBJ code. But surely they could be used to group the faces into PShape “children” and therfore giving the user easy access to the wheel of their model car for example, instead of having to figure out which faces are which from the 1000’s of children…

1 Like

Hi @mala,

It’s not quite clear how complex your project is, since you haven’t posted any code, but if you’re free to choose a different dev environment for your project, I’d recommend doing that.

Imagine for a moment that Processing could parse the hypothetical car .obj file into appropriate pieces (four wheels, chassi, etc.). It’d still take less hassle to coordinate and animate those pieces in a program like Unity, Blender or – take your pick – than it would in Processing.

Another possibility would be to research Processing libraries, which would involve looking through their documentation and/or examples.

The source code for getTessellation is here. The simplified code (no .mtl file) below seems to retain UVs post-tessellation.

PShapeOpenGL shape;
PImage txtr;

void setup() {
  size(256, 256, P3D);
  textureWrap(REPEAT);
  txtr = rgb(256, 256);

  shape = (PShapeOpenGL)loadShape("cube.obj");
  shape = (PShapeOpenGL)shape.getTessellation();
  shape.setTextureMode(NORMAL);
  shape.setTexture(txtr);
}

void draw() {
  background(#fff7d5);
  directionalLight(255, 245, 215, 0.0, 0.6, -0.8);
  camera(
    0.0, 0.0, height * 0.86602,
    0.0, 0.0, 0.0,
    0.0, 1.0, 0.0);

  rotate(frameCount * 0.01, 0.0, 0.6, 0.8);
  scale(128);
  shape(shape);
}

PImage rgb(int w, int h) {
  PImage result = createImage(w, h, ARGB);
  result.loadPixels();
  for (int i = 0, y = h - 1; y > -1; --y) {
    float gr = y * 255.0 / (h - 1);
    for (int x = 0; x < w; ++x, ++i) {
      float re = x * 255.0 / (w - 1);

      result.pixels[i] = color(
        re, gr, 127.0, 255.0);
    }
  }
  result.updatePixels();
  return result;
}

The .obj file is as follows:

o Cube

v -0.353553 -0.353553 -0.353553
v -0.353553 -0.353553 0.353553
v -0.353553 0.353553 -0.353553
v -0.353553 0.353553 0.353553
v 0.353553 -0.353553 -0.353553
v 0.353553 -0.353553 0.353553
v 0.353553 0.353553 -0.353553
v 0.353553 0.353553 0.353553

vt 0.000000 0.000000
vt 0.000000 1.000000
vt 1.000000 1.000000
vt 1.000000 0.000000

vn 1.000000 0.000000 0.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn -1.000000 0.000000 0.000000
vn 0.000000 1.000000 0.000000

f 1/3/5 2/4/5 4/1/5 3/2/5 
f 3/3/6 4/4/6 8/1/6 7/2/6 
f 7/3/1 8/4/1 6/1/1 5/2/1 
f 5/3/4 6/4/4 2/1/4 1/2/4 
f 3/2/3 7/3/3 5/4/3 1/1/3 
f 8/2/2 4/3/2 2/4/2 6/1/2 

Best,
Jeremy

1 Like

Hi @behreajj ,

My project is quite complex, though it does not involve any animation.
Apologies, the car example was poorly chosen.

The project is an interface for controlling a large network of devices, being able to represent these devices in 3D space and in a reasonably realistic looking way makes the UI much easier to use.

Thanks so much for pointing me to the source code for getTessellation, I had struggled to find that.

If I delete from my obj file any references to the .mtl and use getTessellation as you have done in the example above then I get the same correct result.

Thanks again,
mala