Skip to content

Posts tagged ‘Rigging’

Disney’s dRig

December 16, 2012

Charles

I really like Disney’s approach to rigging – with their latests paper instead of building modular units such as ‘arm’ or ‘hand’, they’ve instead devised a method to make the coding itself humanely readable and easy to understand.

Variables & Operators

I’ve been thinking about this myself and essentially it breaks down into two things 1) you need to be able to assign variables and 2) pass operators.

If we take a simple class based function:

create.box(length=1.0, height=1.0, width=1.0)

We have have some base fields – the class, its method, and some arguments passed as assigned types. So what does a field need if it was humanly readable?

  1. Firstly it would need a value for the fields name.
  2. It would need to know if it can pass multiple values.
  3. It would need to know if it passes values or fields.
  4. It would need some sort of rule on its syntax and definition.

So for the above method we’d have something like this:

CLS create DEF box ARG  3 FLOAT length 1.0 FLOAT height 1.0 FLOAT length 1.0

So pretty straight forward – each of these CLS, DEF etc is a field type, with its own rules that govern what the next input should be. An example with a list field could be as follows:

LIST none 2 FLOAT none 1.0 VECTOR none [1,0,1]

So this is a list field type, which has no assignment (thats why its none), has 2 for the next input because it allows for multiple inputs. The reason why the next input is FLOAT is because crucially, fields need be able to pass other fields as input. So the code would compile to something like this:

#(1.0, [1,0,1])

The ‘#()’, is a syntax definition for the field, along with the ‘,’ – values/fields passed to a field could and probably should have a syntax definition too.

With something like this we could code a framework pretty easily, and because these are just one lines they are pretty easily modded. Here’s an example of say an ik chain:

CLS ik_chain create METHOD none chain ARGS none 3  VECTOR none [0,0,0] VECTOR none [10, 0, 10] VECTOR none [0,0,20]

This would evaluate to something like this:

ik_chain=create.chain([0,0,0], [10,0,10], [0,0,20])

What i don’t like about this is assignment is using none when its not really  needed – which i dont like. Crucially i think the string you’d pass should only have what you need. E.g.

CLS ik_chain METHOD chain ARGS 3 VECTOR [0,0,0] VECTOR [10,0,10] VECTOR [0,0,20]

And even the field types themselves could go possibly?

ik_chain create chain 3 [0,0,0] [10,0,10] [0,0,20]

But now we have a problem – by stripping field types etc.. we start to lean towards a structured string. 3 for example can’t be placed anywhere – in fact what does it mean without some association?

So defining fields allows for customization, but we have to be careful to only give enough information for the data to be compiled. My hiccup is that anything can be assigned e.g.

var=1.0

So do we type ‘FLOAT var 1.0’ for it to be assigned and ‘FLOAT none 1.0’ –  for it not to be? It’s seems the none is just extraneous info we don’t really need. Could value that gets passed to the rule allow for assignment? e.g.

FLOAT ‘var=1.0’ – we’d have to split this string based on the ‘=’ and then pass the second half to the rule.

CLS ‘ik_chain=create’ METHOD ‘chain’ ARGS 3 [0,0,0] [10,0,10] [0,0,20]

Advertisements

Function hierarchies, templates and schemas…

October 30, 2011

Charles

I don’t know if anyones used this idea, but I’ve been looking to a rigging frameworks recently. At a discussion I started on LinkedIn JSON was mentioned as a friendly humanly readable format for building a rigging framework – I concur, its a very simple a clean system of objects e.g:

{
“myObject” : {“a property” : “a value”, “another property” : “another value”}
}

The template

At its heart you simply want to build a skeleton apply a template to it and let it build the rest – you don’t need a visual template or guide, infact the skeleton doesn’t need to know anything about the template or vice versa – all thats needed is inputs to the template.

What is this template? To me it’s essentially a hierarchy of functions, with each function defined in a schema. The hierarchy aspect comes in when a function can pass its results to the input of the next function. The ‘intial’ function in the chain could have inputs that get passed to a gui – and the nice thing with this is that it satisfies users needs at each level. At its simplest a layman builds a skeleton, assigns a template to the whole skeleton or a part of it.

