My senior project at OSU was to create the software for a home fabber project. The software would read a file in STL (stereolithography) format and convert it into a format that the fab machine could understand. Everything was up to me as far as how it was written, and I was the only CS student working on the software.
It was a real learn-as-I-go experience. I could have written something in linux using C with a command line interface, but I wanted to be able to show people something that anyone could understand. I decided to create a GUI that could display the shape loaded and allow the user to manipulate it. Problem was I didn’t know how to create a GUI. Visual Studio makes it real easy to create Windows GUI’s, so I used that.
I had never really used Visual Studio before. Most of what I had done was in ANSI C or C++ using command line compilers like gcc and text editors. It turns out that it was easier to create Windows forms using .Net. This means managed code. This means I could not automatically paste regular C++ code into my GUI project. I could have learned MFC, but I did not have the time. I figured out how to make the C++ code I knew how to create mesh with the managed .Net code. It wasn’t pretty.
Next, I had to figure out how to display 3D shapes. The obvious choices were OpenGL and DirectX. I had heard tons about how easy OpenGL was, how great the resources and community was and horror stories about how hard DirectX was. The DirectX was appealing actually, I like I challenge and I know it can do great things, but I was still limited by time. I just OpenGL as the faster (as far as code writing) of the two. With the help of CodeProject, I figured out how to place an OpenGL control on a windows form.
All of the previous was the easy part. I now had to figure out how to manipulate the 3D file into something the fabber could understand. An STL file describes a mesh. A mesh is a description of a surface. I needed to send info about interior volumes to the fab machine. This was tough because I had to be able to describe the problem in accurate terms before I could even begin to search for and formulate a solution.
My initial plan was to decompose the shape into small cubes. The printer could understand this. If the software says that there is a cube at X,Y it spits out some goo at X,Y (Ok really it was X,r but more on this later). I had no idea how to do this. The STL describes a mesh in terms of triangles. I limited my problem to converting a single triangle into a triangle composed of cubes. Once this was done to the whole mesh, the interior could be filled with cubes. I had no idea how to do this either. I further limited the problem to being able to detect if a line intersected a triangle. From here I could construct the cubes. Now I was making progress. There was lots of good info about how to do this on the Internet.
I then realized that this was basically a collision detection problem. I had done this in 2D back in the good old days on my Commoder64 (yes I’m an older student), but collision in 2D was not the same as collision in 3D. Collision in 3D relies on bounding boxes. In many video games, the collision detection is really between the bounding boxes of 2 or more shapes. This was not good enough, I needed to accurately describe the whole shape, not the bounding box.
What I could do though, is use the bounding box of the mesh as a good way to define a point that is definitely outside of the shape. I could then pick a point at random and by comparing it to the point on the bounding box test whether that point was on the inside of my mesh or on the outside. Turns out that there is a nifty algorithm that can do this, and it works for 2D and 3D shapes as long as they are solid. They could even be concave. It’s not proven to be 100% accurate, but it works well enough for my purposes. I started writing the software for this but soon found a nice software library written in C that does this and provided a nice data structure for the meshes.
So here is what I did: I created a small box shape, to represent the smallest thing the printer could create. I then moved the shape in a sequential pattern and at each placement I test each corner of the box for it location inside or outside the mesh. If 6 of 8 corners were inside, the box itself was considered to be inside the mesh and the fabber would print in that location. All of this would be displayed on my GUI as it happened.
And the project was a success.
There you have a wordy but by no means complete description of my project. There was a lot more I could have done and wanted to, but my goal was to have working software to go with the working fabber the engineers creates (they were really sharp guys). There probably should have been at least 1 more CS student working on this, but this was a new type of cross discipline project and was somewhat experimental.
Some of the things I would like to change:
- Write the whole thing in one language
- Make it more modular
- Have a requirements document
- Re-write the pre-written code
- Unit testing
So here begins the Rototyper Software v2.o project!
It will be:
- Written in C#
- Written with DirectX
- Modular
- Created from scratch
- Unit tested
- Fully documented
- Usable with a variety of home fabbers
In the long term, I plan on creating a version usable on Linux machines as well.
I’ve already gotten a good start on the project. This blog will track my progress of the project. I hope to be able to give my completed software back to the OSU engineering project for future student project use. It was an awesome project and I hope they continue it.