first commit

0 parents commit da5721912e94fa33fb633ade96703a8acc121a1a committed Jul 30, 2010
Showing with 628 additions and 0 deletions.
1. +46 −0 Line.pde
2. +79 −0 Mesh.pde
3. +80 −0 Slice.pde
4. +165 −0 SuperSkein.pde
5. +207 −0 Triangle.pde
7. sculpt_dragon.stl
46 Line.pde
 @@ -0,0 +1,46 @@ +// Line Class +// Once we have the slices as 2D lines, +// we never look back. +class Line2D { + + float x1,y1,x2,y2; + + Line2D(float nx1, float ny1, float nx2, float ny2) { + x1=nx1; + x2=nx2; + y1=ny1; + y2=ny2; + } + + void Scale(float Factor) + { + x1=x1*Factor; + x2=x2*Factor; + y1=y1*Factor; + y2=y2*Factor; + } + + void Flip() + { + float xn, yn; + xn = x1; + yn = y1; + x1 = x2; + y1 = y2; + x2 = xn; + y2 = yn; + } + + void Rotate(float Angle) + { + float xn,yn; + xn = x1*cos(Angle) - y1*sin(Angle); + yn = x1*sin(Angle) + y1*cos(Angle); + x1 = xn; + y1 = yn; + xn = x2*cos(Angle) - y2*sin(Angle); + yn = x2*sin(Angle) + y2*cos(Angle); + x2 = xn; + y2 = yn; + } +}
79 Mesh.pde
 @@ -0,0 +1,79 @@ +// Mesh Class + +class Mesh { + ArrayList Triangles; + float bx1,by1,bz1,bx2,by2,bz2; //bounding box + + + + //Mesh Loading routine + Mesh(String FileName) + { + byte b[] = loadBytes(FileName); + Triangles = new ArrayList(); + float[] Tri = new float[9]; + //Skip the header + int offs = 84; + //Read each triangle out + while(offs=0;i--) + { + Triangle tri = (Triangle) Triangles.get(i); + tri.Scale(Factor); + } + CalculateBoundingBox(); + } + + void Translate(float tx, float ty, float tz) + { + for(int i = Triangles.size()-1;i>=0;i--) + { + Triangle tri = (Triangle) Triangles.get(i); + tri.Translate(tx,ty,tz); + } + CalculateBoundingBox(); + } + + void CalculateBoundingBox() + { + for(int i = Triangles.size()-1;i>=0;i--) + { + Triangle tri = (Triangle) Triangles.get(i); + if(tri.x1bx2)bx2=tri.x1; + if(tri.x2>bx2)bx2=tri.x2; + if(tri.x3>bx2)bx2=tri.x3; + if(tri.y1by2)by2=tri.y1; + if(tri.y2>by2)by2=tri.y2; + if(tri.y3>by2)by2=tri.y3; + if(tri.z1bz2)bz2=tri.z1; + if(tri.z2>bz2)bz2=tri.z2; + if(tri.z3>bz2)bz2=tri.z3; + } + } + + +}
80 Slice.pde
 @@ -0,0 +1,80 @@ +// Slice Class +// +class Slice { + + ArrayList Lines; + + //Right now this is all in the constructor. + //It might make more sense to split these + //out but that's a pretty minor difference + //at the moment. + Slice(Mesh InMesh, float ZLevel) { + + ArrayList UnsortedLines; + Line2D Intersection; + UnsortedLines = new ArrayList(); + for(int i = InMesh.Triangles.size()-1;i>=0;i--) + { + Triangle tri = (Triangle) InMesh.Triangles.get(i); + Intersection = tri.GetZIntersect(ZLevel); + if(Intersection!=null)UnsortedLines.add(Intersection); + } + + + if(UnsortedLines==null)return; + + //Slice Sort: arrange the line segments so that + //each segment leads to the nearest available + //segment. This is accomplished by using two + //arraylists of lines, and at each step moving + //the nearest available line segment from the + //unsorted pile to the next slot in the sorted pile. + Lines = new ArrayList(); + Lines.add(UnsortedLines.get(0)); + int FinalSize = UnsortedLines.size(); + UnsortedLines.remove(0); + + //ratchets for distance + //dflipped exists to catch flipped lines + float d,min_d,dflipped,min_dflipped; + min_d = 10000; + min_dflipped = 10000; + + int iNextLine; + + while(Lines.size()=0;i--) + { + Line2D LineCandidate = (Line2D) UnsortedLines.get(i); + d = pow((LineCandidate.x1-CLine.x2),2) + pow((LineCandidate.y1-CLine.y2),2); + dflipped = pow((LineCandidate.x1-CLine.x1),2) + pow((LineCandidate.y1-CLine.y1),2); + + if(dmin_d)LineToMove.Flip(); + Lines.add(LineToMove); + UnsortedLines.remove(iNextLine); + } + } + + + + +}
