Skip to content

Archive

Tag: Blender

Blender 2.49 has a ‘radioactive’ button opening up a hard to figure bunch of buttons related to radiosity. However these buttons can be pretty useful if you’re looking to add realistic illumination to a scene and like to work with vertex paint. This option isn’t available in later versions of Blender, so it’s a bit of a vintage approach – however you can import the output in a later version of blender.

Radiosity – unlike classic computer light that cannot ‘turn around walls’ radiosity methods let light bounce over and over; it generates soft shadows and is good at indirect illumination.

Baking – The 2.49 radiosity method works with faces, not pixels; it outputs the result as a vertex painted mesh. This is original and defines the unique strengths and weaknesses of the illumination model. The input is the currently selected meshes; the output is a mesh. As part of baking the mesh may be subdivided according to your parameters (see below)

Workflow:

  1. Add meshes to represent light sources. Yes, with radiosity only meshes can emit and receive light. Standard light sources do not illuminate your scene/selection.
  2. Adjust ambient and emit material properties. Every mesh that has emit>0 becomes a light emitter; every  mesh that has ambient>0 can be a secondary source.
  3. Select a few meshes, including some meshes you want to render light on, and some meshes to be used as light sources (a typical case consists in selecting all meshes in your scene).
  4. Press ‘Collect meshes‘ to enter ‘radiosity baking mode’
  5. Press Go, then wait for the process to complete or press ESC if the result already looks good (rendering/baking is interactive). You can also limit the number of iterations automatically by selecting Max Iterations > 0. (At each iteration, the biggest ‘light patch’ transmits energy to the scene, so don’t be afraid of a large number of iterations).
  6. Press either Replace Meshes or Add new meshes. The first will delete the original meshes and replace with just one mesh containing the resulting vertex paint; the second will keep the original mesh data in case you still need it.
  7. Press ‘Free Radio Data‘ to exit baking.
  8. Press SHIFT + Z to activate lighting preview (or render the scene). By default the new mesh uses vertex paint as vcol_light, meaning the result can be rendered without a light source present.

Problems and solutions

  • Shadows are not detailed enough
    • reduce ‘ElMin’ – an element is a face that receives light, smaller means smaller faces
    • try reducing PaMin – a patch is a face that emits/bounces light, smaller means more precise sourcing of the light.
    • increase MaxEl – the number of elements is limited by MaxEl regardless of ElMin/ElMax
  • Too slow - increase ElMax and PaMax, decrease MaxEl, decrease Hemires.
  • Too dark/bright, too much/too little contrast - change Mult and Gamma; this is interactive, after you pressed Go and completed the bake. The advantage is that at this stage the color model still contains a lot more information than just RGB values, so there is no quality loss.
  • Don’t want the algorithm to modify your mesh geometry? Change MaxEl: to 1. If you do so you and still want a good result, prepare subdivided geometry yourself.
    • It can be useful to do a pre-render with MaxEl set high, then you subdivide your meshes knowing ‘light transition areas’ in advance. If your scene isn’t too complex or keeping the face count low is important, this may be a good compromise.
  • I see a kind of rash/noise.
    • Select ‘Gour’(aud) shading to find out. Wire/Solid/Gour are just visualization modes for radiosity baking.
    • Increase ElMin. But this will reduce precision
    • Decrease MaxEl (again, reduces precision)
    • Decrease PaMax and PaMin (increases rendering time and precision)
    • Increase Hemires to something high (e.g. maximum) This reduces artefacts without reducing precision. (When each patch of light is rendered an image of the scene is rendered to decide how the patch illuminates your scene, HemiRes is the resolution of that image). Of course higher Hemires renders a little slower.
    • Use FaceFilter and ElementFilter after rendering. This tends to blur shadows and you can apply it over and over (FaceFilter causes more blurring. Hitting ElementFilter once feels like a good thing to do).
    • Clear artifacts selectively later, using vertex paint (blur mode)

When/Why use it?

There are several alternatives (e.g. Yafaray and Blender Cycles) so maybe this is a bit out of date, however there are cases where this might be just what you need:

  • On current hardware it runs fast, and benefits post-render intensity and gamma tuning
  • I haven’t seen any other method that lets you look at and rotate around a nearly WYSIWYG presentation of your scene’s illumination in real time.
  • The resulting, pre-rendered meshes will render super fast, which may help completing a complex animation (minimally, you might want to add mirror reflections and specular components).
  • The result can be edited using vertex paint (and vertex paint can be converted to texture paint afaik).

So even though it’s a bit quirky it generates data that’s forward compatible and is really good at what it does, being at once interactive, fast and flexible.

Find detailed docs here (official B2.49 manual), including an introduction to radiosity and a detailed explanation of every available knob and button.

Today’s link: 25 useful Blender tricks (from blenderguru.com)

This post won’t give you all the information you need if you’re simply new to Blender Scripting. Many of us, however, continued scripting Blender 2.49 because 2.5 scripting wasn’t stable at the beginning. I’m quite sure this post can help you to migrate your scripts from 2.49 although it’s very hands on and I haven’t really tried to organize these useful bits.

  • Export script template (source code). This shows how to arrange metadata, invoke the file selector and write simple output to a file (to make sure something’s actually happening). Includes summary instructions to install the script.

