Significant code upgrade in UCube v08 – I switched graphics libraries from P3D to OpenGL, and — more importantly — stabilized the .stl file export by switching to toxiclibs – now pretty much any .stl file will be able to print straightaway, no sliceform errors, no adjustments necessary! Plus the graphics just look a lot smoother.
Evidence:
/* UCube v.08
* 3d modeling input device and stl export
* now using toxiclibs and opengl
* Manual rotation, shape mode toggle, and export button
* by Ben Leduc-Mills - 2.10.11
*/
import processing.opengl.*;
import newhull.*;
import java.awt.event.*;
import toxi.geom.*;
import toxi.geom.mesh.*;
import toxi.processing.*;
import controlP5.*;
import processing.serial.*;
import javax.media.opengl.GL;
ControlP5 controlP5;
//Nav3D nav; // camera controller
QuickHull3D hull = new QuickHull3D(); //init quickhull
Point3d[] points; //init Point3d array
Point3d[] savedPoints;
ToxiclibsSupport gfx;
Mesh3D mesh = new TriangleMesh();
Vec3D[] vectors;
Serial myPort; // the serial port
float rotX, rotY; //for manual roatation
int gridSize = 4; //size of grid (assumes all dimensions are equal)
int spacing = 50; //distance between points
int counter = 0; //wireframe toggle
String inString; //string of coordinates from arduino
String oldString;
boolean reDraw = true;
PFont myFont; //init font for text
PGraphicsOpenGL pgl;
GL gl;
void setup() {
size(1400,850,OPENGL);
frameRate(13);
gfx=new ToxiclibsSupport(this); // initialize ToxiclibsSupport
//background(255);
pgl = (PGraphicsOpenGL) g; //processing graphics object
gl = pgl.beginGL(); //begin opengl
gl.setSwapInterval(1); //set vertical sync on
pgl.endGL(); //end opengl
controlP5 = new ControlP5(this);
controlP5.addButton("Mode", 0,100,120,80,19);
controlP5.addButton("Export", 0,100,140,80,19);
myFont = createFont("FFScala", 32);
textFont(myFont);
println(Serial.list()); // list available serial ports
myPort = new Serial(this, Serial.list()[0], 19200);
myPort.bufferUntil('\n');
}
void draw() {
//}
//void serialEvent(Serial myPort) {
if (myPort.available() > 0) {
background(255);
smooth();
// because we want controlP5 to be drawn on top of everything
// else we need to disable OpenGL's depth testing at the end
// of draw(). that means we need to turn it on again here.
hint(ENABLE_DEPTH_TEST);
pushMatrix();
//lights();
translations();
drawGrid();
drawAxes();
String inString = myPort.readStringUntil('\n');
//String m1[] = match(inString, "[0-3]");
//TODO: compare inString to oldString to see if coords changed
//if a coordinate string is coming in from arduino
if (inString != null) {
//make acive points more visible
strokeWeight(8);
stroke(255, 0, 0);
if (inString != oldString) {
reDraw = true;
oldString = inString;
}
inString = trim(inString);
//split string of mutliple coordinates into coordinate-sized chuncks
String coord[] = split(inString, ';');
//init point3d array equal to number of activated points
points = new Point3d[coord.length-1];
//put the xyz coordinates into the point3d array and draw them
for(int p3d = 0; p3d < coord.length-1; p3d++) {
int subCoord[] = int(split(coord[p3d], ','));
points[p3d] = new Point3d(subCoord[0] * spacing, subCoord[1] * spacing, subCoord[2] * spacing);
point(subCoord[0] * spacing, subCoord[1] * spacing, subCoord[2] * spacing );
}
if (counter%2 != 0) {
drawHull();
}
} //end if inString!=null
popMatrix();
// turn off depth test so the controlP5 GUI draws correctly
hint(DISABLE_DEPTH_TEST);
}
}
public void controlEvent(ControlEvent theEvent) {
println(theEvent.controller().name());
}
void mouseDragged() {
float x1 = mouseX-pmouseX;
float y1 = mouseY-pmouseY;
rotX = (mouseY * -0.01);
rotY = (mouseX * 0.01);
}
void translations() {
translate(width/2, height/2);
rotateX(rotX);
rotateY(rotY);
}
void drawGrid() {
//draw rest of grid
//(spacing * (gridSize -1) * -1) /2 = center around 0
int xpos = 0;
int ypos = 0;
int zpos = 0;
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
for( int k = 0; k < gridSize; k++) {
stroke(100);
strokeWeight(2);
point(xpos, ypos, zpos);
//println(xpos + "," + ypos + "," + zpos);
xpos += spacing;
}
xpos = 0;
ypos += spacing;
}
xpos = 0;
ypos = 0;
zpos += spacing;
}
}
void drawAxes() {
stroke(255,0,255);
line(0,0,0, 100,0,0);
fill(255,0,255);
text("X", 200, 0);
stroke(0,255,0);
line(0,0,0, 0,-100,0);
fill(0,255,0);
text("Y", 0, -200);
stroke(0,0,255);
line(0,0,0, 0,0,100);
fill(0,0, 255);
text("Z", 0, 0, 200);
fill(0,0,0);
}
public void Mode(int theValue) {
counter++;
println(counter);
drawHull();
}
public void Export(int theValue) {
outputSTL();
}
void outputSTL() {
TriangleMesh mySTL = new TriangleMesh();
for(int i = 0; i < vectors.length; i+=3) {
mesh.addFace(vectors[i], vectors[i+1], vectors[i+2]);
// println(vectors[i] + " " + vectors[i+1] + " " + vectors[i+2]);
}
mySTL.addMesh(mesh);
mySTL.saveAsSTL(selectOutput());
}
void drawHull() {
int numPoints = points.length;
//check that our hull is valid
if(hull.myCheck(points, numPoints) == false) {
//brute force inefficiency
beginShape(TRIANGLE_STRIP);
strokeWeight(1);
fill(0);
for (int j = 0; j < numPoints; j++) {
float x = (float)points[j].x;
float y = (float)points[j].y;
float z = (float)points[j].z;
vertex(x,y,z);
}
endShape(CLOSE);
}
else if (hull.myCheck(points, numPoints) == true) {
if(reDraw == true) {
//print("redraw = true");
hull.build(points);
hull.triangulate();
//get an array of the vertices so we can get the faces
Point3d[] vertices = hull.getVertices();
savedPoints = new Point3d[0];
vectors = new Vec3D[0];
beginShape(TRIANGLE_STRIP);
strokeWeight(1);
//noFill();
int[][] faceIndices = hull.getFaces();
for (int i = 0; i < faceIndices.length; i++) {
for (int k = 0; k < faceIndices[i].length; k++) {
//get points that correspond to each face
Point3d pnt2 = vertices[faceIndices[i][k]];
float x = (float)pnt2.x;
float y = (float)pnt2.y;
float z = (float)pnt2.z;
vertex(x,y,z);
Vec3D tempVect = new Vec3D(x,y,z);
//println(x + "," + y + "," + z + " " + k);
savedPoints = (Point3d[])append(savedPoints, pnt2);
vectors = (Vec3D[])append(vectors, tempVect);
//savedPoints[k] = new Point3d(pnt2);
//println(savedPoints[k]);
//println(x + "," + y + "," + z);
}
}
endShape(CLOSE);
reDraw = false;
}
else if(reDraw == false) {
// print("redraw = false");
beginShape(TRIANGLE_STRIP);
strokeWeight(1);
//noFill();
for(int i = 0; i < savedPoints.length; i++) {
float x = (float)savedPoints[i].x;
float y = (float)savedPoints[i].y;
float z = (float)savedPoints[i].z;
vertex(x,y,z);
}
endShape(CLOSE);
}
}
}
Seriously awesome Ben. You have been busy.
Thanks Dustyn! It’s only because I don’t have to take the insane math classes you do. 🙂