165 SuperSkein.pde
 @@ -0,0 +1,165 @@ +//SuperSkein! +// +//SuperSkein is an open source mesh slicer. +//Note! Only takes binary-coded STL. ASCII +//STL just breaks it for now. + +//Slicing Parameters-- someone should make +//a GUI menu at some point... +//Obviously not as many of them now... +float PrintHeadSpeed = 2000.0; +float LayerThickness = 0.3; +String FileName = "sculpt_dragon.stl"; + + +//End of "easy" modifications you can make... +//Naturally I encourage everyone to learn and +//alter the code that follows! +int t=0; +float tfloat=0; +float[] Tri = new float[9]; +ArrayList Slice; +Mesh STLFile; +PrintWriter output; +float MeshHeight; + + +void setup(){ + size(640,360); + + Slice = new ArrayList(); + print("Loading STL...\n"); + //Load the .stl + //Later we should totally make this runtime... + STLFile = new Mesh(FileName); + //Scale and locate the mesh + //STLFile.Scale(10); + + //Put the mesh on the platform: + STLFile.Translate(0,0,-STLFile.bz1); + STLFile.Translate(0,0,-LayerThickness); + print("File Loaded, Slicing:\n"); + +//Spit GCODE! +Line2D Intersection; +output = createWriter("output.gcode"); + +//Header: +output.println("G21"); +output.println("G90"); +output.println("M103"); +output.println("M105"); +output.println("M104 s220.0"); +output.println("M109 s110.0"); +output.println("M101"); + +Slice ThisSlice; +float Layers = STLFile.bz2/LayerThickness; +for(float ZLevel = 0;ZLevel<(STLFile.bz2-LayerThickness);ZLevel=ZLevel+LayerThickness) +{ + ThisSlice = new Slice(STLFile,ZLevel); + print("Slicing: "); + TextStatusBar(ZLevel/STLFile.bz2,40); + print("\n"); + for(int j = ThisSlice.Lines.size()-1;j>=0;j--) + { + Line2D lin = (Line2D) ThisSlice.Lines.get(j); + output.println("G1 X" + lin.x1 + " Y" + lin.y1 + " Z" + ZLevel + " F" + PrintHeadSpeed); + } +} +output.flush(); +output.close(); + +print("Finished Slicing! Bounding Box is:\n"); +print("X: " + CleanFloat(STLFile.bx1) + " - " + CleanFloat(STLFile.bx2) + " "); +print("Y: " + CleanFloat(STLFile.by1) + " - " + CleanFloat(STLFile.by2) + " "); +print("Z: " + CleanFloat(STLFile.bz1) + " - " + CleanFloat(STLFile.bz2) + " "); + + + //THEN scale to fit + if((STLFile.bx2-STLFile.bx1)>(STLFile.by2-STLFile.by1)) + { + STLFile.Scale(width/(STLFile.bx2-STLFile.bx1)); + } + else + { + STLFile.Scale(height/(STLFile.by2-STLFile.by1)); + } + STLFile.Translate(-STLFile.bx1,-STLFile.by1,-STLFile.bz1); + MeshHeight=STLFile.bz2-STLFile.bz1; + +} + +void draw() +{ + background(0); + //noStroke(); + + //background(0); + stroke(0); + strokeWeight(2); + + //Generate a Slice + Line2D Intersection; + Slice = new ArrayList(); + for(int i = STLFile.Triangles.size()-1;i>=0;i--) + { + + Triangle tri = (Triangle) STLFile.Triangles.get(i); + Intersection = tri.GetZIntersect(MeshHeight*mouseX/width); + if(Intersection!=null)Slice.add(Intersection); + //if(Intersection!=null)print(Intersection.x1 + " \n"); + } + + for(int i = Slice.size()-1;i>=0;i--) + { + stroke(255); + Line2D lin = (Line2D) Slice.get(i); + //lin.Scale(15); + line(lin.x1,lin.y1,lin.x2,lin.y2); + } + +} + + +//Convert the binary format of STL to floats. +float bin_to_float(byte b0, byte b1, byte b2, byte b3) +{ + int exponent, sign; + float significand; + float finalvalue=0; + + //fraction = b0 + b1<<8 + (b2 & 0x7F)<<16 + 1<<24; + exponent = (b3 & 0x7F)*2 | (b2 & 0x80)>>7; + sign = (b3&0x80)>>7; + exponent = exponent-127; + significand = 1 + (b2&0x7F)*pow(2,-7) + b1*pow(2,-15) + b0*pow(2,-23); //throwing away precision for now... + + if(sign!=0)significand=-significand; + finalvalue = significand*pow(2,exponent); + + return finalvalue; +} + + +//Display floats cleanly! +float CleanFloat(float Value) +{ + Value = Value * 1000; + Value = round(Value); + return Value / 1000; +} + + + +//Print a status bar +void TextStatusBar(float Percent, int Width) +{ + print("["); + int Stars = int(Percent*Width)+1; + int Dashes = Width-Stars; + for(int i = 0; i
