Project #6 - Constructive Geometry - Math 155B

Student: Igor Kaplounenko

Comments:

The premise of this project was to develop classes that would allow the use of constructive geometry
in image generation.  Thus, one would then be able to take the intersection, a union, or a difference of
multiple objects in order to come up with a more complex object that is still easier to raytrace than a bezier
patch.  Such was my plan.  As you can probably tell from the provided images, most of the time has been
spent coding and debugging, although, of course, some among you may find images of something that
resembles a black-and-white photograph of bullet-ridden cheese to be very pleasing aesthetically.
Because the images don't really cover the extent of my work, here's a list of modified/created stuff:

Modified Files: RayTraceData.cpp (of course)
	        RayTrace.cpp (i'm particularly proud of the counter in the title of the raytracing window that 
		shows the number of lines traced; it's probably my greatest achievement on this project)
	        GlutRenderer.cpp (for rendering new object types)
	        ViewableBase.h (added enums to account for additional object types)

Created Files:  ViewableDifference.h & ViewableDifference.cpp
		(this is supposed to display the first object in the array minus all the successive objects; it even
		 succeeds somewhat...)
	         ViewableIntersection.h & ViewableIntersection.cpp
		(used for the intersection of all the objects in the array; as far as i can tell it's the only thing that i'm
		 absolutely sure that it works perfectly, or reasonably near that.)
	          ViewableUnion.h & ViewableUnion.cpp
		(used to store the union of all objects in the array; it appears to work, but i haven't tested it extensively)

The cheese itself, by the way, is a difference of (intersection of a parallelogram and a cylinder) and a bunch of spheres
that i clearly didn't put a lot of effort into placing, primarily because it was meant to be semi-random anyhow.  But yes,
it does mean that these constructive geometry objects stack.

Difficulties encountered in this project:
	There were a lot of difficulties i can only attribute to "human error".  When you have pointers to arrays of pointers
it is very easy to allocate the objects pointers point to, have them die at the end of the function, but still attempt to access
them because they're still pointed to.  Additionally i've had lots of amusement casting and dereferencing viewablebase
pointers in glutrenderer.cpp.  And, last but not least, it took forever for me to determine that not initializing the
intersection distance value to some unreasonably large number was making everything look so horrid, including having
invisible parts of objects show up as faint grey.
	Trying to get these complex objects to display properly was also quite a feat.  For one, the way the raytracer
is currently implemented, invisible objects with refraction index of 1 can still cast perfectly solid shadows.  This killed my
original idea of counting all the intersections and simply changing the materials of the appropriate ones to "transparent",
since then the object could end up being completely black just because it has a transparent layer of itself blocking the
light source.  Initially i decided to resolve this by editing the shadowfeeler function to ignore fully transparent objects,
which, oddly enough, resulted in me getting stack overflows.  Although i managed to bypass it eventually, i ran into
some trouble trying to place complex objects within other complex objects and still have stuff work right.  In the end
I had to make FindIntersectionNT calls within the complex object types recursive, ignoring transparent layers and only
returning actual physical ones.
	That wasn't all, of course, and some objects could still look very very odd, with transparent ones magnifying
objects behind them in a strange fashion.  The reason for that ended up being wrong indices of refraction which are
automatically inverted if the subobject's FindIntersection function determines that the ray will actually be exiting it even
though in actuality the opposite is taking place.

Okay, this is starting to look like a term paper.  I better stop.  Regardless, here are the images.

List of figures

  • For those who stayed with me this far, here are the images of what happens when you mess up:  The first one 
    is the difference of two spheres.  As you can tell, the invisible layer is actually quite visible, being bright gray.
    The second one is when your code decides that it doesn't want to treat intersections as intersections anymore
    because you put it into another object array, and thus wants to now render it as something that vaguely resembles
    a union with cutouts.