Home       About Me       Contact       Downloads       Part 47    Part 49   

Part 48: Programmer Art

February 6, 2012

The kind of art I can do
Call in a professional
To do a game, I have to do some artwork. As I've mentioned repeatedly, I'm not much of an artist. Combined with my tendency to obsess over details, this has a bad effect on my progress. I do some lousy piece of artwork, then spend hours deciding that I can make it just a little bit better...

The last time I got stuck doing this was Part 34, when I added non-cube objects to my world. Those were mostly simple shapes and turned out well enough. I'm sure an artist could make the chest or bed or railroad tracks more interesting looking, but I don't think it matters much. When it came to flowers and grass though, I had to get ahold of an artist friend.

Unfortunately, artist friends don't always feel like doing hours of work for free, and so I have to fend for myself. In addition to lack of talent, I have a few other problems.

File Formats

If I'm going to load art into the game, I need a file format for my graphics. Frustratingly, there doesn't seem to be an obvious choice. Florian Bösch has a blog post on the subject and recommends 3DS files. Originally this format was written by Autodesk 3D Studio and is now widely supported. My only objection is that the format is not completely documented. I know it has been in use despite that for decades, so the unofficial spec is more or less the official spec now. I just find working with an undocumented format annoying.

Back in Part 34, I did my work with Google SketchUp, which outputs only its own format and Collada. I wrote a tool to strip what I needed out of Collada files, but it is in no way a complete parser for the format. As Florian mentions,

Since Collada is completely generic, any usage you make of it is riddled with hacks to make it work for your non generic use-case. Anytime you present your interpretation of Collada with a file from a different author or saved in a different 3D modeling program, it breaks, usually in a way requiring you to spend hours or days figuring out how to add a new hack to make it work.

There is a reference implementation in Java of the Collada file format. However that implementation frequently fails to import or export files.

My artist friend recommends Wavefont OBJ files, another format that's been around for years. The documentation seems more complete on this, although supporting curved surfaces looks like a pain in the neck. It doesn't include any support for animation though.

What format I take really depends on which tools I'm going to use to create 3d objects. That's another issue.

Tools

So far, I've downloaded and at least tried once Google SketchUp, MeshLab, Blender, 3DCrafter, Wings 3D and the beta of Autodesk 123D. Of these, I've only done anything interesting with SketchUp. It had a decent tutorial, and the interface is simple if you don't try to do anything complicated. I'll probably play with Autodesk 123D some more, since it looks like you can do 3D printing with it. I haven't done anything useful with the rest. Any opinions from readers?

My big problem is that I just don't think in three dimensions very easily. I have to draw little pictures of what I'm trying to do and proceed very carefully, or else I get lost and just make a mess. I find the whole process extremely frustrating.

I was thinking at one point that what I really want is an editor which presents a big lump of pixels, and lets you carve or add to it. Then you could paint on the surface of the model to create the texture. Hit a function key and it would generate polygons and textures at any requested resolution. Perhaps there's a tool out there that does that, or a function of one of these editors. So far, I haven't run into it.

An editor like that would be a lot like digital sculpture, and I briefly considered doing things with real sculpture. I'm not a painter or sculptor either, but I could probably put together a clay model of what I wanted more easily than doing it with a modelling program. Then I could scan it in to create a model.

There are some DIY scanners you can build out there, but they tend to be a few hundred dollars at least, and I didn't want to spend weeks messing with something like that at this point.

There are also programs that take multiple photographs of buildings and produce a 3D model. Unfortunately, they seem to require edges in the image to calibrate multiple views. I'm not sure whether photographs of a blob of clay would really be enough for these programs to create a model.

I could of course pick up objects off the various free libraries on the net. The problem is that I always want some kind of change, either to the textures, the style or the polygon counts of the model. And then I get lost again in some complicated tool.