207 Triangle.pde
 @@ -0,0 +1,207 @@ +// Triangle Class + +class Triangle { + + float x1,x2,x3,y1,y2,y3,z1,z2,z3,xn,yn,zn; + + Triangle(float tX1, float tY1, float tZ1,float tX2, float tY2, float tZ2,float tX3, float tY3, float tZ3) { + x1 = tX1; + y1 = tY1; + z1 = tZ1; + x2 = tX2; + y2 = tY2; + z2 = tZ2; + x3 = tX3; + y3 = tY3; + z3 = tZ3; + + + //Sorting the Triangle according to + //height makes slicing them easier. + Resort(); + + + } + + void Scale(float Factor) + { + x1 = Factor*x1; + y1 = Factor*y1; + z1 = Factor*z1; + x2 = Factor*x2; + y2 = Factor*y2; + z2 = Factor*z2; + x3 = Factor*x3; + y3 = Factor*y3; + z3 = Factor*z3; + } + + + void Translate(float tX, float tY, float tZ) + { + x1=x1+tX; + x2=x2+tX; + x3=x3+tX; + y1=y1+tY; + y2=y2+tY; + y3=y3+tY; + z1=z1+tZ; + z2=z2+tZ; + z3=z3+tZ; + } + + //Rotations-- feed these in radians! + //A great application is rotating your + //mesh to a desired orientation. + // 90 degrees = PI/2. + void RotateZ(float Angle) + { + float xn,yn; + xn = x1*cos(Angle) - y1*sin(Angle); + yn = x1*sin(Angle) + y1*cos(Angle); + x1 = xn; + y1 = yn; + xn = x2*cos(Angle) - y2*sin(Angle); + yn = x2*sin(Angle) + y2*cos(Angle); + x2 = xn; + y2 = yn; + xn = x3*cos(Angle) - y3*sin(Angle); + yn = x3*sin(Angle) + y3*cos(Angle); + x3 = xn; + y3 = yn; + Resort(); + } + void RotateY(float Angle) + { + float xn,zn; + xn = x1*cos(Angle) - z1*sin(Angle); + zn = x1*sin(Angle) + z1*cos(Angle); + x1 = xn; + z1 = zn; + xn = x2*cos(Angle) - z2*sin(Angle); + zn = x2*sin(Angle) + z2*cos(Angle); + x2 = xn; + z2 = zn; + xn = x3*cos(Angle) - z3*sin(Angle); + zn = x3*sin(Angle) + z3*cos(Angle); + x3 = xn; + z3 = zn; + Resort(); + } + void RotateX(float Angle) + { + float yn,zn; + yn = y1*cos(Angle) - z1*sin(Angle); + zn = y1*sin(Angle) + z1*cos(Angle); + y1 = yn; + z1 = zn; + yn = y2*cos(Angle) - z2*sin(Angle); + zn = y2*sin(Angle) + z2*cos(Angle); + y2 = yn; + z2 = zn; + yn = y3*cos(Angle) - z3*sin(Angle); + zn = y3*sin(Angle) + z3*cos(Angle); + y3 = yn; + z3 = zn; + Resort(); + } + + + //The conditionals here are for working + //out what kind of intersections the triangle + //makes with the plane, if any. Returns + //null if the triangle does not intersect. + Line2D GetZIntersect(float ZLevel) + { + Line2D Intersect; + float xa,xb,ya,yb; + if(z1ZLevel) + { + xa = x1 + (x2-x1)*(ZLevel-z1)/(z2-z1); + ya = y1 + (y2-y1)*(ZLevel-z1)/(z2-z1); + if(z3>ZLevel) + { + xb = x1 + (x3-x1)*(ZLevel-z1)/(z3-z1); + yb = y1 + (y3-y1)*(ZLevel-z1)/(z3-z1); + } + else + { + xb = x2 + (x3-x2)*(ZLevel-z2)/(z3-z2); + yb = y2 + (y3-y2)*(ZLevel-z2)/(z3-z2); + } + Intersect = new Line2D(xa,ya,xb,yb); + return Intersect; + } + else + { + if(z3>ZLevel) + { + xa = x1 + (x3-x1)*(ZLevel-z1)/(z3-z1); + ya = y1 + (y3-y1)*(ZLevel-z1)/(z3-z1); + xb = x2 + (x3-x2)*(ZLevel-z2)/(z3-z2); + yb = y2 + (y3-y2)*(ZLevel-z2)/(z3-z2); + + Intersect = new Line2D(xa,ya,xb,yb); + return Intersect; + } + else + { + return null; + } + } + } + else + { + return null; + } + } + + //In the old days, a triangle's normal was defined + //by right-hand-rule from the order vertices were + //defined. If this were the case with STL this would + //scramble the normals horribly. + //Of course, we never USE the normals... + void Resort() + { + if(z3