Exporting to OBJ

I used to use Nervous System to export to OBJ, but it does not work for Processing 3, I even installed Processing 2 and won’t work there either. If there’s no similar library now I’ll try to code it directly in python/blender

import nervoussystem.obj.*;


PImage img;
boolean record = false;

void setup() {
  size(600,700, P3D);
  img = loadImage("adventuretime.jpg");
  img.loadPixels();
  noStroke();
}

void draw() {
  if (record){
    beginRecord("nervoussystem.obj.OBJExport", "at.obj");
  }
  background(255);
  lights();
  //translate(width/2, height/2);
  //scale(4);
  //rotateX(mouseY*0.01);
  //rotateY(mouseX*0.01);
  //image(img, 0,0);
  for(int x=0; x<100; x++){
    for(int y=0; y<100; y++){
      int imgx = (int)map(x, 0, 100, 0,img.width);
      int imgy = (int)map(y, 0, 100, 0,img.height);
      float bri = brightness(img.get(imgx, imgy));
      //if(bri>50) {
      pushMatrix();
      translate(x,y);
      box(bri/256.0);
      popMatrix();
      //}
    }
  }  
    if(record){
      endRecord();
      record = false;
    }
  
}

void keyPressed(){
  if(key == 's') {
    record = true;
  }
}
1 Like

I tried this:

PImage img;
boolean record = false;
ObjWriter obj = new ObjWriter();

void setup() {
  size(600, 700, P3D);
  img = loadImage("adventuretime.jpg");
  img.loadPixels();
  noStroke();
}

void draw() {
  if (record) {
    obj.beginRecord("at.obj");
  }
  background(255);
  lights();
  for (int x=0; x<10; x++) {
    for (int y=0; y<100; y++) {
      int imgx = (int)map(x, 0, 10, 0, img.width);
      int imgy = (int)map(y, 0, 100, 0, img.height);
      float bri = brightness(img.get(imgx, imgy));
      if (record) {
        PShape shp = createShape(BOX, bri/256.0);
        shp.translate(x, y);
        obj.addMesh(shp);
      } else {
        pushMatrix();
        translate(x, y);
        box(bri/256.0);
        popMatrix();
      }
    }
  }  
  if (record) {
    obj.endRecord();
    record = false;
  }
}

void keyPressed() {
  if (key == 's') {
    record = true;
  }
}

class ObjWriter {
  PrintWriter output;
  StringBuilder verts = new StringBuilder();
  StringBuilder faces = new StringBuilder();
  int vertCount = 0;
  String filename;
  void beginRecord(String fname) {
    output = createWriter(fname);
    filename = fname;
  }
  void addMesh(PShape mesh) {
    final int vc = mesh.getVertexCount();
    final PVector v = new PVector();
    for (int i=0; i<vc; i+=3) {
      mesh.getVertex(i, v);
      verts.append("v " + v.x + " " + v.y + " " + v.z + "\n");
      mesh.getVertex( i+1, v);
      verts.append("v " + v.x + " " + v.y + " " + v.z + "\n");
      mesh.getVertex( i+2, v);
      verts.append("v " + v.x + " " + v.y + " " + v.z + "\n");
      faces.append("f " + (i+1+vertCount) + " " + (i+2+vertCount) + " " + (i+3+vertCount) + "\n");
    }
    vertCount += vc;
  }
  void endRecord() {
    output.println("o shape\n");
    output.println(verts);
    output.println(faces);
    output.flush();
    output.close();
    println(filename, "saved with", vertCount, "vertices");
  }
}

but it didn’t work because shp.translate() doesn’t translate the shape, but it alters its matrix (I think) so all the produced shapes are overlapping.

It should be easy with Toxiclibs… one moment :slight_smile:

Exporting OBJ or STL with ToxicLibs is very easy, just mesh.saveAsOBJ(...)

import toxi.geom.*;
import toxi.geom.mesh.*;
import toxi.processing.*;

PImage img;
ToxiclibsSupport gfx;
TriangleMesh mesh;

void setup() {
  size(600, 700, P3D);
  img = loadImage("adventuretime.jpg");
  img.loadPixels();
  noStroke();

  gfx = new ToxiclibsSupport(this);

  mesh = new TriangleMesh("shape");
  for (int x=0; x<100; x++) {
    for (int y=0; y<100; y++) {
      int imgx = (int)map(x, 0, 100, 0, img.width);
      int imgy = (int)map(y, 0, 100, 0, img.height);
      float bri = brightness(img.get(imgx, imgy));

      // Axis Aligned Bounding Box
      AABB box = new AABB(0.5 * bri/256.0);
      TriangleMesh m = (TriangleMesh) box.toMesh();
      m.translate(x, y, 0);
      // Add all cubes to one big mesh
      mesh.addMesh(m);
    }
  }
}

void draw() {
  background(255);
  lights();
  gfx.mesh(mesh); // draw the mesh
}

void keyPressed() {
  if (key == 's') {
    mesh.saveAsOBJ(sketchPath("mesh.obj"));
  }
}

The only issue is that the faces are sharing vertices so the shading is smooth and may look wrong. You should set Flat Shading for this shape in Blender or wherever you plan to use it.
Otherwise, construct a box without using AABB, but with 6 planes instead.

Here a close up of the Processing logo using the technique above, but all cubes with the same size and setting a random rotation for bright pixels only.

2 Likes

Thanks a bunch, this really helped me! I was not aware of the toxic lib
I changed the script a little bit to only create cubes on the black pixels found.

So, what I did is the following:
I rotoscoped manually a sequence of a dancer, I’m not running every frame with this script to create cubes where I drew the dancer and now I’ll import that sequence of OBJs to Blender and create a sequence out of it. I’ll share the results when decent.

Thanks again!

OBJExport is available in the Processing 3 libraries with examples and it is working for me:

  • I created a Mobius strip rotating and translating boxes.
  • Exported it as an OBJ file.
  • Imported it into Prusa Splicer.
  • 3D printed it with my new Prusa MK3S. This is just a draft print.

:slight_smile:

1 Like