Thursday, November 18, 2010

How to merge animations?

There are two basic problems with copying animations from one figure to another:
  1. The skeletons do not match. First, the body proportions are off, especially if converting between male/female or realistic/stylized characters. And secondly, the non-obvious bones are often arranged completely differently. By obvious bones I mean the ones like armbones, shins and so on, that connect two visible joints. Non-obvious bones are hidden and their joints are not immediately visible - like backbone or shoulders. Thus the exact number and placement of such bones may vary, depending on how realistic and fluid motion is needed and how it is achieved.
  2. The bone orientations do not match. Even for bones that are perfectly aligned, like arms, the local coordinate systems can be very different and thus the transformations from one skeleton cannot be immediately carried over to another.
 How to deal with it?

In Khayyam I am currently doing the following procedure:
  1. Create one-to-one links between the well-defined bones of each skeleton - i.e. legs, shins, arms, forearms and heads. These function as anchors for matching body movements via IK solver.
  2. Pick rootmost joints of matched bones, i.e. hips and shoulders as anchor point pairs.
  3. Find the bone chain leading to last common ancestor of such pairs (starting from the point where previous chain ended). I.e. we get chains like these:
    3.1. Center_of_Mass -> Skeleton_Root -> Pelvis
    3.2. Lower_Backbone -> Upper_Backbone -> Chest
  4. Adjust chains, starting from rootmost, as closely as possible to anchor points using IK solver.
  5. Point all well-defined bones to the same direction as the originals, using IK solver

As you can see, it basically works, although some constraints on joint movement would be nice.

A demo video showing how dancing moves for DAZ skeleton can be imported to Esk Anderson figure

Sunday, November 7, 2010

About C++

I have had love/hate relationship with C++ from the time I started using it extensively about nine years ago. Before that everything was C - for example Sodipodi was 99.9% written in C (the only exception was the interface to KDE file dialogs). Those were good old times...

The learning of C++ was mostly one big frustration. Few beautiful and useful features - buried in clumsy, unintuitive and ugly mess. So after trying out and throwing away one feature after another, I mostly joined the C with classes crowd. This is the style used in Khayyam/Miletos/Elea code. But even for this minor subset of features, the language is just implemented plain wrong. Some completely elementary, clean and logical things are missing - and on the other hand - extremely clumsy, opaque and hard to use features are present.

So following is my list of things I'll one day implement in my own C Successor(TM) language.
  1. Keep classes and struct separate. Structs should be POD, classes should ALWYAS have pointer to RTI. So no virtual methods for struct - and who in his right mind will miss these?
  2. Keep memory layout standardized. Seriously. Probably all C++ variants implement things in one way - but the specification refuses to fix things once and for all.
    • Classes are struct(ure)s. Like in Java. Standardized containers having function pointers for virtual methods, RTI information, link to parent class and so on.
    • All object instances have hidden data field in first position, that is - you guess it - pointer to class struct(ure).
    • All nonstatic methods should have pointer to class instance as hidden first parameter. So you can call class method from C. It is implemented this way anyways - but why force people to jump through loops to use it.
  3. Keep meta-language separate from core. Implement two-pass compiling or something (in addition to preprocessor).
    • Operator overloading should be specified in some meta-language. This would allow really useful things, like implementing separate dot and cross operators for vectors and so on. It should be transparently translated into proper C code during metalanguage parsing pass and then compiled by normal C/C++ compiler.
    • Templates should be specified in proper metalanguage instead of "yet another hack on top of C syntax" and translated into normal C code during compilation.
And for extra sugar - allow overloading the virtual method call operation. So I can actually subclass object systems from other languages without writing countless ugly wrapper classes.

Obligatory screenshot - Ichiro having break in a forest (needs better lighting actually)

Tuesday, October 26, 2010

Chibibel

Chibibel is a character by DAZ3D.
Poser cr2 (character rigging) files are quite heterogenous. So until now Chibibel has been the main reference implementation for cr2 importer.

