Code
August 10, 2005
New demos: OpenGL Java LWJGL
Entry posted by Mark at August 10, 2005 10:59 AM
I overhauled my Java OpenGL demos to use LWJGL version .97, and did some substantial code cleaning. These demo applications demonstrate many valuable features of the OpenGL graphics api, using the LWJGL Java/Opengl binding.
Changes include:
* upgraded to LWJGL .97
* wrapped model loading into a new GLModel class
* new 3DS model loading demo
* added documentation
The base class GLApp.java is now easier to use. This class wraps many useful OpenGL features includes loading images, creating textures, setting display modes, creating lights, running a game loop and many more.
OpenGL Java demos and source code: http://potatoland.com/code/gl
April 17, 2005
Death to Dependencies
Entry posted by Mark at April 17, 2005 09:45 AM
java.net: Breaking the Last Dependency
Elisabeth Freeman and Eric Freeman demonstrate a technique to remove hard-coded dependencies between classes. By loading class types from a properties file they create a simple plugin architecture that allows core code to refer to classes at runtime, without explicit knowledge of their type. This approach can break compile time checks (you store class types in a text file, outside of the scope of the compiler) but that loose type checking at compile time allows for flexible connections at runtime.
April 16, 2005
If programming languages could speak...
Entry posted by Mark at April 16, 2005 09:37 PM
Burningbird » The Parable of the Languages
A hilarious and strangely believable story by Shelley Powers, about a gathering of programming languages. My favorite is C, "a rude language and hard to live with". Back when my day job used C for software development, I wrote up a test to give to prospective programmers to see if they actually knew C or just memorized parts of it. The last question was:
char c = "abcdef"[2];
What value is stored in c?
C let you do things like that. Rude, yes, but the language gave you these sublime moments, like alchemy. A glimpse into the heart of the machine.
April 14, 2005
Encapsulation in the Real World
Entry posted by Mark at April 14, 2005 10:24 AM
Encapsulation is one of the cornerstones of object oriented programming. With encapsulation we can represent or "abstract" an object in computer code. We can describe the object; it's features, capabilities, properties, what it can do and how its behavior can be modified, to describe the rules of a system or to mimic the behavior of a real-world object.
But does OOP actually encapsulate objects as we are familiar with objects in the real world? The OOP approach does a good job at "wrapping" a set of behaviors and properties while hiding internal details, yet it is in these hidden details that OOP falls down and fails to truly encapsulate an object. One of the founding rules of a class is that it hides its implementation. The internal workings of the class are private, and can be accessed through methods, without knowledge of how the object works on the inside. With this approach the programmer can work with the abstract idea of the object, minus the ugly details of implementation, yet ignorance is not always bliss. If we take encapsulation to mean that an object is fully enclosed, distinct from its surrounding environment, then we find that we don't have encapsulation in the current OOP model. Since the internals of the class are hidden, the class is free to refer to any number of other classes, without formally describing these dependencies. This "hard-wires" the class into its surrounding context and breaks from true encapsulation.
For example let's compare the OOP model to a real-world situation. Suppose I see a pen placed on a piece of paper on a desk. It's safe to assume that I can pick the pen up. I don't expect the pen to be permanently attached to the desk it's resting on. It goes without saying that the pen is fully encapsulated (by virtue of its physical existence in the world), meaning that when I pick up the pen, the desk stays where it is. The paper stays where it is. There is no hard connection between the paper, pen and desk, though the three may be used in conjunction. I can pick the pen up and put it in my pocket, walk out of the room, even leave the country. The pen still works. I can write on paper, but can also write on other surfaces. Indeed I can try to write (with varying degrees of success), on any flat surface I find. The pen doesn't care what the "type" of the surface is.
Now translate the pen into OOP. We make a class called Pen with a method: write(Surface). Simple enough, but is this really encapsulating a pen? For the pen to write I need to also create a Surface class to write on. This is still a simple enough class definition, and accurately describes what a pen can do. But let’s look at the internals of the class, at what the Pen does with other classes. Let's say the Pen can draw either freeform lines or can type letters in a given font. The Pen class refers to a Surface class, a FontMetrics class, a Font, a Texture (for stippling lines) and perhaps a 2DGeometry drawing class for generating paths. Now in the OOP environment, when I try to move the Pen out of its existing context and compile it somewhere else, I find that I'm missing 5 other classes that must be present for the pen to work. The pen is married to the Surface it is designed to write on. It cannot function without it. We don't have a Pen, we have a Pen+Surface.
Two Java features let us split the pen away from the context it's developed for. We can use the import statement to define dependencies on external libraries, for things like Graphics contexts, awt or swing, but import statements are broad and don't provide much clarity on how the pen refers to these external libraries. And while import statements define references to defined packages (ie. Font,FontMetrics, awt, etc.), it doesn't help us much with referring to our own custom types, such as the Surface and Texture classes.
For our custom class types we can use interfaces to separate the Pen from dependent classes. For instance we can create a Drawable interface so that Pen.write(Surface) method becomes Pen.write(Drawable someDrawable). Now the pen is no longer married to the Surface class, it's married to the Drawable interface, and the Surface is also married to the Drawable interface. While the idea of a remote marriage has its appeals, it's still a fairly context specific arrangement. Other surfaces/canvases/panels must implement Drawable in order to be used by my pen. And we still haven't addressed the other references that the pen makes, such as the hypothetical Texture class. Do we create an interface for every external reference the Pen makes? Programmers are urged to take this approach through "best practices" but they usually don't. Despite the moral and ethical urgings of the gurus, this approach is time consuming, requires planning and a high level of agreement between the code-sharing parties. Ultimately it's not as flexible as we'd like. It doesn't pay off in the short run and the additional interfaces present a maintenance overhead in the long run, so this step is often skipped, and programmers fall back on the easy, fast and simple direct reference. It's easier for the pen to stay married to the paper than to arrange the (appealing, yet idealistic) threesome of paper pen and interface.
So does OOP give us a truly encapsulated pen? No not really. It's more like those pens at banks that are wired to the desk so you don't steal them. As long as it's easier to hard code references than to make soft references, hard references will propagate and classes will not truly be separable. A truly encapsulated pen is a Pen that is easy to steal, so easy that we have no need to create our own.
I haven't discussed how true encapsulation could work in OOP... I'll save that for another post.
March 28, 2005
Why Programs Crash and Buildings Don't
Entry posted by Mark at March 28, 2005 10:29 PM
On his blog John Reynolds asks "Why is so much software so bad?". I think the answer to this question is not in the methods used by programmers, but in the nature of OOP languages themselves.
When the question of software quality comes up, the conversation usually turns towards the craft of programming. We hear about design patterns, best practices, methodologies, extreme programming, management techniques, better specs, better tools. The emphasis is on how the program is created, and how we can be better programmers. A program is essentially a hand-crafted good. To improve programming we improve programmers.
Yet as long as programming is a hand craft, where individual humans operate on individual lines of code, software will never be any better or more reliable than the programmers doing the coding. One line of faulty code, even one byte of data written outside of allowed memory, can crash a program. Imagine the fragility of a building or bridge if the entire structure could collapse due to one faulty rivet. Good craftsmanship can correct this only partly and requires a surplus of extremely dilligent rocket-scientist programmers. The solution is not to improve the craft, the solution is to design inherently stable systems.
Fortunately software is not the first technology that has worked through these growing pains.
To see how software projects can scale up, we can look at other technlogies that have scaled up succcessfully. Look at buildings. The components are very simple, predictable, and provide no-brainer redundancy. You can build nearly any building from a collection of I-beams, granite slabs, cement and glass window frames (all pre-fabricated units). The building can be put up by hi-school grads. No rocket scientists needed.
Look at electronics. Again, simple components that can be combined predictably. Resistors, capicitors, transistors, chips, can be measured to insure that they are operating within acceptable limits. Each component has a simple function and clear inputs and outputs that can be tested empirically. The component either works or it doesn't. If shoddy craftsmanship mars the manufacturing process, the resulting component may have a higher failure rate, or noisy output, but since this can be empirically tested, these components can be found and isolated. Considering their complexity, electronic systems work quite predictably, and we rarely have to worry that a single layer of silicon in a transistor wasn't applied correctly because the geek that made it didn't love his craft fully enough. The process has been quantified so that poor craft can be spotted (a resistor that is 10% off the mark when tested), and corrected. Electronic components aren't crafted, they're manufactured.
Henry Ford scaled up the automobile industry, not by hiring the best hand craftsmen in the world, but by removing hand craft from the process. As one who loves the craft of coding, this hurts to consider, but I have to recognize the historical trends. When technology scales up it leaves hand craft behind.
Stereo systems, computers, and car engines are built of components. To build a PC you aren't likely to solder together your own power supply, or build your own Pentium processor. When fixing your car you don't build spark plugs from scratch. You use parts that are defined to fill a specific need. Yet I don't see components like this in software development. Most code is written from scratch, usually building on top of libraries (such as Java's APIs..
Though OOP promises encapsulation, it fails to provide true encapsulation. Classes, methods, and interfaces define the "front" of an object, the features that allow the outside world to use that class. But this is only half of the picture. When the class hides its implementation it also hides all the ugly habits programmers have. But hiding the problems, much like piling your junk in a closet and slamming the door, doesn't make the problems go away. A simple clean class (on the outside) may contain dozens of references to other classes on the inside, each of these refers to still other classes, and each of those references introduces complexity and potential errors.
The biggest problem here is not the references. They are necessary for any larger sytem to work. The problem is that there is no formal way in the language itself to declare and define these references. I know what features a class provides to the world by looking at it's methods, but I have no way to know that the little screen widget I just dropped onto my canvas actually instantiates ten other classes to do it's work. There's no syntax that tells me what the class does to it's world while it's running. When I use that widget I implicitly sign a contract to incorporate these other classes into my project as well (and bring all the baggage that they have). I don't know that these references are occurring and have no way to police them. In this sense we don't have encapsulation. A class does not work like a resistor, transistor, spark plug, fuel injector, I-beam, or any other functional (time-tested) component. The front of the class is a clean, formally defined interface, but the back is a mess of ugly wires spilling out of the box, hard soldered into a dozen other classes, which in turn do the same thing, hard-wiring themselves into still other components. Look under the hood of an object in nearly any class library and you'll see a pandora's box of connections that are inherently unpredicatable and largely hidden from view.
No amount of well meaning craftsmanship or rocket-science coding can fix this situation. What is needed is for code to follow the pattern established by successful component systems since the invention of the wheel. Code must be broken into small encapsulated units that perform simple tasks, very predictably, with rigrorously defined inputs and outputs that can be empirically tested. The component must be both front and back encapsulated, which means "what the class provides to the world" is defined (as with classes now) but also "what the class request of the world" is just as rigorously defined. Currently we only have the vague and general "import" statement to tell us that a class refers to other classes outside of itself. What we need is a means to define the nature of the connections to other classes, to turn these references into plugs like the plugs on the back of a stereo component, PC, IPod, etc., that can be detached if necessary to separate a class from it's environment.
As much as I love hand-crafting code, I can see that historically this sort of craft has always given way to standarization, automation, and pre-fabricated modules. This is the growth path, not towards higher and higher skill level, but towards lower skill with more rigorous encapsulation. Consider the job of the longshoreman before container ships. In the past a longshoreman loaded all the various oddly shaped cargo into the hold of a ship. A good longshoreman could visualize how the cargo would fit and predict the most efficient packing of the cargo in the hold. A mistake would lead to costly inefficient use of the cargo space or the (also costly) need to unpack and repack. Longshoreman had a unique talent and craft and were paid highly for it. That ended abruptly when container shipping arrived. Cargo was packed first into (completed encapsulated) perfectly rectangular containers. Standard sizes meant that the containers could be stacked predicatably onto ships, trains, and trucks. Efficient packing was now a smaller problem, distributed to the people packing the individual containers. The unique talents of the longshoreman are no longer necessary.
The question is not how we become better programmers, but how to make systems that don't require better programmers to work well.
March 20, 2005
Java OpenGL demos updated
Entry posted by Mark at March 20, 2005 11:30 AM
I upgraded my Java OpenGL demos to use LWJGL version .95. These applications demonstrate many valuable features of the OpenGL graphics api, using the LWJGL Java/Opengl binding.
The demos contain utility code that wraps many critical features of OpenGL and LWJGL in a simple set of function calls. This includes loading images, creating textures, setting display modes, drawing meshes, running a game loop and many more.
Other recent additions include a sound demo using OpenAL, functions for using pbuffers (offscreen rendering buffers), and support for Mac OS X.
OpenGL Java demos and source code: http://potatoland.com/code/gl
February 27, 2005
Drawing the Line Betwen Objects
Entry posted by Mark at February 27, 2005 10:12 AM
I used this example of a simple particle system in the Code Literacy course that I teach at ITP. This is a good case of encapsulation at work and raises the question of how much should be encapsulated in one class, or more accurately, how many different kinds of features should be included in one class.
The original code merged the ideas of particle motion and rendering into one object, while these are actually two very different features. As this code is developed, the particle system and rendering code will become very tightly woven together, making it difficult to use the particle system in new contexts.
To make this clearer, look at a real-world example of a component, like the iPod. An iPod does one thing well: play music. But what if I always listen to music while I wash my car, does that mean I want an iPod that dispenses soap, or doubles as a sponge? Not likely, yet this situation arises in code routinely.
The ParticleSystem class contained a Particles array. It could move and render:
ParticleSystem
--------------
Particles[]
move()
render()
I separated out the rendering functionality:
ParticleSystem ParticleRenderer
-------------- ----------------
Particles[] -----> render(Particles[])
move()
I didn't actually create a class called ParticleRenderer, my main applet class functions as the renderer, but the logical next step would be to encapsulate rendering in its own class. The ParticleSystem and ParticleRenderer communicate by passing an array of Particles between them. The value of this approach is that the ParticleSystem now clearly encapsulates one idea: particle motion. We could use that motion to drive animations, build meshes, plot points, draw into an image, or any other specialized use we can think up.
A similar case came up in class with the Jiggler class that takes a Shape as an argument. The ideas are very simple: a Jiggler jiggles a Shape. And the code clearly reflects that: Jiggler.jiggle(crosses[i]).
This isn't just about coding well, it's an exercise in thinking clearly about complex problems. Our brains have evolved over millions of years of perceiving a world of discreet objects. We take for granted that an iPod doesn't also wash the car and that a chair is separate from a table. But in the world of software these structures are not clearly defined. We have to create our own conventions to make usable systems.
December 17, 2004
Code Giants
Entry posted by Mark at December 17, 2004 03:16 PM
I've been trolling the forums at Processing.org looking at java code samples. Processing (a tool for building graphics applets) has a handy feature to publish an applet to the web, and includes the source code with the applet. By leveraging human laziness -- it's easier to publish the code than to remove it -- Processing is rapidly becoming a mecca of source code snips.
When browsing the many fine demos and virtuoso coding at Processing.org I think of the quote by Albert Einstein "If I have seen farther than others, it is because I was standing on the shoulders of giants". When I look at code -- not code theory, but the actual craft of writing applications and applets -- I don't see many programmers standing on the shoulders of giants. Each programmer starts fairly much from scratch and bangs out algorithms that have been written maybe dozens or hundreds or thousands of times by other coders.
When using Processing we are standing on the shoulders of the authors of that system (a well deserved bravo), but this is where shoulder standing stops. A team of coders writes a system and programmers use that system, benefit from it, but also work within the restrictions of it. This is fair, and valuable, but I'm talking about something else. I'm talking about programmers sharing code among their peers, building on each others code vs. using a tool that has been provided largely complete (ie. flash, shockwave, and to some extent Processing). Cases of shoulder standing among peers are rare and usually involve large projects that attract a lot of attention, ie. Linux or OpenGL.
When I program I typically start with the ideas of others, and perhaps grab some snips of code from a book, and I troll Google for code samples, but rarely do I find a sample that is designed to be reused, meaning it actually works outside of it's original context. In most cases code is hard-wired into the applet it was written in and can't be used anywhere else without substantial hacking.
I teach a beginning programming course at ITP (NYU) using Processing, and one of my students found this class by Robert Hodgin of flight404.com. It looked to be well written and modularized so I tried it out as a case study in reusability.
Called "Meander", the class does exactly that: it moves a point along a semi-random organic path, like an ant exploring a tabletop. What immediately struck me is that this class encapsulates a fairly abstract idea. The class does not encapsulate an ant, or an organism or a ball or any object. It encapsulates the idea of meandering motion. It returns only a point, a pair of x,y coords. It's up to the programmer to decide what to do with that point, and that's exactly what makes it reusable. If Robert coded the graphics right into the class then I'd have to get out the clippers and start snipping wires to remove his drawing and put in what I want to draw, thus creating another un-reusable class. By restricting the class to return just a point the Meander class becomes more usable, not less.
I wanted to use Meander in an OpenGL/Java application, so I tried a simple test. I dropped the class into a Java IDE and compiled it. The compiler found five errors that showed where the class referred to built-in values in Procesing: width and height, keydown, and the noise function. These references hard-wire the class to the Processing applet, but are easy enough to replace with params. To separate Meander from the applet context I needed to:
1) Define a rectangular area in which Meander will work. This not only removes the dependency on global Processing vars but also allows Meander to move in areas that are not equal to the full applet.
2) Define an alternative motion behavior that can be triggered from the keydown event but from outside the Meander class. This removes the dependency on the keydown event and allows Meander's behavior to be altered based on other events.
3) Provide a noise function.
To make Meander a reusable component I made these tweaks:
1) I added four params to the constructor so I can pass in the bounds of the area that Meander will be constrained to. These are floats, since I intended to use this in OpenGL 3D space where coordinates are not limited to whole pixel values. Now Meander can refer to any numeric space without expecting only applet pixel space.
2) I added setTarget(x,y) to switch Meander into a "seek" mode, and removed the keydown reference and replaced with a boolean. Now the class can be switched into different modes without refering to specific keypressed events in the applet.
3) A google search on "Perlin noise" turned up this delightfully reusable class (PerlinNoise.java by Ken Perlin) that takes the same args as the Processing noise function. This class is straight java and compiled with no problems. For my OpenGL app I was able to replace the noise() function with the PerlinNoise class by changing only one line of code.
4) For kicks I made up a wall collision response, and added some variables to clarify the magic numbers that RHwas using. Then I renamed the class to MeanderN to avoid confusion with the original.
The results:
MeanderN.java
PerlinNoise.java
1 meandering line
2 meandering lines in separate areas
To stand on giant's shoulders we need some giants around. I propose that a code giant is not a rocket scientist that produces amazing algorithms. A code giant is anybody that makes code that can
1) be used in many contexts
2) be easily re-worked, scaled up or extended
3) be easily used by an >>average<< programmer
Usually the way to do this:
1) use simpler programming techniques, not more complex.
2) Reduce the features of a component to just what the component is good at.
3) Provide a clear interface that hides complexity.
4) Remove references to outside contexts. Make it self contained.
In this case Meander and PerlinNoise demonstrate how two building blocks can be put together in a completely new context and produce results.
December 12, 2004
Audio demo using OpenAL and Java
Entry posted by Mark at December 12, 2004 10:12 PM
I uploaded an audio demo using OpenAL (Open Audio Library) and LWJGL at http://potatoland.org/code/gl. This Java demo loads four WAV files, positions the sounds and plays them in a 3D scene. The sounds will fade in and out realistically as you navigate the scene.
OpenAL is a cross-platform 3D audio API that is similar to OpenGL in appearance. I found it relatively painless to wrap some lower level functions into a simple SoundScape class that manages sounds in a 3D space. LWJGL provides the OpenAL and OpenGL bindings.
Organic Algorithms
Entry posted by Mark at December 12, 2004 08:57 PM
Jared Tarbell's digital art combines the mindless repetition of computer programs with the creative expressiveness of natural growth. From this seemingly contradictory match he generates a bewildering array of delightfully intimate forms. In a grid of 88 "sand dollars", each algorithmically generated design is approximately the same size and shape as the others, yet each is distinct and uniquely engaging. The surface monotony of the grid gives way to organic delicacy.
Complexification | Gallery of Computation by Jared Tarbell
December 05, 2004
Particle System
Entry posted by Mark at December 5, 2004 05:04 PM
Fascinating smoke effects, particle systems written in Processing (processing.org).
By Tom Cardin
More here:
TomC's Processing Sketchbook
November 27, 2004
Blur Algorithms in Java
Entry posted by Mark at November 27, 2004 08:52 PM
Quasimondo : Incubator by Mario Klingemann
This site has many good algorithms written for Processing (processing.org), but easily adaptable for straight java. Code is clean and modular, I've already seen several cases of his blur functions being reused in other applets.
November 19, 2004
Java Graphics and Processing
Entry posted by Mark at November 19, 2004 10:55 PM
If you've never heard of Processing think "Java Lite". Processing (processing.org) is a quick and easy way to create small Java programs, without having to figure out the intricacies of a development environment like JBuilder or Eclipse. Processing provides many built in functions that make graphics coding easier, such as pixel level image operations, animation looping, and a scaled down set of opengl styled 3D render commands. But the biggest value of it has little to do with Java. The killer features for me are:
1: Processing allows me to start a new code "sketch" just by clicking File | New. To save a copy of a program just click File | SaveAs and enter a new name. In a few seconds I have a new version of the code that I can modify without altering my original, and without having to spend the five minutes that it takes to set up a new project in a development environment.
2: The Export to Web feature creates a folder with applet, jar files, and an index.html set up and ready to ftp to a server. The html page even includes a link to the source code for the applet. The brilliance of this is that it makes it easier to publish the source code than to exclude it, encouraging an open source approach and helping to build up the knowledge base of both Java and Processing.
Once I started using Processing I realized how much I like the feeling of sketching: spontaneously banging out quick ideas. Try something, tweak it, try something else, move on rapidly. Software development environments are made for business and typically assume you'll have a lot of code to organize. Java scales up well for use by the business enterprise, but it needs to scale down for easy access to individuals. Processing does just that by packaging Java into a small-scale and manageable form tailored for graphics programming.
Some applets created in Processing
October 08, 2004
Update on Java/OpenGL Demos
Entry posted by Mark at October 8, 2004 01:29 PM
Over the past two years I've been exploring graphics in Java and looking for a simple flexible platform to create high-performance graphics.
Recently I'm leaning towards a game approach to coding, a simple take-over-the-computer approach: fullscreen rendering, grab every cpu cycle available, no threads, just one loop that manages events and rendering, and use OpenGL to talk to the video hardware.
I've been working with LWJGL (http://lwjgl.org), a low-level OpenGL binding for Java that is geared toward game developers. The transition from pure Java to java/openGL was surprisingly straightforward and the performance was a big plus. Some unexpected benefits: coding time drops because OpenGL actually works as documented, there are no gui/threading issues to work out, I completely dropped out awt/swing so quirky gui-related bugs go away, code size shrinks since OpenGL handles many aspects of rendering that I was doing in Java. Drawbacks: can't show the work online without plug-ins, but after 8 years caught in the crossfire of browser wars, I'm okay with requiring that folks download the piece and run locally.
I developed a few OpenGL demos and created a utility class that makes my life much easier and may be of some use to others. Demos with code are here:
and screenshots of some of the graphic qualities I'm going for are here:
http://potatoland.com/whotel
http://potatoland.com/kk2
http://potatoland.com/kk2/kk3_1
I'm excited by the results I'm getting from OpenGL and Java, so I'm passing this on with the hope that other digital artists may benefit from it.
September 15, 2004
Java OpenGL Demos
Entry posted by Mark at September 15, 2004 10:27 PM
Demo code is online at http://potatoland.org/code/gl. These demos show the basics of LWJGL, a Java/OpenGL binding that can be used to create hardware accelerated 3D graphics in Java.
This first batch of code demonstrates rendering with textures, setting up a simple scene, making a native cursor, rendering text, rendering in 2D and 3D, scene navigation, amongst other things.