I updated my exporter, Ox3ich, although not with all the features of the current 2.49 version. After trying it out a little I will make it available. In the meantime I list just a few of the many differences between the 2.49 / 2.59 APIs.

Writing I/O scripts for Blender 2.5 isn’t exactly what I’d like to do at the moment. I just have to. Scripting integration looks interesting, with a little more flexibility than in 2.4. Useful links…

As usual, looking at existing scripts will help. The documentation isn’t awesome.

Script Registration

  • The registration process has changed. The easy part is updating your metadata (just look at any of the scripts bundled with 2.5).
  • Scripts now require register/unregister methods. This allows tighter integration as far as I can see, notably it makes it easy/possible for a script to call another script.

Your script/add-on won’t automatically show in the designated menu, but it should appear under [file > user preferences > add-ons] where you can enable it. Then save user prefs (save as default option in the bottom left) to keep the script enabled next time. This page gives a little information about registering add-ons.

2.49 => 2.59 scripting : Miscellaneous changes

  • access current scene - bpy.context.scene
  • get object data (e.g mesh) – object.data
  • Blender.sys.join => os.path.join
  • Writing strings to output stream, see stack overflow answer (python 3.0)
  • mesh.verts => mesh.vertices
  • faces.verts => face.vertices - additionally, face.vertices is now an array of ints representing vertex indexing.
  • face.mat => face.material_index
  • mesh.getFromObject => object.to_mesh(bpy.context.scene,True,”PREVIEW”)
  • vertex.no => vertex.normal (but still uses vertex.co for ‘coord/coordinate’)
  • to change the current frame, use scene.frame_set(). Do not directly assign the frame number. Note that frame numbers start at 0, not 1.

There are changes from Python 2.x to Python 3.x in the way global variables are handled; this combines with a change in the way scripts are invoked, adding up to annoyances when trying a quick and dirty way to output debug info to a file…

Vertex colors

Vertex color data is now separate from face data, stored in Mesh.vertex_colors; additionally this now supports multiple layers, and colors are now in rgb float format (think it used to be rgba, byte format)

  • Iterate layers with something like for layer in mesh.vertex_colors
  • layer.active to find if a layer is active.
  • get layer data: layer.data
  • get vertex color for a face: layer.data[i], will contain corner colors for face at index i.
  • example 1: mesh.vertex_colors[0].data[1].color4[0]
    Red component for corner 4 in face 1, vcol layer 0 of mesh
  • example 2: mesh.vertex_colors[0].data[0].color1.r
  • Red component for corner 1, face 0, vcol layer 0 of mesh

Random links

Exporting cloth animations required only a few changes to the ox3ich exporter.

=> Ox3ich exports blender meshes and animations (source, LGPL).

Since both qwagga (scene export) and ox3ich (mesh/animations export) are now available for download, I guess I’ll want to consolidate this soon with an online project manager. In the meantime… you can have a look at the notes below, outlining how ox3ich handles cloth animations.

Finding Cloth objects

myObject=bpy.data.objects["Dress"] // get the object to be exported

myObject.type == Modifier.Types.CLOTH // confirm this object has ‘cloth’ enabled

We could have an isCloth method, looking like this:

def isCloth(object):

for x in object.modifiers:

if x.type==Modifier.Types.ARMATURE:

return 1

return 0

Using Cloth Objects as equipment

A simple way to generate animations for equipment (see this article) consists in reusing the parent object’s Armature (with extra bones for equipment) and export the actual keyframes (the shape of the mesh as deformed by the armature). Mesh data is memory intensive. One advantage, however, is we don’t need to rewrite / adapt modifiers code.

Now, for equipment, we grab all actions and apply them to the actor’s armature. We’ll do the same for cloth objects. However, there is a difference

In the case of equipment the actor’s armature is on the object’s modifier stack and is really used to animate the object, not the actor.
In the case of cloth, we may not want to animate the cloth with the armature directly. Instead, we apply the armature (and the action) to the actor, which indirectly influences cloth dynamics.

So we need to retrieve the actor used to influence cloth dynamics. I’ll use the same naming convention I used for other equipment items, e.g. dress@player. Then we have:

def getArmatureForCloth(cloth):

influencingActor=bpy.data.objects[cloth.name.split('@')[-1]]

return getArmature(influencingActor)

This uses the naming convention to retrieve the actor. For basic animation export, ox3ich doesn’t need anything else (in code sample ‘object’ is the object using cloth modifier):

exportItemFile(object,path)                      # export basic mesh and material data

actions=getActions(object)                      # return actions for owner (uses naming convention)

armature=getArmatureForCloth(object)            # return the owner’s armature

exportActionFiles(actions,armature,object,path) # export all actions in the usual way.

Restricting key frames for export

By default, the exporter will export mesh data for all action frames, so I’ll extend the actor naming convention to allow us to define a frame range; for example

“player.walk@30-50″ # walk cycle includes only frames 30 to 50 for export

The following function parses the frame range according to this convention

def getFrameRange(action)

range=[1,30000]

parts=action.name.split(‘@’)

if len(parts)==2:

rngString=parts.split(‘-’)

range[0]=int(rngString[0])

range[1]=int(rngString[1])

return range

Notes