The intermediate  user doesn’t need to understand each function of the template, ( defined by the schema) but is skilled enough to build templates mix functions and pass inputs correctly.

The expert user would have full understanding of the schema that drives the functions and the code of the function itself.

The power of this approach is you have a schema that defines functions that are ordered in a template. You can change the order of the functions, remove functions etc in the template, and allow the template to point to a different schema to completely change the results. Very much how an html document uses css to structure the data.

How would a schema work? Something like this I’d imagine:

{
“schema” :
[
{“id” : “ik_system”, “path” : “path.module.def.function”, “arguments” : [{“name”:”joint”, “type” : “node”},”boolean”, “node”], “returns” : [“float”,”list”, “boolean”]}
]
}

How would a template use this schema? This is the hardest part; i’m guessing something like this:

{
“passedToGui” : [{“id” : “joint”, “type” : “node”}, {“id” : “allowStretch” : “boolean”}],

“functionHierarchy” :
[
{“id” : “buildLeg” , “type” : “ik_system”, “arguments” :[“passedToGui.joint”, “passedToJoint.allowStretch”] },
{“id” : “buildFoot” , “type” : “foot_system” , “arguments” : [“buildLeg[0]” , “passedToGui.allowStretch”, 10]
]
}

With objects/attributes following ‘.’ or ‘[#]’ methodology –  argument passing is still something i’m looking at. But the nice thing with this approach is that is could be used with pretty much any 3d package all your doing is associating functions/defs/methods to a schema and using that schema in a simple template  that users could edit ‘visually’ in the viewport or just by the script itself. Error handling would be to validate the template can work (function results allowed to be passed to other functions) using the schema.

Isolation at the neck, head or both?

May 29, 2011

Charles

Most bipedal rigs tend to have isolation at the head, but a lot of quadrupedal rigs have it at the neck – is it really a case of spreading the isolation from the chest to the head over the length of the neck? This doesn’t seem true of a giraffe – in its case the neck is a column that can be independent of the spine, with secondary bending at its center.

I’ve done both, but am thinking if there’s a commonality between – i.e an approach that can use both.

Mapping data..

March 27, 2011

Charles

Data is becoming more and more important to share across multiple rigs, skeletons, skin etc. Data itself can essentially be dependent e.g. skin weights are dependent on a model and a list of bones or non-dependent, a skeleton in the scene for example. Mapping too can either be online i.e live captured or offline i.e baked/plotted down. I’m slowly working on a format the allows for mapping different types of data in max.

My idea is to first store a list of id’s for the source objects, and a list of ids for the destination objects. An objects controller (treated as a string – exprForMaxObject) would get mapped to several other objects via there id and im guessing some sort of expression. Mapping a value to multiple values is the trickiest part and also calling an expression on them. Heres an example:

1 "root_a"                                              1

2 "root_b"                                              2
3 "spine_b"

1 bezier_float "pos.controller[1].controller" 2         3
2 "pos.controller[2].controller"                        4
3 "pos.controller[1].controller"
"@2+@3 + 10.0" 4.0                                      5

So firstly (1) we store the ids for the source objects and there names, they could be hierarchal in theory if we add an additional id for there order. Secondly we do the same for the destination objects. The meat of the mapping (3) basically stores firstly the id of the object being mapped, then the class of its controller, and the controllers “object” lastly we store the amount of target objects its going to be controlled/mapped to.(4) we store the target objects id and there controller “objects” – we don’t need to define the class of there controller object i think because its an explicit approach i.e it inherits the type from the ‘mapped object’ – this my bite me in the ass later though as for example point3 and bezier_pos look identical.

(5) lastly we call and expression using the target objects id’s – this is a little messy as i have to determine if the expression is using the id or just a regular value. “@” is an idea for the minute. In theory you could call whole functions e.g “myFunction #(@1,@2)” as long as it returns a correct type . Lastly i store an offset value, why?, well if were not passing a function but still want a offset value applied – e.g. transform offset.

This just an idea for now, I’m not sure if ill store the target id’s in parenthesis “{“,”[” etc.. It’s pretty humanly readable which is good, and easy to change objects just by changing the string the id points to. Controller objects are harder to change, its why i specify a class type way at the front for them to compare against. How this works for simpler 1:1 mapping might get messier e.g. mapping a skeleton to another skeleton for skin weights..

1 "root"
2 "spine"

1 UndefinedClass "" 1
2 ""

Little/Big Idea: Nodal App

February 26, 2011

Charles

I’d love to build an app, which basically only manipulated data/prototyped data. Basically you would import mesh data/nulls/shapes etc (possible create base types: nulls etc) and  rig/control them through a nodal work flow. I.e Max’s script controller in encapsulated nodes.

  • Import models, objects, point cloud data – possibly create nulls etc
  • Transforming wouldn’t need specific connections (i.e a transform handle node in Houdini)
  • Parenting would be done in the viewport and possible show up in a schematic type view

MotionBuilder similarities:

  • Each object would appear as a node or cluster (point cloud etc) – inputs/outputs being position/rotation/scale/xyz
  • Local/world space could be used as input output

XSI/Houdini Similarities:

  • Nodes could be grouped/compacted into digital asset/compound like object. i.e you could build an IK/FK compound
  • Vector operations on the models etc

Operations E.g.

  • add, subtract, multiply, inverse, transpose, dot, cross, power,exp, factorial, abs,ceil,floor,mod,arcLength,tangent, binomial
  • sin,tan,cos, acos

Case Types E.g.

  • If/else/elseIf/finally/then, continue/while, try/catch/throw/break

Value Types E.g.

  • integer,float,point2,point3,point4, matrix n*n
  • custom variables
  • pi, e, etc

Questions..

  • Importing data – simple xml data, open customizable
  • Animation support?
  • Skinning support?
  • UV support? Masks?
  • Reference space – At one level we want to work on the object itself, at another we want to work on its vertices/knots etc. Operators need to handle both levels of abstraction.
  • Is this just for prototyping? (i like this) – need XML to export data to be readable in a standard web browser for translating in final app max/maya etc..

Maybe I’m just describing Houdini/ICE, but this would be purely for visualizing/manipulating object relative data –  custom subsystems e.g. iksolvers, rendering, animation layers, custom constraints etc etc..

More on XSI Compounds here: http://softimage.wiki.softimage.com/xsidocs/ICE_compounds_OverviewofICECompounds.htm

Re: Owning Keys

February 13, 2011

Charles

Maybe I was a little hasty. Crucially when it comes to keys, animators need to know the reference a value exists in – and that, it shouldn’t change.  For example if I animate a guy jumping from one platform to another – the curves of the jumping, moving from and to the platforms shouldn’t pop erratically to allow its reference space to change. More over the the space the values are relative to should be transformed.

Offsets

The offset is a great mechanism for retaining space – it wouldn’t be a good mechanism for FK/IK systems because your trying to force the IK/FK into its opposite – i.e you want its value to change. Can we form a rule here?  When you want the value to change directly transform the object, when you want to retain the value transform the objects parent space.

But..

You still need to allow this approach to be understood by the animator. The offset needs to be understandable, accessible and crucially clean-able!. Any system  that transforms an object by an offset will encounter pops and hitches if the keys of the offset change, get moved or deleted. (Another reason to place them in there own area – attributes etc)

Hiding Transforms in Layers of Abstraction

May 21, 2010

Charles

Don’t do this!

What you see is what you get – that is the rule you need to follow when it comes to getting and setting transforms. When an objects transform is actually an internal transform relative to an internal parent and not its physical one things get very complicated when trying to access them.

If at all possible (this applies to rigging too) when accessing data and there controls, don’t hide data/curves in other data/controls methods. Blending between IK-FK is a clearly defined system; you can see both systems and know when your blending between them.

Generalized ordered systems

February 6, 2010

Charles

Im working on an ordered theory for building rigs and loading animation. This is a general approach that isn’t reliant on rig construction at all, just an paradigm for ordered processes.

‘parent > system > index’

The theory follows some basic strict rules to determine an objects id in a system, and generalize relationship – not in any way its physical parent etc (though i can be used for it). An object is first represented by its parent, then the system its in and finally its index of that system. A root object for example can look something like so:

‘011’ or [0][1][1] or [0]system[1][1] – the first part denotes the systems parent, in this case ‘0’ represents nothing or ‘undefined’, the second part is the system index – in this case its the first system of the rig. Lastly the index denotes that its the first object in that system. Note that the parent index, and the last part ‘index’ and co-habit with each other. This will be explained now:

Once a root/base/first system has been establishes with its id; 011 extending this to cover new relationships is easy. Adding a leg system to this can be referred to as:

011-21

or

parent|system|index| – |system|index|

Reading this id (right to left) we can see its the 1st bone of the 2nd system, which is in turn parented to the 1st bone of the 1st system, which has no parent.

Chains

System can have multiple objects , we just need to determine there index. On creation of a system, an index of 1 always follows as a system or object cannot exist without one or the other. Object represented by an index do not need to be parented – they can if need be, but its not necessary.

Rigging information such as the how the object in the system are setup is purposefully left off, as this is more of a generalized approach than a finite one. Addition information about the system could be held in a’custom’ variable such as #(“leg”, “ikfk”,poleVector”) etc..  This is to allow a system be constructed in any manner we see fit I.e. there maybe a system for the entire leg, or one up to the ankle and another for the foot.  Crucially its dependant on how you want to build your systems.

Construction

Constructing a  system we first build the base system and object, ‘root’ in this case. Addition systems need to know about the system there connected to, and as before this does not need to be a physical parent just a connection to the entire system.

Biotensegrity: The geometry of Anatomy

October 2, 2009

Charles

This is something I’m very interested in, its the study of tensional integrity (Buckminster Fuller) in biology. From an aesthetics point of view it would probably fit in the field of  dynamics – but I’m coming from the standpoint of evolutionary kinematic constraints. Essentially that the notion of our evolutionary movement can only conceivably  end up in our current form. Our wrists, shoulders, hips, spine etc can only work they way they work, because its the only way they can.

Now I’m not including ideas such as being double jointed etc, but from a general standpoint I find the ideas found in biotensegrity a sort of bridging of the mathematical  models we create in rigging and real world biology. We both end up with the same results – e.g. the spine in a tensegrity model and a mathematical one have the same limits, rotation spaces and constraints.

It is said that mathematics is a poor man’s representation of nature – but the fact that it can represent it with enough detail as being real its pretty exciting to me. Tensegrity i find is a beautiful connection between nature and maths.

http://www.intensiondesigns.com/geometry_of_anatomy.html

Encapsulation and incorporation without loss of independence.

July 4, 2009

Charles

No this isn’t about politics, more a case of keeping assets tied to a system, that allows them to be flexible with all departments – animation, tech and art, whilst being editable and exportable en-mass.

The most important factor is iteration. Assets, animation, and rigs will get iterated over time and you need the ability to change and update them whenever.

Assets need to be editable/exportable on mass and externally, to not slow production down. Version control systems generally have a locking process that means if all your assets are on one rig, another user will have to wait for the unlock or submitted changes to get it. Using externally linked or tied resource means, a tech guy can make changes to the file and user needs only to reload the resource back to get changes, even if the users had those assets loaded with the saved scene. Essentially dynamic referencing or passive referencing is crucial.

Animations are gold, and so need to be kept to the highest fidelity when loading them onto another rig. Crucially what needs to be kept between rigs is animation controllers, not bones. A mapping file then only needs to use what it finds to reload the animations back onto a rig.

The rig has to be updatable, and in a non-destructive way to the scene. It needs to get either dynamically changed – controller changes already existing and nodes that get removed and updated attached to the rig; or passively changed – where the entire rig along with everything attached to it gets loaded out and reloaded in with updates.