I’ve been a Cinder devotee for about two years (almost as long as Cinder has been publicly available). I officially switched from openFrameworks because a project I was working on as a student at ITP made heavy use of GLSL shaders, which at the time were much easier to work with in Cinder. openFrameworks GLSL support has since improved greatly, but I’ve maintained my loyalty to Cinder because of its clean architecture, extensive core feature set and impressive sample projects.
Every few weeks, though, I find myself porting an openFrameworks addon to Cinder. And now that there’s ofxAddons, a site that tracks every addon on GitHub, my porting has become even more frequent. Some of these are easy enough. Vec3f becomes ofVec3f, ColorA becomes ofColor, etc. But more complex addons like ofxOpenNi or ofxAssimpModelLoader are time-consuming or difficult to port. Of course, the Cinder community has its own “addons” (which are instead called “Blocks”). But there are fewer of them, they often take longer to reach the community and in some cases they are harder to wrangle. Cinder’s OpenNi block in particular is a nightmare to get setup.
I believe the greatest strength of each framework is also its greatest weakness. openFrameworks is extensively documented and supported by a large and active community. This means a constant stream of new features, but also that the tools themselves sometimes feel like a disorganized hodgepodge. Cinder is supported by a smaller community, which is rigorous about API standards and best practices. However, this often translates to month-long forum debates that do not result in any new features. So we beat on.
I’ve learned a great deal about programming by reading the Cinder source code and that nagging feeling of wanting to do things properly and efficiently keeps me a Cinder devotee. But this week, something happened that changed my attitude: I met Polycode.
I’d been aware of Polycode since it first surfaced, but only gave it proper attention for the first time this week. I was looking for inspiration while implementing the 3D environment and scenegraph components of my software project, Foil. I was impressed with Polycode’s Assimp-based 3D model loader, scenegraph structure, Bullet-based physics simulation and overall architecture. For a moment, I considered making the switch. But then, I began to find that Polycode was extremely slow in loading large skeletal animation files and started looking elsewhere for solutions.
This brought me back to openFrameworks, which unsurprisingly has a very nice Assimp loader addon. My first impulse was to port ofxAssimpModelLoader to Cinder. After a bit of frustration and wasted time, I decided to put Cinder aside temporarily and try working in openFrameworks instead.
Within a day, I had connected ofxAssimpModelLoader, ofxBullet and ofxTimeline with openFramework’s built-in ofLight, ofCamera, etc classes to reproduce the majority of Polycode’s 3D model/skeleton, physics and animation functionality. Over the course of the next few days, I will integrate addons including ofxTerminal, ofxAssimpOpenNISkeletonSync, ofxOpenSteer/ofxPathfinding/ofxFlock, ofxParticleSystem, ofxFaceTracker and ofxOpenNi to produce a scriptable 3D modeling/animation/gaming environment, potentially called “ofxGoneWild” or maybe “ofxKitchenSink.” ofxAddons galore! There is some work in connecting these pieces and without a fair amount of C++ as well as Xcode experience, it would be difficult. Yet, given the volume of features that comes with these addons, it’s a pretty quick process.
I still love Cinder and will continue to work in it. But the draw of openFrameworks’ vast collection of addons is immense. The ability to build a custom physics-simulating, keyframe-animated 3D environment in a week is earth-shattering. It’s not Maya, but it’s an extremely good start. With the support of Assimp and Bullet, openFrameworks provides access to the same model loader and physics engine that are available in Maya 2013. So, for this project at least, I’m with openFrameworks.
(A very early screenshot of ofxGoneWild.)
A preliminary test using FaceTracker to control a virtual camera within a 3D gaming or design environment. With some tuning, the effect could be made pretty convincing. The biggest obstacle is that FaceTracker looses non-front-facing faces. Perhaps the face detection training model could be extended. Failing this, it might be helpful to supplement the FaceTracker data with Kinect skeletal tracking to smooth or approximate the head position when necessary.
For this version, I ported ofxFaceTracker to Cinder and wrote a simple camera control system to interface with FaceTracker data. By shifting control of the camera position towards a motion vector rather than pure position-driven approach, it should be possible to diminish the apparentness of brief drops in face tracking. Some turbulence forces might also mask a freeze in face-controlled camera data.
Using Jason Saragih’s FaceTracker library:
Adapted for Cinder from Kyle McDonald’s ofxFaceTracker:
My Cinder port of ofxFaceTracker is now available at:
I think 3-Strip Technicolor films deserve as much of nostalgia’s warm embrace as vinyl records. Webcams and mp3s are completely ubiquitous, but their predecessors (and distant ancestors) still hold a certain charm. So, for Eric Rosenthal’s Digital Imaging class I created a few digital images using a process similar in spirit to that of old Technicolor films.
This project was developed for and presented at the ITP Big Screens 2010 event @ the IAC Video Wall in Chelsea, NY.
The aspect ratio of the IAC wall is 10.625:1, which is not very conducive to the web. This video represents the middle third of that screen.
Evaluating the state of each of the eight neighbors of the center pixel in a nine-square grid for every one of the 8,160 x 768 pixels on the wall of the IAC, algorithms are employed to generate such natural behavior as the flooding of lowland areas by rising water levels, and the reformation of new land masses by sedimentary deposition. The same pattern of behavior exists at multiple scales, and can be seen in chemical reactions, culture growth, spillage, and lava flows, to name a few. The algorithms themselves can be modified to simulate any variation. To operate in real-time, our algorithm must compute a baseline of 150,994,944 pixel comparisons every frame. To achieve this, we have designed our algorithm to take advantage of the computer’s standard processor (CPU) as well as its hardware-accelerated graphics processor (GPU).
MeandriCA was created using C++, OpenGL, GLSL and Cinder.
I am exploring natural simulations, terrain generators, evolutionary and genetic algorithms as starting points for interactive or gaming experiences. Here are a few images that have come out of my early programming work on the project:
In all stages of this project’s development, I believe it will be important to consistently reconcile the visual and conceptual elements to one another. I am hoping to strike a delicate balance between a light-hearted, playful tone found in Disney or Pixar animated films and the understated presentation of natural wonder that can be found in few good nature documentaries. At the same time, I am building the system as an interactive one. For this purpose, I am looking to the books Theory of Games and Economic Behavior by John von Neumann and Oskar Morgenstern and Evolution and the Theory of Games by John Maynard Smith. Through these books, I am exploring how concepts of evolutionarily stable systems could be applied to the gameplay mechanics of my project. A few more visual and conceptual influences are depicted here:
Click to enlarge. Conway’s Game of Life being computed on the graphics card for 8160×768 pixels at 60 frames per second. The full frame is rendering to a frame buffer, only the left 1360×768 is drawing to the screen.
Here is a slideshow of some of my childhood work. Though I primarily focus on software development in my “adulthood,” my interests have remained much the same. The above image is of a design model for a virtual reality headset I constructed when I was nine or ten.
This collection covers a sample of works from ages 5 to 13.
GoSort! is a human sorting algorithm game with mechanics similar to Go Fish. It can be played by two to four players. The object of the game is to hold the complete, sorted deck in your hand. I developed this for my Games & Art class. It is still in its infancy.
Here are the rules:
- Each player receives seven cards, the rest remain in the deck.
- Turns go clockwise around the circle.
- The game ends when one player holds a complete sorted deck. If something prevents this from happening, the game should be replayed from the beginning.
- During a player’s turn, he/she may ask one other player if that player holds a particular card (the 5 of Hearts, for instance). If the other player holds the desired card, they must hand it over along with any other cards that are “sequential” with the one that was requested. (See more on “sequential” cards below). If the other player does not hold the requested card, the player takes one card from the deck. In either case, the player does not go again until every other player has had a turn.
- SEQUENTIAL CARDS: Players should order the cards in their hand in the following manner: Hearts then Diamonds then Clubs then Spades and from Two to Ace within each suit. Sequential cards are ones that touch one another within this ordering. So if a player is asked for a 4-D (4 of Diamonds) and their hand contains: J-H, K-H, A-H, 2-D, 3-D, 4-D, 6-D, they would have to hand over everything except for J-H and 6-D.
That’s how GoSort! is played. This sorting algorithm isn’t nearly as efficient as a computational sorting algorithm such as MergeSort or QuickSort, but hopefully it is more fun.
Week 1: “Genetic Optimization Visualization”
For our first session of Games & Art, we looked at Rock Paper Scissors (RPS) as well as at strategies for winning this time-honored game.
In the standard game, one point is awarded for rock beating scissors, paper beating rock or scissors beating paper. With this point assignment, there is no numerical strategy that will create a distinct advantage. Basically, the best way to win is to try to psyche the other player out or, to go a bit further, to make your rock, paper or scissors choices be as random as possible. In other words, R, P and S should each have a 33.3% chance of being chosen in each round. This makes sense given that RPS is generally thought of being more along the lines of a coin toss than a game.
If we change the point distributions awarded to a winning R, P or S, however, the possibility of numerical strategies for winning begins to emerge.