This is enough to get started with exporting cloth animations. There are several shortcomings:

  • The exporter does not bake cloth animations, this is done manually (so probably the cloth animation part only works if each file contains only one animation).
  • The exporter doesn’t explicitly handle cyclic animations. With my sample walk cycle, it doesn’t look all that bad, but there has to be a discontinuity between the first and last frame. Minimally the last frame should be replaced by the first frame. For smoother results, two consecutive cycles should be blended together, and I’d like the exporter to do this as well.

Aging

Remember one problem with cloth simulation is that the cloth / garment (or whatever else) is originally assuming a rather stiff, unnatural shape. One solution may be to add lead frames to ensure there is enough time for cloth material to assume it’s rest position.

A much easier solution in practice is to bake a few frames, then apply the cloth modifier in the modifier stack. This will save the current vertex coordinates (so if you go to frame 10 and apply the modifier, you have a ’10 frames old’ version of your mesh).

This method isn’t absolutely accurate for a cyclic animation. Our ‘aged mesh’ doesn’t record initial velocities, so it’s probably more accurate to run/duplicate (sigh) 2 or 3 animation cycles. Still useful…

The Marilyn Effect

I continued experimenting with the dress (I know I should post a pic, just think of it as a light summer dress or night dress).

And I continued getting this funny/bizarre/undesirable effect where the dress is steadily rolling over itself and upwards, and this isn’t exactly what I’m looking for.

I tried pushing a fair bunch of parameters that should logically rid me of this effect, but I can just about mitigate it. Shall we start from the beginning then?

  • Expected behavior: the dress settles down under the influence of gravity, covering the character’s body.
  • Actual behavior: the dress rolls up while the character is walking (12 centimetres up after a complete walk cycle)

Proposed solutions:

Increase the definition of the mesh

I don’t know for sure how the simulation works. So I guess this is worth trying since my mesh is pretty low def, just to get a rough idea of how the definition of the mesh affects the simulation.

=> At subsurf level 1, I gain 2 cm although it’s difficult to evaluate because the ‘bottom sleeve’ isn’t straight if anything.
=> At level 2 I strictly get the same as without subsurf enabled.

I guess this is good news if anything. Means I should be able to work at low def and save time on testing.

Increase gravity

The dress doesn’t roll up by itself. This happens because the character is walking, so their legs are pushing the dress forward and up. I thought that, if I increased gravity, it may be more difficult for the dress to bounce up.

=> Increasing to 10 G (100), the collision detection fails and the dress simply slips down. Interesting.
=> At 2G, the result is much more interesting. In fact I didn’t see the ‘dress rolls up’ effect in this case. But the result looked pretty rough so I increased collision quality (2>3>4) …and after doing this I fall back in the initial situation.

Increase Cloth Friction (Cloth tab group > Collision > Friction)

Increased friction is meant to ‘kill motion’ when a collision occurs. So I increase friction (5 > 80 – the maximum).

This pretty much does the trick, but just using it in isolation may not be enough; note that there are similar parameters in the collider’s collision tab (). However tuning this doesn’t seem to affect the outcome.

But just increasing friction doesn’t help much with a silk preset. It only really worked after I replaced the silk preset by leather.

Increase the mass?

I restored the silk preset and replaced the default 0.150 (Kg?) by a staggering 10 kg. The effect is spectacular. The top  sleeves stretched a good 20 cm down, revealing most of the character’s upper body. The bottom sleeve also dropped down. This uses about 10 frames. During the walk cycle per se there is no ‘rolling up’.

Changing the mass of the cloth demonstrates limitations when trying to pre-calculate a ‘rest position’. Say we burn 10 frames. Now the dress top sleeves are stretched 20 cm down as I explained. Let’s apply the cloth modifier and restart the simulation. What happens then? You guessed, the top sleeves stretch another 20 cm down.

Back to leather

I wasn’t fully convinced with my experiment with leather and friction. So I thought I’d try leather alone first, then add friction (80 – still maximum) and think things through.

In short, friction helped a little, not all that much. Without friction the dress seemed to be bouncing up and down, pretty much like very hard leather. With a lot of friction the overall effect would be better, filling more like wearing a clothe and less like wearing a piece of armory.

Some thoughts

There’s a couple of things I didn’t do, which may actually solve the problem independently from everything else:

  1. Make the dress longer (well… I’ve actually done that)
  2. Duplicate my walk cycle 2 to 4 times and run the simulation through.

Given the tests I carried out, it feels like we need to plan ahead, taking into account a dynamic relaxing process rather than trying to rely on pre-calculated aging. In plain english, I think if I made the dress longer, and let the animation run, a little more, it would stabilize and the dress would appear shorter, with more or less jiggling depending on selected material properties.

Since it’s a walk animation the feet of the actor are somehow linked to ‘ground dummies’. That shouldn’t make duplicating the walk cycle difficult, but somehow it does (at least for me). It’s a pity because Blender has unified views to deal with key frames involving concurrent objects (e.g. NLA editor) but these seem to fall just a little short of letting me ‘just copy everything’.

Cloth properties are unit-less. That doesn’t make individual properties terribly easy to understand.

