Exporting geometry (.stl/.obj/.dfx) (ModelBuilder and Android)

edited June 2014 in Android Mode

I'm a "returnee" to Processing having not used it in a while. I have an idea for a project that involves using Android for Processing to make 3D geometry, and export it like you can from the desktop version. However, the wiki states that in the Android version "beginRecord, endRecord, beginRaw, endRaw are not available. There are no plans to include them, because it doesn't make sense to use them to export geometry on a handheld or portable device".

I wonder why this seems to "make no sense". To probably only me, this is a logical and indeed necessary function. Are there any workarounds for this that I am missing?

Answers

  • I suppose this is because in comparison to desktop, android apps have less memory/system resources, so they are less suitable as a production tool and more suitable for smaller apps/games. For a workaround you could write a custom export method based on the output file you require. Most of these output formats and export implementations are open-source.

  • Thanks for the reply. I am working with Marius Watz's ModelBuilder library, and have almost got it working. I just need to learn how to save the .stl files to a specific path on my Android device because I cannot find where the exported files go...

  • edited June 2014

    Bumping up because I have another related question. Sorry this is long.

    As I briefly described above, I am playing with Marius Watz's excellent ModelBuilder library. I am trying to save/export an .stl file to the SD Card of my phone. I found this great example of how to save a text string/file by Dimitry Kireyenkov which, works perfectly:

    http://forum.processing.org/one/topic/how-to-savestrings-in-android-22-8-2013.html

    ...but I am having difficulty adapting it to work with a modified/simplified ModelBuilder example I am using just to try and get this part of my project working. There are one of two reasons I cannot do this: 1. (and most likely) I have missed the point of the example and my bad code is missing one or more vital elements, or b) the Modelbuilder library does not allow it.

    I have a desktop version of what I am trying to do (below). It is a simplified version of an example from the library, intended just to get this part of my project working. It works i.e. the .stl file is exported to the sketch folder.

    First tab for "setup":

    import unlekker.util.*;
    import unlekker.modelbuilder.*;
    
    
    UGeometry model;
    
    void setup() {
      size(600,600, P3D);
    
    
      build();
    }
    
    void draw() {
      background(100);
      lights();
    
      pushMatrix();
    
      translate(width/2, height/2, 0);
      noFill();
      box(300);
    
      fill(255,0,128);
      model.draw(this);
    
      popMatrix();
    }
    
    public void keyPressed() {
    
        model.writeSTL(this, "Test.stl");
      }
    

    A second tab deals with the simple build (a centered sphere) and works. The problem is not here.

    void build() {
    
      UGeometry b;
    
      model=new UGeometry();
    
    
        b=UPrimitive.sphere(200, 20);
    
        model.add(b);
    
    
      model.setDimensions(300);
    
    
      model.center();  
    }
    

    I have tried an failed many times to use Dimitry's example, and looked in Daniel Sauter's Rapid Android Development book, and the correct method just will not click. I currently have this:

    import android.os.Environment;
    
    import unlekker.util.*;
    import unlekker.modelbuilder.*;
    
    UGeometry model;
    
    void setup() {
      size(600, 600, P3D);
      noSmooth();
      build();
    }
    
    void draw() {
    
      background(100);
      lights();
    
      pushMatrix();
    
      translate(width/2, height/2, 0);
      noFill();
      noStroke();
      box(300);
    
      fill(255, 255, 255);
      stroke(0.5);
      model.draw(this);
    
      popMatrix();
    } 
    
    public void keyPressed() {
    
      model.writeSTL = (this, new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/test.stl"));
    }
    

    Can anyone offer any tips, pointers on this?

  • edited June 2014

    OK. I am still working on this, and this ^ is the closest to a working version I have managed. The error is for the last line of the code. The console gives a "cannot find symbol" error message:

    java:59: cannot find symbol

    [javac] symbol : method writeSTL(java.io.File)

    [javac] location: class unlekker.modelbuilder.UGeometry

    [javac] model.writeSTL(new File(Environment.getExternalStorageDirectory()+ "/test.stl"));

    [javac] ^

    [javac] 1 error

    ...so I think this is something to do with how the writeSTL function has been designed in the library. Or, am I still missing something?

  • Answer ✓

    The relevant code for UGeometry.writeSTL() can be seen here. The issue is likely in how Modelbuilder tries to find an output stream.

    Sadly, there is no version that accepts a File or FileOutputStream as input. Since I no longer maintain the old library I'd suggest extracting the relevant writeSTL() code and modifying it to be Android compatible. Most of the code should be usable as-is, hopefully only the stream creation part would change.

  • edited June 2014 Answer ✓

    Here is the command in question as a free-standing function. Replace the lines dealing with the creation of a FileOutputstream ("FileOutputStream out=...") with a method that works on your intended platform.

    It's likely that the "UIO.getOutputStream()" method performs some action that's not acceptable.

    import java.io.*;
    import java.nio.ByteBuffer;
    import java.nio.ByteOrder;
    
    /**
         * Output binary STL file of mesh geometry.
         * @param p Reference to PApplet instance
         * @param filename Name of file to save to
         */
    public void customWriteSTL(UGeometry geo, PApplet p, String filename) {
      byte [] header;
      ByteBuffer buf;
      UFace f;
    
      try {
        if (!filename.toLowerCase().endsWith("stl")) filename+=".stl";
        FileOutputStream out=(FileOutputStream)UIO.getOutputStream(p.sketchPath(filename));
    
        buf = ByteBuffer.allocate(200);
        header=new byte[80];
        buf.get(header, 0, 80);
        out.write(header);
        buf.rewind();
    
        buf.order(ByteOrder.LITTLE_ENDIAN);
        buf.putInt(geo.faceNum);
        buf.rewind();
        buf.get(header, 0, 4);
        out.write(header, 0, 4);
        buf.rewind();
    
        UUtil.logDivider("Writing STL '"+filename+"' "+geo.faceNum);
    
        buf.clear();
        header=new byte[50];
        if (geo.bb!=null) UUtil.log(geo.bb.toString());
    
        for (int i=0; i<geo.faceNum; i++) {
          f=geo.face[i];
          if (f.n==null) f.calcNormal();
    
          buf.rewind();
          buf.putFloat(f.n.x);
          buf.putFloat(f.n.y);
          buf.putFloat(f.n.z);
    
          for (int j=0; j<3; j++) {
            buf.putFloat(f.v[j].x);
            buf.putFloat(f.v[j].y);
            buf.putFloat(f.v[j].z);
          }
    
          buf.rewind();
          buf.get(header);
          out.write(header);
        }
    
        out.flush();
        out.close();
        UUtil.log("Closing '"+filename+"'. "+geo.faceNum+" triangles written.\n");
      } 
      catch (Exception e) {
        e.printStackTrace();
      }
    }
    
Sign In or Register to comment.