16 December 2007

March of Man: Image Feed

There is now an RSS feed that will show all the latest updates to the March of Man gallery. Point your blog-reading software to:

http://marchofman.org:8080/marchofman/imagefeed/


This was surprisingly easy to develop, thanks to the ROME library for Java. (I had a few problems deploying it, but that was my fault.)

12 December 2007

Exobotics!

We at Exopolis just launched this today:



This is a hybrid Flash/Flex app that allows you to select robot parts (including a heart, which represents a musical track) and assemble them into a dancing robot which you control with the mouse and keystrokes. I have to say—I spent hours making this and it's still fun to me.

I'd actually started something similar back in Flash 4, if you can believe that. Yes, before true ActionScript. I had to manually create a sine lookup table. It was fun.

After a couple of false starts in intervening versions of Flash, I finally had my greatest success with a Flex version. Dynamic binding makes this sort of thing so much easier.

Basically, the way the robots work is that each joint is associated with a type of object called a Locator. Minimally, a Locator stores a point, dispatches updates whenever that point moves, and allows that point to be constrained. A Locator can be created as simply as:

<Locator id="myLocator" x="100" y="100"/>

Of course, that's not a very interesting Locator, since it doesn't move. Moving a Locator can be done in one of two ways. One way is to extend the basic Locator class, creating a specialized type of Locator. As an example, one of these is StageMouseLocator:

<StageMouseLocator id="mouseLocator"/>

The x and y properties of this Locator always correspond to the position of the mouse. If I wanted to bind another Locator to this, I could do it like so:

<StageMouseLocator id="mouseLocator"/>
<Locator id="myLocator" x="{mouseLocator.x}" y="{mouseLocator.y}"/>

Voila, now myLocator follows the mouse. Why would I want to do this when mouseLocator already does that? Good question. I wouldn't. But now I can do stuff like this:

<StageMouseLocator id="mouseLocator"/>
<Locator id="myLocator" x="{mouseLocator.x + 100}" y="{mouseLocator.y}">
    <constraint>
        <constrain:VerticalConstraint minY="100" maxY="500"/>
    </constraint>
</Locator>

Now it will always be 100 pixels to the right of the mouse, but it will constrain the vertical position to between 100 and 500 pixels in the display's coordinate system. You can see how this sort of binding with modification can lead to more complex behavior.

Another way to control a Locator object is by using an (aptly-named) Controller object. One such object is a SineController object:

<control:SineController id="beatController" speed="0.25" context="{this}"/>

This keeps an angle value, updates it on every frame (incrementing by 0.25 radians) and makes the sine value available through a property called sine. So if I wanted a controller that followed the mouse but oscillated up and down, I could do this:

<StageMouseLocator id="mouseLocator"/>
<control:SineController id="beatController" speed="0.25" context="{this}"/>
<Locator id="myLocator" x="{mouseLocator.x}" y="{mouseLocator.y + beatController.sine * 50}"/>

Of course, I have other types of Controller (StepController, which extends SineController; RandomController; ClickController; etc.), other types of Locator (JumpLocator, JointLocator, InterpolatedLocator, ModeLocator, etc.), and other types of constraints (DistanceContraint, RectangularConstraint, etc.). All of these I blend to create a basic skeleton of points.

Once I have the skeleton, I can attach various visible objects call Connector objects, each of which connect to a number of points and have rules for "squash & stretch". The robots all use MovieClipConnector objects, which each link a Flash movie clip to one or two connectors. I also have DrawnConnector, ImageConnector, etc., and hopefully I can use those on future projects.

I had actually started to make this as an application where you would sketch your own character and it would animate according to a skeleton, but this turned out to be much too processor-intensive, at least for now. Fortunately, one of our senior designers, Chuck Chugumlung, had this idea for a dancing robot factory and he and some other designers (Dan Duran, Jancy Liu), went to town.

Anyway, enough geekery. Go make some robots dance!

11 December 2007

Holiday Fun: Affirmative

Coming soon (probably tomorrow) ... possibly the most fun thing I have ever had a part in making.

Clang clang,

—Keesey

09 December 2007

Human Origins: Wrong Answers to the Question

Anyone who's spent enough time discussing human origins is bound to have heard this old chestnut at some point:

If we're descended from apes, how come apes are still around?

A variant uses "monkeys" instead of apes.

In an attempt to defend the scientific explanation, people will often use one of two stock answers:
  1. If you're descended from your parents, how come they're still around?
  2. We're not descended from apes, but we share a common ancestor with them.