I think it would be nice if we could specify in advance which parts of the clothe are stretched before running the simulation. Pinning feels like a kind of substitute, not necessarily a great one. Pinning makes it difficult / impossible to avoid combining the cloth with an armature, but then the kinematics of the armature tend to conflict with cloth behavior. Instead, I’d like to specify (e.g weight paint) that the top of the dress is stretched, while the bottom isn’t.

That’s it for now. Next time I’ll discuss exporting cloth animations.

Today I decided to experiment with the Blender clothes module (see here and here). So I took the hairlock/antistar PC model (the red haired girl) who happen to be wearing a pretty dress, and off we go.
It took me an evening to get something decent up and running. First I’ll describe the minimal setup, then reasons why the initial setup didn’t work out and how I fixed it.

The minimal setup involves three essential steps:

First we enable ‘cloth mode’ on the target (a mesh we’d like to behave as clothe, e.g. a table cloth, a pair of jeans etc…). This means that we tell Blender to compute cloths physics based on gravity and collisions on this object.

Secondly we setup one or several ‘colliders’ – Blender will only evaluate collisions with designated objects.
Finally we ‘bake’ (precalculate) the cloth simulation. While this step is in theory optional (Blender will calculate frames while scrubbing through the timeline), you’ll need a really fast box to avoid it.

I just outline the procedure, if you’re getting lost please refer to the links provided or dig up a YouTube video (no, really!). The caveats section is more interesting.


Minimal setup
  • Setup clothe:
    • select the mesh that you want to use as cloth.
    • select object > physics > cloth > enable clothe
    • enable clothe.
  • Enable clothe collision
    • In cloth tab group, select collision tab
    • enable collisions
    • enable self collisions (recommended)
  • Setup collider
    • select object to collide with
    • select object > physics > enable collisions.
  • Bake and playback
    • Again, select the clothe object, then object > physics > cloth
    • Select the start and end frame. The 250 frames default will have you wait a couple of hours or more. Just pick the frame range you need, or less to experiment with parameters.
    • Press ALT+A to preview the animation for baking is complete.
    • Select Free bake to get rid of the current simulation.

