I wrote a few days ago about how I had this killer (simple but useful) Mac application idea bouncing around in my head for a year now. I have to confess I’ve spent a fair amount of time over the last three days in refreshing my Cocoa programming skills, and I’ve written my first decent test-app: a Mandelbrot generator.
Back when I was a teenager I was fascinated with the Mandelbrot set. It was kind of the “hallmark image” of the then-newly-emerging field of fractal geometry. This was the same field of Mathematics that was allowing computer-generated landscapes like moon in the Genesis Planet Demonstration video from Star Trek: Wrath of Kahn. I remember staring at the strangely beguiling image in a Scientific American article, fascinated with its strange features. Also incredible was the fact that no matter how closely you “zoomed-in” to a point of the Mandelbrot set, you got a uniquely different-yet-similar picture.
I remember being about 16 years old and reading and re-reading the article, trying to understand the relatively simple mathematics behind it. It was just the equation z=z2+c but in the complex number plane. I understood complex numbers and had a year or two of algebra under my belt, but couldn’t get it. Then one day I had that “eureka” moment and it all made sense. I jotted down the simple quadratic, translated it into a computer algorithm and set to writing a program to test it.
This was in the days of DOS. I wrote my program in Turbo Pascal, where it wasn’t all that difficult to set color values to individual pixels on a computer screen. In fact, in those days that was almost the only way you could do graphics! Granted, there were libraries to do the incredible feat of drawing lines and adding simple text labels, but in the end you were working with setting the grid of 320×200 pixels one of four colors. (I’m talking CGA graphics mode. Actually, my NCR PC 6 had a “special enhanced” graphics mode of 640×400 pixels and four colors.)
The numerical calculations were not complex, but there were a lot of them. I remember that generating a 640×400 image took a little over 2.5 hours on my 8 Megahertz 8088 computer, and the 32-bit floating point operations meant I couldn’t zoom in for too much details, but it was still amazingly cool.
For a few years my hallmark of breaking in a new computer involved rewriting my Mandelbrot generator. It looked far better on my Dell 286-20Mhz PC with 287 math-coprocessor. That had an actual VGA (640×480 at 256 colors) monitor and rendered the image in about 45 minutes. My first time on an 80386 computer it was even faster.
I want to reiterate how much the art of “writing cool looking things on the computer” was to me back then. As a kid I spent endless hours with my friend Tom; we both started with the Texas Instruments TI-99/4A and then both moved on to PCs and Turbo Pascal. We would write graphics programs that would do primitive CAD. Actually, Tom did most of the heavy lifting with really involved programs like that. I diid the simple model of the U.S.S. Enerprise that could be rotated around in 3D, scaled, etc. It was Tom’s experiment with optics and visual perspective. We wrote some (very lame) video games on the TI-99/4A in BASIC. My friend Bryan had an Atari for which he knew every byte and how to do crazy and magical graphical stuff. Those were also the days when kids were writing amazing programs on the original Apple, just by “poking and peeking” special byte values in special locations. It was the ultimate era of tweaking.
Then came the days of Windows. All of a sudden I didn’t have control over the pixels on the screen. I didn’t know how to draw simple lines. Programming became weird and difficult, and as powerful as it seemed with this new Windowing and multi-application paradigm, I felt like things got too complex. 1990 marked the end of my era of writing “neat desktop applications”. I became more of a “systems engineer” of the application development was more in data-management or statistical computation applications. Yeah, they were important, and I’ve carved out a decent career over the years, but I missed the days of “writing a cool program that made something pretty on the screen”. (An analogy that might appeal to my brother: the Golden Age of Tweaking I mention above was like the old days when cars were simper, and a high school boy could take apart an engine and fuss with the carburetor, etc. without some magical plug-in computer interface. I blame the end of that Golden Age of Tinkering with the downfall of the American Automobile.)
So a couple days ago, really just a few minute after writing that article about my Task Manager program I wanted to write, I picked back up my copy of Cocoa Programming for Mac OS X by Aaron Hillegass, and started on page 1. I got to page 232 when I decided I would have to try actually fiddling with all these new concepts before they just started mushing together in my brain. And I decided the best “real app” that would test whether I could move beyond the simple cookie-cutter demos was to rewrite the Mandelbrot Generator.
As powerful as modern computers are today, it’s amazing that something as simple as directly controlling a grid of pixels and assigning colors to them is so hard. It seems the writers of books and documentation can’t imagine such a desire. What do I mean by not writing some application with buttons and tables and text fields!? Oh my! For a while I started getting really frustrated. There was the NSImage class, which could make it effortless for me to load a JPEG from a file, scale it, rotate it, zoom it, add layers of transparency to it… but I didn’t want to load a file image, and I didn’t want to scale it. I wanted a one-to-one correlation with pixels in front of my face.
Finally I got it figured out. I just had to understand how to create an NSImage based on an NSBitmapImageRep (which I would actually draw on) and have it managed by an NSImageView. In truth it ended up being pretty simple once I figured it out—don’t most things end up that way—and it was remarkable how easy it was to add controls to let me type in coordinates, later adding the ability to click on a point in the image to zoom in. There’s a lot I could add to this program—resizing, unzooming, custom coloration schemes, multi-threading so the app doesn’t lock up for a second during computation. I also really wanted to handle the mouse-click using a delegate instead of subclassing the NSImageView, but I need to start the next chapter in the book.
It is a wonderful feeling, however, being able to get back into “sitting and writing neat and fun programs on a computer”. And everything I’ve said about OS X Cocoa being a revolutionary programming environment is still true. For anyone with a Mac who cares, here’s my (unfinished 0.9 version) app: MandleTry Cocoa Mandelbrot generator.
Addendum
A few people recently asked in the Comments section for source code. I’m not going to release the entire package, but I’ll release part of the Objective-C source code that calculates the pixel values and, more importantly, uses the NSBitmapImageRep class to do the pixel-manipulating magic most elegantly.
Bug Report:
MandelTry immediately crashes on my Mac Mini Core Duo running Tiger.
Glad you were able to write a good Cocoa app, though.
Cheers.
Thanks for the word. For some reason I had the same problem on my PowerBook. (I was developing on my Dual G5 PowerMac.) I thought for a second that maybe it was compiling for 64-bit code, but that appears NOT to have been the case.
My best hypothesis is that it had something to do with ZeroLink—the XCode feature that allows a developer to change the source code and have those changes immediate register with the program while it’s still executing, but I don’t have the time to test that extensively.
I DID instead tell XCode to compile a “release” version of the executable instead the “debug” target (oooh, that reminds me, I need to change it back now) and that new binary does indeed run on my laptop, so I think it’ll work.
I also told XCode to generate a Universal Binary, but I have no idea of knowing whether it made one or not. I figured I would see two binaries in the resulting package (via Show Package Contents) or at least some parameter in the Info.plist file, but I don’t see anything. I also couldn’t find on the net anything suggesting how a person can tell that a program is indeed a Universal Binary.
Anyone know the answer to that?
Anyway, the binary linked in the article should now work.
I think for me my days of programming ended when Compute! magazine stopped publishing listings of complete programs you could spend hours typing. I learned more about the secrets of peek and poke from those lengthy examples than anything else.
Oh and hey, what was the name of that CADish program you and Tom worked up? My weak memory says “Perspecs†or some such and that it was an acronym for something? Can you remember?
You’re exactly right, Bryan. I’d forgotten all about that. (But then again, you had those Pete the Fish cartoons! You shall be dubbed the Great Historian!)
Something I loved about Perspex: It was written as a combination of two programs the first would “compile” your CAD image from a series of human-readable commands into a more compact binary file that the second (the actual graphics rendering program) would use. We decided to be funny and actually have the compiler insult the programmer if it found errors.
It must have been immediately following reading Hitchhiker’s Guide or something like that, being inspired by Marvin and the happy Improbability Drive ship’s computer. The more errors you had in your file the nastier the compiler’s temper. If you compiled an error-free file, it’s response was some happy happy joy joy sort of thing.
Heh, now I’m remembering the semester in High School I got to spend learning vector based graphics programming on the Evans & Sutherland workstations at CSU. (Although I probably spent more time goofing about with unix and playing netrek.) I remember at one point though I had managed to code a wire frame model of a robot whose arms could be manipulated via potentiometers (paddles.)
Wow, have my programming abilities atrophied since then. Well, I’m glad one of us is still able to program up something neat.
The Mac programming environment (read: the NeXTSTEP programming environment that is now Mac “Cocoa”) is really as fantastic as I’m always raving. It takes a little figuring-out how to get things working at first, but it is amazingly easy to do vector drawing, 3D OpenGL, scaling and rotating, etc. with Cocoa, and assembling your widgets and getting controls to respond to them is light-years beyond most other development environments. Ie. if you were programming in Visual C++ for Microsoft, I can’t begin to express how complicated it is to actually render a button and have that button-press launch a simple snippet of code.
One of the brilliant things (IMOHO) that Apple did was to include this development environment for free with every computer. Whereas Microsoft charges boatloads of dollars for their tools, Apple followed the Linux model here. Apple also maintains an dizzingly extensive library of “Apple Developers Connection” documents for all these technologies.
In addition to the standard documentation and API references, they also regularly publish articles with (sample code) as supplementary documentation. These articles either give extra help showing a new technology and how it works, or they give extra explanation of some topic when Apple feels the developer base (ie. mortals like me) are having an extra-hard time grasping some particular angle.
All in all, I’m feeling like with Cocoa, the good old days of scrapping-together some neat little program are back. The sad thing is that few people know this.
One thing about programming on a Mac that doesn’t make a lot of sense to me is the way XCode and Interface Builder are (or aren’t) integrated. When and how to use each app. can be a bit confusing. Thankfully, Aaron Hillegass actually explains this very well (unlike Apple). I really do like that book and very much second the recommendation.
murray…can I borrow your brain?
Any chance of you releasing the source?
Any chance you could share your pixel-drawing code? I’m trying to do something pretty similar (another fractal generator, but more generalized) but at the moment I’m stuck at the filling-1px-by-1px-rectangles-very-very-slowly stage. 😛
In response to the last three comments (which I neglectfully didn’t see in sitting in my moderated-comments queue until now) I’ve just added a link to a snippet of Objective-C code that handles the Mandelbrot calculations and the Quartz drawing. Look at the very bottom of the article now. (Under “Addendum”)
And to “Cocoa Newbie” sorry, but my brain is spoken for. (And it’s not what it used to be. The odometer is going to flip over any day now.)
Fantastic work! Thanks for the source posting. Helped me out immensely.
I may be a little late coming to this party, but tried to DL the app or the code and couldn’t, I get:
You don’t have permission to access /wordpress/wp-content/uploads/2006/09/fractal_code.html on this server.
Cheers,
Leo