If I felt like spending some money, I could commision artwork, pay my artist friend, or put my crude attempts out on a design site and let people bid on improving them. At some point later in the project, I might do that, but before I spend a lot, I'd like to have a more solid demo of the entire system.

This all reminds me of what I liked about Minecraft in the first place. You can build interesting things without messing with 3D models!

The Hacker Way of Knowledge

Once I got frustrated enough with this situation, I did what I normally do -- write some code. I started with a model I fiddled with back in Part 22. I was trying to make a giant seed pod that would contain cities. For my mini-game, I just want a bunch of them floating around in the background.

There are only two interesting things about this model. First, I wanted the spines to curve in an "natural" way. I could have just used random numbers and made each spine independent, but you get a messy looking shape that way. I wanted the spines to curve gently and be similar, but not identical.

To do this, I used Simplex noise again. Because of the way it is generated, it's more or less continuous -- no abrupt changes. That means that two nearby points or lines or shapes cut through the noise will resemble one another. I generated the curve of the spines by displacing the center of the spine by values taken from noise at the x,y,z values of each point along the spine. This gets me what I want -- nearby points are similar, so there are no abrupt bends in the spine, and nearby spines are similar.

The other interesting thing about this model is the seamless texture. The second image shows it unlit, which makes the pattern easier to see. I do this by cutting the shape out of three dimensional noise. Since the noise is continuous, the texture pattern will be as well.

To do this in general, you would create a list of triangles with x,y,z position and u,v texture coordinates at each vertex. For each pixel of texture, you have a final u,v coordinate. You'd find the triangle that contains this coordinate, and interpolate to get the x,y,z under at this point. Sample the noise and produce your texture pixel from that value.

This looks nice, but due to the large surface area of the spines, it chews up a lot of texture (25 spines plus the 6 faces of the sphere, at 64 by 64 by 4 bytes per texture is 500K of texture memory.) In the final version (not shown here), I decided it didn't really make a difference unless you looked closely, and used the same texture for all the spines. For a larger object that the player interacts with, this technique might be more useful.

I'm not sure how artists handle this problem, or whether I can create a small repeating, seamless texture and then tile it over complex surfaces by setting the correct u,v coordinates. This is the kind of problem that makes the "spatial visualization" part of my brain just roll over and die.

Texture Animation

The next shape I wanted was a flying saucer. I constructed a half-outline using splines and line segments (in code, not a graphics editor), then rotated this to get the shape I wanted. The texture is created just as with the seed pod. I cut the shape out of noise, giving me a single continuous texture over the entire saucer. I added bands of color corresponding to the parts of the saucer shell.

I wanted the texture to be animated, so it looked like static or lightning running over the surface. The program can choose a different texture on every animation cycle, so this is no problem. However, I still have to generate the textures. I could produce a different noise pattern by adding a value to the surface coordinates. Running through a few of those in a cycle would be very random though. I wanted a cycle of gradually changing textures.

To get this, I moved the points of the surface (which I use to sample the noise) along a circle. Since the circle returns to the original value, the texture will return to the original pattern. Since nearby points in the noise are similar, the patterns along the circle are similar.

If I do this in x,y,z though, it just looks like a fixed pattern shifting around on the surface of the saucer. To avoid that, I actually use a four dimensional noise function, and the circle points are in x and t.

I generated ten textures, and to smooth the transitions, coded a special shader to display them. The shader takes two textures and a blend value. Over the cycle of two seconds, there will be 120 frames, and ten texture changes. Between each texture change, the code is blending the two adjacdent textures.

Progress

The moral of the story here is that if you have no art skills, I guess you make do with the skills you have. I just build my models in code rather than rely on my limited 3D visualization abilities. This way, I can tweak the design over and over until it looks sort of OK, instead of trying (and failing) repeatedly to build it in a 3D modeling program.

I continue to work on the game logic, some real character animation and even on internationalization. It's not like I've spent the entire week fussing with these models....

Home       About Me       Contact       Downloads       Part 47    Part 49   

blog comments powered by Disqus