Caveats

  1. The first time I run this simulation I had the character’s skin clipping (showing through) the clothe. Not just a bit, really showing through.
    => If we have a character animated with an armature, and we want to ‘let physics take care of clothing’ we probably don’t want the armature to be enabled for the cloth object. However, with a posed character, that typically means that, in the first frame, the clothe object won’t be fitting, it will overlap the character. The simulation starts with the posed character as is (not the rest position).
    I shifted all keyframes 10 frames forward, then key-framed the character back to rest position (at frame zero) and fitted the clothe correctly. That got rid of clipping (no need to worry about collision quality just yet).
  2. To prepare my models for Open GL rendering I usually split meshes by color (otherwise color bleeding occurs). Unfortunately this also means that each colored piece of clothe becomes a separate object in it’s own right.
    => A cloth object must be ‘in one piece’ for the simulation to work correctly. separating color groups should be done later (e.g. when exporting the animation)
  3. Initially my character didn’t have a trunk (anymore). Why include faces and vertices that won’t ever be displayed? Unfortunately this doesn’t work any good with clothes, because there’s nothing to collide with(!). The solution, obviously, is to have a complete body with a decent shape! In fact we don’t need to use the same object for simulating the clothe and rendering (let alone animation playback in a game).
  4. Physics ‘takes time to boot’. The piece of clothe we’re animating won’t look right at frame 1, it needs to ‘shape up’ following the rules of the simulation.
    If we’re already adding lead frames at the beginning of the simulation to match the shape of the cloth with a ‘rest position’ then this may leave enough lead time for the clothe to start fitting naturally before our animation really begins, otherwise there is a technique (see links above) which allows baking a pre-calculated deformation for the cloth, so we could replace the original mesh by a fitted version.
  5. Why does it look all rounded?
    If we’re using something like 1 blender unit = 1 metre (I do) then the default minimum distance for collision is really set too high. if we’re trying to fit a cloth nicely, it will look good in places, bad in others. In my case I had a sleeveless dress with just a couple of ribbons to fit at the top, so the ribbons looked all round and even bounced unrealistically against… …nothing. Reduce the collision distance as much as possible (there are two settings for this, one in the collision tab for the cloth, one in the collision tab for the character’s body.
  6. Clothe simulation per se isn’t overly time consuming (or the Blender routines are deadly optimized), collisions are. Animating just about 20 frames takes minutes, and my model isn’t really high poly. This isn’t a problem except tuning parameters is time consuming.

Simple experiments

While trying to get around the ’rounded sleeves bouncing in thin air’ issue, I tried a few things…

  • Combining with the sub-surface modifier. It may be fairly obvious that, if we want smooth wrinkles and other clothe-like appearance, we might want to refine the definition of the source mesh. Adding a subsurface modifier does the trick (without the need to generate hard to edit vertex data). The subsurface modifier should be at the top, keep the cloth modifier (gets generated automatically when we check the cloth setting) at the bottom.
    Make sure the resulting subsurface doesn’t overlap the character
  • Pinning. With most garments, not all parts are meant to flow freely. In fact, some parts are stretched. The cloth simulator gives a light ‘free flow effect’ that looks nice in parts and rather terrible in others. So Blender includes a ‘pinning feature’. The idea of pinning is that a selected group of vertices will be very ‘stiff’ compared to other, keeping the default shape of the mesh throughout the simulation (can save a lot of time trying to tune cloth parameters).
    With a posed character, we really can’t use pinning without  adding the armature modifier to the clothe. While this hurts my logic a little (I want the body to the move the clothe, not the armature…) it can be fairly easy to limit the armature’s influence (e.g. use envelopes or vertex groups) to avoid unwanted effects.1

I’m seeing weird glitches when I combine sub-surface, pinning and armature together (sometimes). Aside, my character’s dress seems to bounce up all too willingly. It’s almost amusing but not always desirable; but I’m really just learning how to tune this up and there’s quite a bunch of parameters to go through.

Conclusion

Animating clothes with bones is a total pain (I tried). In contrast, using the Blender cloth functionality definitely has a learning curve, but the results look very promising. I can see many useful applications, even with fairly stiff, low poly clothe models. With a reasonably high poly count it can get really pretty.

I’m expecting the baked cloth animations to go through when I export the animation (because the exporter collapses the modifier stack, and cloth is a modifier) so I may be able to get this working in my game. Frames may need to be offset to allow time for ‘shaping up’ the garment, then I would need to adapt my exporter.

Finally, many animations cycle through. The physics simulation doesn’t take this into account, so beginning and ending frames must be interpolated, either while exporting or later.

A quick solution for equipment

The story so far

A few months back I wrote a simple export plugin for Blender. Unlike most export scripts, the plugin interprets blender files as asset libraries. The plugin supports basic material properties and animation.

When I wrote the export script, I didn’t want to spend time writing a bone animation module for the engine. Instead I decided to bake animation frames – bone deformations are applied from within blender, resulting in ‘mesh frames’.

While mesh frames are pretty heavy, there are advantages too:

  • Interpolating between frames is much faster than applying bone deformations.
  • Since the exporter generates frames by collapsing an object’s modifier stack, it is possible to export all kind of animations, not just bone animations.

Equipment

At that point, my setup didn’t provide a solution for equipment. So if I wanted an actor to hold an axe, or a sword, I had to clone the model and bake a separate animation. Needless to say such a system is hardly usable.

Equipping items consists in making them visible as part of a PC or NPC visual presentation, so an actor could hold a sword, a shield, or change dress (this requires more care).

The new setup is fairly simple:

  1. Bones are added to the actor’s armature – so we can add a bone to represent a sword, a gun, a hat… anything.
  2. The item we want to equip is placed at the correct location – so if it’s a sword, we just place it in the character’s hand.
  3. The item is renamed accordingly, e.g. sword@elven, indicates that the sword should animate along with an actor named ‘elven’.
  4. Parent the item to the armature (in the item’s modifier tab, I check ‘make real’ for the armature modifier, to ensure that this gets applied when the exporter collapses the modifier stack)

The notation item@actor is an arbitrary convention. Since actions are not bound to any particular actor, if we have…

  • an action named elven.strike
  • a piece of equipment named sword@elven

…then the exporter knows that elven.strike should be applied to sword@elven.

Animations are exported separately for various pieces of equipment. It’s a huge step forward compared to the previous system I used. When we want an actor to equip an item, all we have to do is load the matching ‘animated version’ of this item and synchronize animation playback.

This solution is still wasteful – but it wouldn’t be too hard to extend it to define equipment slots (so instead of exporting all animations over again for each item, we’d just have ‘dummies’ used to define transform matrices)

One Animation per File, really?

When I investigated Blender animation to create my exporter, I found about Blender actions. Blender actions provide a simple, easy way to define ‘several animations per actor’. More specifically, an action is a named sequence of key frames associated with an object (typically an armature, but also works with other object types). So at the moment I have ‘run’,'walk’,'hit’ actions etc… While actions are normally used in NLA (non linear animation – aka mixing part animations together, e.g. smile + run), they originally seemed well suited to building ‘animation libraries’ - All the exporter has to do is retrieve each action, bind it to the armature and export it.

Unfortunately, this approach breaks down when we combine several animated objects. For example, suppose you want to apply a floor constraint (e.g., as part of a walk animation), then…

  1. Consider the armature for the actor we’re animating.
  2. Define a ‘floor’ object
  3. Define 2 empties (used to move the actor’s feet)
  4. Apply the floor constraint to the empties using the ‘floor’ object as target
  5. Add IK solver constraints to the feet of the actor’s armature, so the feet now follow the empties.
  6. To animate, we move the empties, not just the bones.

How many objects are being animated here? Well, 3 really. We have the armature and the empties. To setup this animation correctly, then, we need to bind the following actions (assuming we associated the empties animations to actions) …

  • The armature action (e.g. elven.walk)
  • LeftFootEmpty action (elven.walk.leftFoot?)
  • RightFootEmpty action (elven.walk.rightFoot?)

At this point, I drop the towel altogether. Although there are disadvantages to keeping one file per animation, we have to choose: unless an animation is simple (1 action <=> 1 animation <=> 1 object), it should be kept in a separate file.

I guess if it was to do all over again, I’d simply try to avoid complex rigs. In the meantime I changed my export script (never mind some of my engine code) so that animations are always kept in separate files. I now have, for each object:

  • A model file. All models, whether animated or not, use the same format
  • For each model, zero, one or several animation files.

In order to get started porting my engine to JME, understanding this example seems like a very good start. It’s also a quick, hands on way to understand M3G and the blender exporter. So I’ll replace the Pogoroo by one of the sample files associated with the blender exporter. This will break the app and I’ll learn how it works by fixing it.

Please refer to my last article for links to this example — won’t be much use if we’re not looking at the code together.

I really liked the Pogoroo example. Apparently this was originally provided by Superscape, and somehow bundle in Sun’s edition of the JME before landing in the Samsung SDK.

I also like the blender M3G exporter. So I did this…

myWorld = (World)Loader.load(“/com/superscape/m3g/wtksamples/pogoroo/content/bebe.m3g”)[0];
//myWorld = (World)Loader.load(“/com/superscape/m3g/wtksamples/pogoroo/content/pogoroo.m3g”)[0];

…after trying this:

myWorld = (World)Loader.load(“c:/bebe.m3g”)[0]; // replace by sample model exported from blender.

Since an absolute path doesn’t work, we can tell that there’s a configuration bit somewhere setting the path for resources.

Now, you’d figure that we can’t replace the original model by another one, and you’re almost right. Except instead of a black screen we get a very cute 3D rendering of a Penguin (Pingoo?) and an engaging exception.

So I think we’re set. We have a working JME project manager, a working simulator and a working assets exporter. Time to understand some of this stuff. Now, this is what triggers an exception:

tRoo = (Group)myWorld.find(POGOROO_MOVE_GROUP_TRANSFORM_ID);
tCams = (Group)myWorld.find(CAMERA_GROUP_TRANSFORM_ID);
acRoo = (Group)myWorld.find(POGOROO_TRANSFORM_ID);
animRoo = (AnimationController)myWorld.find(ROO_BOUNCE_ID);

I haven’t looked at JSR184 in the past 5 years or more, and I never actually used JSR184. The beauty of it is that it doesn’t require an explanation(?).

Here’s what I’m finding:

  • I moved the camera in the original blender file and exported again. The camera updates in the MIDlet, so this camera is actually in use.
  • None of the above calls (tRoo = etc…) does actually trigger an exception, so they’ll just be returning null (I don’t have a debugger setup and line numbers seem wrong, so I’m tracing)

Surely this would trigger a NullPointerException at this point.

AnimationTrack track=null; // changed this way because there is already code to provide defaults instead.
//AnimationTrack track = acRoo.getAnimationTrack(0); // exception!

Once modified as above, we don’t have an exception anymore. We can use the phone simulator’s controls to try to move the Pingoo and it obviously doesn’t budge. More worrying, we don’t get an exception either.

I want to reassign tRoo, tCams, cRoo, animRoo. If we can do that, we’ll know that we know for sure how the exporter generates IDs. But before that I’m really curious to find out why trying to operate the controls doesn’t throw an exception.

So I started tracing this stuff again, and I found that exceptions raised within RefreshTask‘s run() method (Oh my… they use a timer for that!?) aren’t displayed. We can catch them though.

So what do we need?

This is what gets extracted first:

private AnimationController animRoo; // 5, 18
private Group tRoo;
private Group tCams;
private Group acRoo;

In my last article I mentionned that the blender M3G exporter allows the user to specify a user ID for scene nodes – scene nodes are retrieved using an integer – a (hopefully) unique identifier. The Pogoroo example demonstrates the same idea.

I missed several interesting facts about the exporter and the provided example last time:

  1. The exporter assigns ID 0 to anything that doesn’t have a user defined ID (so much for unique IDs?)
  2. In the provided example 2 nodes have ID 1. One is the armature controlling the Pingoo, the other is an animation controller.

The exporter displays export related data (includings IDs) in the blender console. Rudimentary, but it helps.

Bound animRoo

The first item I managed to rebind was animRoo. I used the second animation in the blender file, and this works easily because it has ID 2 by default, and that is a unique ID.

Bound a transform group for the camera (tCams)

In the blender scene browser (I’ll post a screenshot), any object seems to be living under a transform group. However, although tCams expects a transform group, the exporter doesn’t create one for the camera. Instead the transform and the camera seem collapsed to one node.

So I added an ‘Empty’ in blender and parented it from the camera (so the camera is a child of the empty). I named this Empty#25 (25 is an arbitrary int I came up with and voila I managed to bind my camera group.

tRoo and acRoo

I have these two left. Now I have nodes for both the armature and the Pingoo, but they’re not groups. Since I already got into this trap, I thought OK, why should we have two transforms for the Pingoo. Not diving deeper into the code, I’m just guessing there’s an inner transform for the rotation, and an outer transform for the translation. So I made two empties, further complicating the transform hierarchy, but maybe necessary to get this to work. I ‘named’ them 200, 201 and updated the static ints in the java file.

I wouldn’t say this feels like it works as I expected. However…

At the next run, several interesting things happen:

  1. I can see the little Pingoo moving it’s beak. So our animation is working out, big time!
  2. Left/Right keys appear to rotate the Pingoo
  3. Top/Down appear to move the Pingoo

I write ‘appear to’ because these behaviors seem somehow incorrect. I put the camera back in place (facing the pingoo) and moved the transforms (aka tRoo, acRoo) to coincide with the Pingoo’s vertical axis.

Interlude

My cute project manager seems to be getting moody. Also, when I check my process my manager, I find 4 (yes, four!) instances of java running simultaneously. Admittingly they don’t seem very busy, but that’s just a cherry on top of weird taskbar widgets that I didn’t have before installing the JME SDKs (three of these).

Guess I’ll try a ‘cold start’.

Finally

I checked things up after restarting the IDE. The Pingoo is moving along the wrong axis (got bold enough to actually add some terrain so I could get a fair idea). It’s rotating too, but somehow I’m not convinced the camera is following as it should. This seems to be down to axis orientations (and assumptions the ‘game logic’ makes about it).

There’s a lot of good stuff in here. JSR184 clearly supports bone animation, textures and lighting (looks horrible in the simulator) out of the box, never mind a well formed scene-graph. Plus, the exporter gets it right too, although I really need to do something about these IDs.

My engine maybe implements 10% of all this stuff, not to say anything about my exporter. So porting the engine ‘facade’ and reimplementing my game logic on top of that may be much easier than I anticipated. Proof also, than 10% of a game engine can run a pretty nice game. OK… I do have quite a bit of stuff in there that’s clearly not scoped under “3D rendering”  :)