Things implemented so far:
  • Parsing actor tree with channels. Actors (or props) are just a fancy name for bones (or frames) - i.e. positioned and transformed controllers for skin data. Channels are elementary property controllers - like individual rotation angles, morphs and so on. The main problem is, that the whole cr2 file format is mostly just (text based) dump of internal Poser controller structure as opposed to properly designed file format, so it contains many duplicate entries and meaningless data.
  • Twist and joint bend zones (no welds yet). Poser is special because the bending of joints is controlled with different weights for each main rotation axis - and these are specified algorithmically by line segments, angles and spheres. I am somewhat sceptical whether this would allow more natural movements - the weight system with extra bones and constraints should IMHO be easier and more powerful. But maybe it would be too difficult to set up for 3D modeling novices...
  • Welding obj meshes. Obj files cut meshes to groups, that cannot have interconnections. So cr2 file specifies, which groups should have their identically positioned vertices merged.
  • Loading textures from image files. Poser has quite complex material system, but currently Khayyam only looks it for diffuse texture entry and loads it as plain texture. Hopefully more is coming.
  • Conforming objects can be dropped to the same figure object as body. They behave surprisingly well, moving and bending with skeleton. But morphs cannot currently be linked, so if clothing has conforming morphs, they have to be adjusted manually.
  • Morphs work, but their values are not saved in XML data.
  • Props can be loaded but cannot be directly associated with bones. Props is (another) Poser fancy name for immutable objects (like tools, buildings etc).

Kuroyume Unoffcial CR2 File Specification has been invaluable resource for digging through the cryptic character data of Poser files.

Obligatory screenshot - Chibibel selling pottery in market (rendered with POV-Ray)

Saturday, October 16, 2010

First steps with Poser(TM) figures

Khayyam can now load (no import dialog yet) some basic Poser figures. They are not even close to renderable status yet, but things are becoming more interesting now:
- Basic morphing works
- Skeleton transforms poses as twist/joint/joint angles to body
- Blending angles are implemented
- Spherical falloff zones work (somewhat)
- Color values are parsed from materials

The next things I am working on currently:
- Loading conforming meshes (like hair and clothes)
- Implementing bulges
- Welding vertices

Obligatory screenshot - chibibel from DAZ3D

Friday, October 8, 2010

Khayyam architecture

Khayyam is a collection of handful libraries plus shell application written in Gtk+ toolkit. Most components come from Sourceforge Floyd project, but core components are borrowed from Sodipodi. The most basic building blocks are

1. libarikkei (Sodipodi)
This is a collection of utility libraries for file handling, unicode parsing, text file tokenizing and similar things. It has both C and C++ versions of some most basic functions and is implemented as small, self-contained library that can be directly included into project.

2. elea (Floyd)
This is (yet another) 3D geometry library written in C++. It is meant to be small, so only the subset of functions used in Khayyam (and some other) are implemented. Again, it is self-contained and can be directly included into project.

3. libnr (Sodipodi)
This is small, self-contained, anti-aliased 2D rendering library.

4. libnrtype (Sodipodi)
Compact text rendering library on top of libnr

5. sehle (Floyd)
3D engine for OpenGL 2, using libelea for algebra. It is meant to be mostly bare-bones layer, implementing only the most basic stuff, like vertex buffers, textures, display list and so on. It should be quite flexible regards to rendering pipeline.

6. thera (Floyd)
Small and compact DOM-like library for XML parsing. It implements basic parser and writer on top of libxml, node tree, basic mutation callbacks and transaction system for rollback (undo and redo).

7. miletos (Floyd)
Fat scene graph library on top of thera, sehle and elea. Implements all more complex things like various file format parsers, skeletal animations and so on. It borrows the basic design concept from Sodipodi (although is implemented in C++ instead of C) - it is written as typed object tree, parallel to the purely untyped tree of thera. Most editing can be done either directly for temporary editing, or by customizing thera nodes or attributes for permanend modifications.

8. khayyam (Floyd)
This is the application itself.

This is only the most basic overview. Next time I hope to write some more details.

Obligatory screenshot (Des Blood 4 models, Digital Girl background, rendered with POV-Ray)

Monday, October 4, 2010

What is Khayyam?

Khayyam is a frontend tool to my experimental set of 3D (and related) libraries.


A scene composed in Khayyam and rendered in POV-Ray
In current incarnation it cannot do much. Still you can import some model formats, place and pose these, and render resulting scene in POV-Ray. Plus it is free software. And works under both Windows and Linux.


A small overview of Khayyam can be found here.

At moment I am working on Poser model format support. This will be the first step for Khayyam to become a serious rendering tool.