Twonky began in my mind in a state of doubt.  I know that is usually never the thing, or to put it better I never imagined I’d be capable of such a thing.  I even thought about stopping work on it in the very beginning because I felt my programming and math skills aren’t quite where they should have been, they still may not have been there 100% but I will admit up front I have pleased myself greatly with the progress I have made with Twonky and hope to continue to make.

 

What is Twonky?  

            First off Twonky in its original form is my favorite robot from the game Robo Rally, now from Avalon Hill and the original version from Wizards of the Coast.  However in this sense I am dedicating this project to my favorite robot who brought me many victories to him and Twonky in this sense is a Ray Tracer that I wrote entirely in C++.

 

New Concepts and C++:

            The initial setup of Twonky brought about some new ideals and design paterns in C++ I honestly had never heard of, let alone knew how to setup.  My teacher of the class/project thought to clean up the code and help us learn some methods becoming popular, or at least write better code suggested the use of Factories and Singletons.  This was to be implemented from the start, in addition to the setup of the class structure.  These new design patterns brought about a world of headache and pain to wrap my head around.  However, with a little research, some testing, and some help from my fellow classmates we were all able to help each other figure out and get working both of those design patterns quite successfully I might add.  Factories were the worst to figure out, but man once I did, I don’t know how I lived without them. 

            Twonky really brought out my bad programming style I had up until this writing this code.  It forced me to really utilize the full aspect of C++ and the use of the Object Oriented Programming to clean up and organize my code 100 times better than anything I had done before.  One other aspect I learned is to really utilize inheritance for what it is and is meant to be, I had used it minimally before and didn’t really have a lot of knowledge as to how to best use it, or using it period, but I do now.  Lastly, on this I would like to state that I now know how and when to create a new class in order to keep code clean and readable for everyone, which goes along the lines of using inheritance as well.

 

The first visible results:

            I tell ya, when I got my first actual render to be seeable in an image viewer (Photoshop since I was and still am writing to Targa files) I almost cried, I never imagined I could actually “create” an image by writing some code and a basic text file for input.  I had always used Maya or some 3D software to do it, but to know I created it, wow it was great.  Sure it was just a ray cast render, so all the spheres looked like circles with no lighting, or shading elements to them.  Just black with colored circles, but it was still a wonderful feeling to see progress being made.

First Raycast Render:

 

The next step:

            Well now that I had flat spheres rendering out, I had to add in surface shaders and lights in order to make these spheres well…look like spheres.  So now began the fun of writing basic diffuse and specular surface shaders, plus directional and point lights.  This didn’t prove incredibly difficult, my specular shader did give me some really fun and unexpected results, and actually took me a long time to figure out why, it took a fair amount of debugging to track it down, but I did and man it was a bugger to find.

Shaded Spheres:

 

Shadows and Anti-Aliasing:

            Shadows came about easier than I first thought they would, it was a simple calculation to see if the ray was hidden by the last object intersection…simple.  However, when it came to Anti-Aliasing, or Super-Sampling depending on how you look at it, that was another story.  This seemed like an easy concept to shoot some extra rays at that pixel and take an average of it.  Well something went real wonky in my calculation and I was getting what looked like a sphere exploded into millions of pixels.  Which as you can imagine was not what I wanted.  This bug took me almost a week to find.  Turns out I was calculating the increment of the ray direction by dividing it by the wrong value entirely, so my rays were deviating more than one sometimes two pixels at times, which again is bad.  This one took me and two other people looking at it to resolve the problem and find exactly why it was happening.

First Super-Sample:

 

            Before I continue on to the next progression in Twonky, I must tell you of a MAJOR problem I hit during the development.  My infinite planes had to be simply the biggest problem I hit during this entire project.  I went through at least three to four different ways to calculate a ray-plane intersection, countless books, web sites, people, all telling me similar things as to how to do it.  This was incredibly annoying as infinite planes are essentially the easiest to setup hit detect we encountered.  I had incredible results, I mean real weird stuff.  However, it was solved, thanks to a good friend of mine Ronn who noticed I was using the same hit record every hit detect, I wasn’t saving the old one, so my planes were never recalculating a new object that might be hit, only themselves once hit.  So as you can see in the above image there, I did get them working and then they all rejoiced.

 

Depth of Field and Soft Shadows:

            Another problem similar to my super-sampling, since I wanted to implement a more realistic form of depth of field I got renders that looked like exploded spheres all over again, and again a similar solution so this one didn’t take me as long to find.  The soft shadows came quite easily, I now implemented sphere lights, which are capable of shooting multiple light rays from a specified area as to illuminate and shadow softly, but it tacks on render time like one might imagine.

Pretty soft shadows:

 

Texture and Reflect stuff:

            Thanks to my teacher, texturing was fairly painless, he gave us a pseudo setup as to what one might need to calculate the UVs of a sphere and plane and we went from there.  Since I was doing similar calculations in other areas of the project (at least when it came to calculating UVs of a plane) this was mostly modifying of some code already there, nothing too major to tell of here other than I still appear to be having a problem with my textures being flipped on spheres, I’m still working with some things on that.

            Reflections were sort of something I stumbled upon when looking through a book, noticing I already had the reflection vector calculated, I just needed to have that get me a color of something it hits, so quite literally and unintentionally I had already setup the reflection code back when I was doing specularity I believe.

 

 

 

Textured Sphere with reflections:

 

The Future of Twonky:

            Well I doubt highly this is the end of Twonky, just as far as the class is concerned I am done with it.  I know I will continue to work on this working to get other things working in there as I want Twonky to be the best that he can be.  So for the class I now have triangles working in there and getting triangles to work only means one thing, the ability to import 3D meshes into the scene, currently I only support *.obj file format, but still it works and looks great.  I couldn’t be more excited with now being able to import meshes, however it does tack on some significant render time.  I had some issues at first with my triangles only drawing two of the points in and magically picking the third one, it was real annoying.  However, upon reading closely a great book I got it, and the best part is a triangle basically gives you the setup for the UVs right away, so texturing meshes now was a snap.  The only major problem hit here aside from the wonky triangle thing, was my mesh vectors kept breaking on themselves, driving me nuts, but I did eventually figure it out and noticed it was one of those dreaded copy and paste errors.  I was calling a location in the vertex vector when I needed the normals vector of the mesh, and as you can imagine this causes and unhappy compiler.

Octopus of Doom:

 

In Conclusion:

            I feel this Twonky has taught me a lot about writing precise and clean code up front and right away, it saves SO many headaches in the end.  I also have learned the magical (and what still appears to be somewhat rare) art of commenting the crap out of my code.  After a long real late night of coding, half the time you aren’t writing anything clear anyways, let alone your comments, but they still help that next day when you are trying to decipher a problem or piece of code.  This project has taught me the importance of classes, inheritance, make sure I comment any and all code I write, and how to keep code clean and readable.  I have gained so much from this project, not only a ray tracer that I wrote, but some incredible programming practices that I had nothing close to before writing it and taking this class, thank you Twonky.