The frame rate is defeating in the simulator, but it doesn’t say much about how it would look on a phone.

I think the sample *.m3g files (and the methods used to load and display them) look neat. I also noticed that Blender has an exporter for *.m3g with support for textures, armatures and animation. Gerhard Völkl clearly put a lot of work in this exporter, topping 3000 lines of code in a single file (a couple dozen classes in there, it’s actually quite readable).

(note: on a PC you can find the source for blender py scripts under Documents and Settings\User\Application Data\Blender Foundation\Blender\.blender\scripts)

The linked page also provides samples files to help us understand how the exporter interprets blender files. There are two things I immediately want to know:

  • How are animations exported? In Blender, bone animations are not directly connected to armatures. Export plugins typically use a kind of naming convention, and this one makes no exception, for example Talk#A1E10#2 is an action, where A1 refers the target armature, E10 means the animation ends at frame 10, and 2 appears to be the node ID (see below).
  • How are node IDs selected? From sample M3G code, it’s fairly obvious that M3G files, for better and for worse, do not contain named entities. Unfortunately the blender M3G exporter uses a naming convention that requires the artist to insert IDs. Maybe this can be improved a little – for example, we could have a java source file with named constants remapping blender object names from arbitrary IDs.

The M3G exporter also allows direct export to java code (in other words, it can generate code which, when run, will produce a scenegraph).