Number 1 has a valid point, but it's a bad analogy. Stem-humans originated around 5–7 million years ago, but there aren't any apes sitting around today that are that old. Our parents are still alive (or were not long ago), but our ape ancestors are long dead.

Number 2 is flat-out wrong. We are descended from apes. You could modify that sentence a bit, though, and get a true statement: "We're not descended from any living apes, but we share a common ancestors with them."

So what's the real answer?

The real answer is that "ape", as commonly used, is an unnatural term, and it obscures communication about the subject. Generally "ape" is used to refer to all hominoids except for humans. What's a hominoid? Let's spell that out in some detail:

Hominoidea
|--Hominidae
| |--Pongo
| | |--P. abelii (Sumatran orangutans)
| | `--P. pygmaeus (Bornean orangutans)
| `--Homininae (African hominids)
| |--Gorilla
| | |--G. beringei (eastern gorillas)
| | `--G. gorilla (western gorillas)
| `--Hominini
| |--Homo sapiens (humans)
| `--Pan
| |--P. paniscus (bonobos)
| `--P. troglodytes (common chimpanzees)
`--Hylobatidae (gibbons)
|--Symphalangus syndactylus (siamangs)
|--Hoolock
| |--H. hoolock (western hoolocks)
| `--H. leuconedys (eastern hoolocks)
|--Nomascus
| |--N. concolor (western black crested gibbons)
| |--N. gabriellae (yellow-cheeked gibbons)
| |--N. leucogenys (white-cheeked crested gibbons)
| `--N. nasutus (western black crested gibbons)
`--Hylobates
|--H. agilis (agile gibbons)
|--H. klossii (Kloss's gibbons)
|--H. lar (lar gibbons)
|--H. moloch (silvery gibbons)
|--H. muelleri (Müller's gibbons)
`--H. pileatus (pileated gibbons)
Cladogram of extant hominoids, to species level.

(Yes the scientific name of western gorillas really is Gorilla gorilla. And the western subspecies thereof is Gorilla gorilla gorilla!)

As you can see, hominoids form a big, bushy branch of the primate tree, and most of the extant twigs (i.e., species) are among the gibbons (although most living individual hominoids are human—nearly all of the other species shown here are threatened or endangered).

Among living hominoids, we humans are most closely related to chimpanzees (including bonobos). The second runner-up is gorillas, then orangutans, and then finally that big bushy mass of gibbons. These relationships reflect events in our ancestry: the human-chimp split (about 5–7 million years ago), the split from gorillas (about 8–10 million years ago), the split of African hominids and orangutans (about 12–15 million years ago), and the split of great apes and gibbons (about 16–21 million years ago). Each split stems from a population, a group of common ancestors which we share with some other living hominoid group. Those ancestors were hominoids and were not humans; therefore, they were apes.

But, looking at this tree, you can see how unnatural the designation "ape" is. What sense does it make to lump our closest living relatives (chimpanzees) in a group with much more distant relatives (e.g., gibbons)? It would make as much sense as if we invented a group that included all hominoids except for siamang giboons, or all hominoids except for gorillas, or all hominoids except for any randomly-selected group in that cladogram.

(This also points out some problems with the Planet of the Apes movies—chimpanzees would probably just see humans, gorillas, and orangutans as belonging to some group of non-chimp hominoids. And gorillas and orangutans would respectively exclude themselves from such a group, but include chimps. Come to think of it, only the orangutans would be thinking of a natural group.)

Really, the only way to make the term "ape" natural would be to include ourselves. Then we would not only be descended from apes—we would be apes.

The term "monkey" has a similar problem, since some monkeys are more closely related to us than they are to some other monkeys.

Haplorhini
|--Tarsius (tarsiers)
`--Simii (a.k.a. Anthropoidea)
|--Catarrhini
| |--Hominoidea (apes, including humans)
| `--Cercopithecidae (Old World monkeys)
| |--Cercopithecinae (macaques, baboons, etc.)
| `--Colobinae (colobus monkeys, langurs, etc.)
`--Platyrrhini (New World monkeys)
|--Aotidae (owl monkeys)
|--Atelidae (howler moneys, spider monkeys, etc.)
|--Cebidae (marmosets, capuchins, etc.)
`--Pithecidae (titis, uakaris, etc.)
Cladogram of dry-nosed primates (haplorrhines), to an arbitrary level of resolution.

A "monkey" is basically any simian that is not an ape (or human). To make it a natural term, we would have to include apes (including humans).

Should we use those terms differently, and consider ourselves apes and monkeys? It would be more honest, phylogenetically speaking. In the end, though, those are vernacular terms and people are free to use them however they want.