I have to say that producing my little video has turned out to be a bit of a pain in the neck. It's my first attempt at video though, so I guess I should have expected some problems.
As I mentioned at the end of the last part, I have a set of utilities for writing AVI files that I found here. They came with a little test program which I compiled and ran, so I knew the AVI code basically worked. I wasn't worried about that end of things.
I integrated this into my (slow) ray tracer. Next I needed to position the camera and fly around for the movie. For that, I added a feature to my cube-world demo. I can fly around in that world, and on a function key, write the current position and camera angles to a file. That gives me a way to easily plot out the camera path. The ray tracer then reads this file and produces the individual frames, 30 per second, along the camera track. Simple enough.
The AVI utilities had a routine for adding audio, so I figured I would just do that. Unfortunately, the code makes some assumptions about the audio file that weren't true on my machine (different sized header in one place) so it just crashed. I spent a couple of hours reading AVI documentation, cleaning up that code, and fixing the bug. Then I had an AVI file with audio.
I tried to display the file with VLC, but it complained that my file was damaged and offered to repair it. Once that was done, it displayed correctly. After some more reading and debugging, I discovered the AVI utilities were not handling stereo audio correctly. After I fixed that, VLC was happy and I thought my problems were over...
Handbrake loaded the video, said it was 9 seconds long, and then proceeded to completely botch the conversion. It produced a video 18 seconds long. The first half was perfect, then the audio stopped and it repeated all the video. Playing with the AVI output code, I got several variations. In some cases, Handbrake seemed to be encoding only the difference between frames, giving bizarre results. I never did satisfy it.
Windows Movie Maker read the AVI and produced a video that was correct, except that it was labelled as 15 seconds long, not 9. VLC played it without any complaints, but it was odd.
I finally just went back to pure video and let Movie Maker add the audio and do its default compression (I can't seem to find compression options on that program.) That uploaded fine to YouTube and gave the result you see. Good enough!
Of course, the first time I produced a really long video, the resulting uncompressed AVI file was several gigabytes, and none of these programs would touch it. I assumed there were 32-bit limits on sizes or offsets somewhere, and that I had exceeded them. So I changed the ray tracer to output the movie in gigabyte chunks, then put them together in Movie Maker. Sigh.
Faster Ray Tracing
I reused the Octree code I introduced in Part 1. All the triangles of the scene get put into a tree, so that each "leaf" of the tree contains a list of triangles that intersect that cube. To trace a ray, I start with the cube containing the eye, then step to the next cube along the ray (see Figure 2.) In each cube, I test the ray against all the triangles stored in that node of the tree. When I finally hit an opaque one, I stop.
Most of the cubes of the scene are empty space and take no time to test. As you step along the ray, you quickly come to the triangles of the scene. There may be a dozen in a cube. One of these is the opaque one that stops the ray, and you are done. For transparent triangles, the stepping continues until we hit something opaque. Then the same stepping is used to trace the ray from the hit point to each of the light sources.
While I was at it, I restructured my ray tracer to use multiple threads, so that I could get the most out of my machine (an AMD Phenom II six core CPU). The new version rendered my Minecraft chunk, which turns out to have 461 lights and 342,970 triangles, in 2.4 seconds. See the resulting image in Figure 5, with the Minecraft and unlit demo versions in Figures 3 and 4.
This still doesn't look like the Minecraft version, but now that I look at the lighting there, I can see where I'm different. For one thing, Notch casts all shadows directly below the object, so the tower on the right is all in shadow in the Minecraft version. In mine, the shadow is lighter because it's only facing away from the sun, not shadowing itself. The ray tracing also produces more accurate long shadows from all the cubes in the landscape, and from the bridge. Because of the way I implement transparency, the shadows are not cast on the surface of the water, but on the bottom. A real ray tracer would fix this, but what I have here is good enough to go on with.
Due to all the issues with audio and video production, I didn't actually do any world building this week. As a consolation prize, here's a video of my chunk of Minecraft data from twentymine.com
In case it's not clear, you start this video underwater, in a garden inside that glass pyramid at the back/left of the image above. The various transparencies in the walls and water make for a confusing backdrop. The camera path could also use some work...
Update: If you want to play with the ray tracer yourself for some reason, I've uploaded it here.
Update: Here's a version with glass panes that have edges. It makes it easier to see what's happening at the start, although there's a lot of aliasing around the frames.
blog comments powered by Disqus