Useful resources

Hairlock - dev pic

Originally developed under the codename ‘Hairlock’, Antistar 3D: Rising. is a universal game (iPhone, iPad, iPod Touch) published on the 1st of August 2010. Artwork in the game is a mix of Blender art and procedurally generated elements.

A Key Decision…

It was decided very early that all the details in the game would be modeled – no textures! There are several reasons why Antistar was created this way:

1 – I have never been very fond of textured games. This is isn’t because I think textures are bad, but because usually, I find that textures are abused, becoming an easy substitute for shading and high quality visual content.

2 – I trained myself in blender around 2000-2002; I always focused on modeling.

3 – Supporting textures would have added a load on the engine, taking longer to develop, leaving much less time to produce the actual content, making it potentially harder to run at frame rate and increasing loading times.

4 – Although it is now available on iPhone 4 and iPad, the game was originally developed to run nicely on an iPod Touch. On a small screen, the need to crowd scenes with tiny flatland decorations isn’t obvious – even if some games (e.g. Samurai: Way of the Warrior) use textures very ingenuously.

Blender’s good

Edit mode rocks!

Back in 2000 when I discovered Blender, I was still looking for software that could help me make my models. I am not a professional artist, so I need to try again and again until I see what I have in mind in the 2D view. Blender’s edit mode, with one hand on the keyboard and another securely cuddling the mouse, lets you change things over and over again at the speed of thought.

While the game doesn’t use textures, Blender has a nifty ‘retopo’ mode allowing to project geometry onto a surface while editing. This was used to add effects that make some players think that the game supports textures, but more importantly, offer an OK substitute to textures in situations where they’re really needed.

Free and comprehensive

It just turns out that Blender is completely free, open source and comprehensive. I didn’t use many features, but these are key to creating a game:

1 – Support for bone animation, with a little of a learning curve, but the same ergonomics found in edit mode, allowing to quickly define and adjust areas of influence for bones, add constraints, etc…

2 – Python scripting. I looked around for an export plugin for ages before getting into it, only to realise that python scripting isn’t hard, and there are key advantages to writing your own file format for 3D. In Antistar, geometry is loaded on the fly, in a format that Open GL understands, as exported directly from Blender, in just a couple of clicks.
Hairlock - dev pic
Technical data

How much geometry in there?

As this was my first 3D engine, and my first experience on a mobile platform, I was fairly cautious when I started modeling, as I was worried I would run out of GPU time fairly quickly. Over time I realised that (a) rendering is pretty fast, even on an iPod Touch 2nd gen, and (b) once we do away with mapped images, we have a lot of polygons to play with (it’s also good to know that smaller poylgons render much faster than large ones). Here are some examples:

- Humanoids and other creatures: 650 to 2500 vertices/quads(*)
- Small decorations: ~40 vertices/quads or less. These can get duplicated a few dozen times in the same scene.
- Terrain (e.g. the ‘incubator’ scene displayed at the top): up to 10,000 vertices/quads.

(*) In most cases, the number of vertices is roughly equal to the number of quads.

Rendering

For rendering, I used a mix of just-in-time calculated and real time lighting (for actors and props). Evaluating simple illumination on the fly while loading models has advantages, but I haven’t implemented a method to refresh lighting following the day/night cycle in the game; instead, fog is used to affect the rendering of the environment according to the day/night cycle.

I’m still considering whether to use LOD (level of detail) nodes (aka, lighter models when viewed from far away) or not. In the first version of the game, I used depth of field balancing to avoid dropping the frame rate too much. depth of field balancing works quite well, although it seems a little difficult to make it perfect :). in the meantime, artefacts aren’t usually disturbing and may even bring a little life to the game, with soft oscillations in depth of field and fog level.

Cheats ?

At times 3D can get a little intense. To create the dark forest near Klinnburg, I flattened the trees, only leaving 2D geometry. This allowed keeping patches of procedural grass that I kinda like, and adding walkable stones here and there. I don’t like doing that too much, because it always does show a little.

Future work

materials

In the first release, the exporter only processed RGBA colors for materials. The engine is a little more powerful though, as it can take parameters for shading, ambient… well, the basic kit.

I probably want to get better at python scripting, so I can explore ways of generating geometry using plugins, and better balance what’s generated on the fly versus what gets loaded.

Hairlock - dev pic

level editor

Currently, my export plugin handles objects and bone animations quite well, but it works more like a library export plugin, with any blender file containing a generous mix of actors, items and terrain. I want to take the time to turn this into a level editor. This would help streamlining the workflow, as for now the ‘level editing’ process consists in walking around the world and writing down coordinates (**)

forward raytracing?

And finally, I’ve been working on ‘rough and ready’ procedures for self illumination (!). This can be used part in real time, part by pre-calculating contributions. Initial results are promising and the results may ship with the game within a couple of months!

————-

Antistar 3D: Rising – is a realtime 3D adenture taking advantage of 3D capabilities on the iPod Touch, iPhone 3G/3GS, iPhone 4 and iPad. (app store link)

Hairlock - dev picBy the calendar, I fixed many obvious bugs in my game engine up to the 1st of March. Since last week, and for hopefully no more than another dozen days, I’ll only be working on game assets.

Guess it’s time to post a pic then – the project still goes by the codename Hairlock - not as good as it used to be since the hairlock incident proper has been moved to a proposed sequel.

I started modeling a couple of months back, among worries that the rendering wouldn’t follow. Now the question is different: can the artwork follow?

One question that comes to me over and over about the artwork is, why don’t I borrow/buy stock models? I doubt whether this would actually be feasible granted my geometry has to stand for (no) textures, and game models following the twist may be hard to find. But that’s not it. Nor taking the challenge (well yeah, in part…). I just have this feeling that even amateur artwork will be more interesting than even professionally produced stock models – granted it is designed to be coherent and originally produced.

Sure I could use borrow or buy artwork for little things – one chair here, a house there, and so forth but…

The actual cost for me is characters. The little guys on the right took me about 15 hours to get done with. And we don’t want to borrow characters, do we?

Artwork is expensive, but we don’t need to pay every time

The bottom line is…

  1. Since a game is its own universe, it may be a good idea to create original artwork for it.
  2. Within the game, reusing artwork elements increases consistency without compromising quality.

One of the great advantages of 3D is that 3D is vector graphics. While the cost of a new model is high, dressing up a model in different ways, or just changing it a little, is fairly cheap – if you’re using Blender and you’re out making actual geometry for clothes or hair, retopology may be worth a try. That, and a little patience.

So while I enjoy making new stuff, I also look forward to just pulling models off the hat later on, so I can focus more on story and game mechanics.

About the screenshot…

Here we’re running at around 13 FPS. The models use no textures, so everything you see is (un-decimated) geometry.

  • Our little heroine on the left renders 1,588 vertices / 1623 faces
  • The wise guy with the bed-head boasts 1,812 vertices / 1790 faces

This goes on top of the 15,836 faces sent to render the environment (hardly any of this actually intersects the viewport) using 7 calls to glDrawElements.

I don’t know about textured scenes – you can do a lot without textures (in fact, a lot more than what is demonstrated here). For now here’s a quick break down of how this renders:

  • 36.3% rendering the terrain
  • 12.5% rendering actors (frame interpolation doesn’t generate overheads in this particular case since I got the actors to pose for the pic)
  • 19% hit testing to keep the camera somewhere reasonable (oh no!)
  • 5% running game logic
  • 10% (!) refreshing the text box (this gets done quite often just to display the frame rate…)

I’m not worried yet about the terrain rendering time – I might have to eventually. Hit testing overheads are to go away altogether (not the hit testing, just overheads). I’m not planning yet on using distance based LOD – overall, I hope these stats make you feel that it’s possible to run at frame rate with detailed geometry on an iPod Touch, and if doesn’t, let’s wait until we get better screenshots :)