16 comments on “Corrective shape extraction from the inverse transformation of a skincluster

  1. Really trying to understand the maths of taking the target back into the bind space – making my head hurt. How do you deal with weights?

    • I have just tried to do really basic thing: in my setup corrective shape are supposed to be additive and I wrote a node to trigger each pose weight sequentially( a kind of spherical coordinate but wrap around my preference ). @math : Is the current pseudo code with matrix concatenation readable?

  2. Sort of, I kinda get you have to transform the target into the space of the bind – I just don’t know how you include the weights. I need to think on this overnight. I’m thinking much broader in terms of n-space dimensions. Just stuck on getting a target pose into the bind space.

    • Ok, my brain cracked like a coconut on the walk home and I understand it now hopefully! – Basically an transform inverse of the weighted joints transforms multiplied into the bind pose.

      Thanks for you help, i’ll try and post some results.

  3. How are you creating this value: ( currentJointBindPose* currentJointTransformation * currentJointweight ) ?

    Do you break the transforms into rotation and translation, sum there weights accordingly then add them back as matrices? e.g

    A + B

    r0 = slerp a.rotation (quat 0 0 0 1) jointWeight
    t0 = a.worldtranslation * jointWeight

    (r0 as matrix3) * transMatrix t0

    ?

  4. Not really, this a the most shameful type of interpolation: just weighted vector addition . lets say that your vertex is rigidly bind to a joint , the final transformation of a vertex is defined by multiplying each vector by its weight and adding the vector together. Hence the name linear vector blending which is much more evocative than linear blend skinning or smooth skinning…

  5. Perfect, Its just basic vector and matrix, but once you play with it there is no turning back( as your already know ). I was digging last time in comet pose deformer / reader source code but I have a hard time on the radial basis function used to blend poses together. Tweaking curve or interpolation range is kind tiring. Do you deal also with lots of corrective shapes?

  6. We’ll the math is super hack-tastic currently – but it works! As for blending i’m really thinking about n-dimensional space (eigenSpace). With the upper arm you really have a n-space of 6d (+x/-x … -z) – interpolation can be any type (cubic, ease-in etc) and its naturally non-linear. Crucially poses can exist at any point this space.

    Poses can also be absolute when you include zero position dimensions. For the shoulder you can essentially break the space into two chunks: direction and spin – if you treat these as your dimensions* your really only doing 1st and second order poses. I.e pose == direction + spin.

    N-space math is awesome – simple yet brain crunchingly complex!

  7. yet its just to complex for me for the time being, thus I tried to do a brute force simple stupid linear interpolation: divide space into thinner sector until an acceptable error margin is reached…

    Even now my system is based on one postulate: removing spin/twist from the equation: instead of default twist for an articulation I provide a database of state that convey the most logical default pose for a limb.

    Without twist shapes , with sectors spanning over 30 degrees in front/rear, up/Down for the arm and shoulder I am already dealing with 164 shapes and If I add 8 shape per pose to cope for twisting ,it will fatten this number exponentially .

    What i want to achieve is a way to handle robustly corrective shapes creation/maintenance .
    at a pose a corrective shape is a result of several repetitive factor that can be reused and described individually: muscle repelling each over , sliding over hard surface, etc…

    In maya or max several tool can do the job( like muscle smart collide, point relaxation etc )but I just find they are too generic.I strive for something like a knuckle deformer or a hip module: a suite of tool which can be use from classic toon to anatomical coherent creatures.

  8. PSD

    For the basic data flow, i think i’ll store the vertex positions, there associate bone ids, world transforms and weights offline – or into an attribute. I’ll get the inverse bind pose of the current pose, sculpted pose and do a basic corrective math now that its back in world space:

    (vertexWorldPos + sculptedPoseBind) – (vertexWorldPos + currentPoseBind)

    This way its analogous to any corrective system – only that i’m putting it back into world space. I don’t have to worry about what poses went into the current ‘state’ of the mesh.

    N-Space

    As to n-dimensionality crucially the thing to remember is a pose is a product of the dimensions that go into it. And this product of result of the position placed on the weight. I have more on this on my blog.

    As to automatically building a corrective or 2nd, 3rd, 4th order etc pose – it would be tricky. You could definitely build a ‘generic’ crease, mass shift builder sort of how Face Robot defines creases using vertex color.

    You not dealing some much a rubber tube that always creases the same way – human tissue, muscles etc act in complex ways based on the hierarchic they moved in.

  9. Interesting post as usual . For the implementation I choose to reverse the world sculpted pose target as my goal was to deal with only 1 regular blendshape deformer working before a skinCluster.

    @storing useful data: yeah i tried that also: first I use matrix attribute, message connections and even dagPose node.

    What I have in mind was not to have procedural/automatic corrective shape: to build these shape even with different design we have essentially the same type of phenomenon( then it just how far we want something intricate or not ), and the workflow is always the same: put into pose try to sculpt a good shape by pushing points, using other deformer and maybe relaxing some point.

    My goal is to store this step in an agnostic manner.

    Let say when you bent your arm over 120 degrees, you can define a line deformer to control the inner flesh crease, reuse a kind of lattice to push the flesh on the side, isolate in the view a set of vertices /face to better understand the form your are working on, or relax a region by not painting weights but rather defining a gradient from 4 corners attributes.

  10. First of all, thank you for your fantastic blog. :)
    You can’t imagine how much your work is inspirational for me.

    I’m creating a corrective shape extractor for max and I’m stuck, it’s driving me crazy!
    I think I’m pretty comfortable with vector math but I’m wasn’t able to negate skinning deformation.

    I assume that you do this when you multiply a matrix ( I hope I got it! :-/ )
    (
    fn multiplyMatrix Mat val =
    (
    resPos = Mat.position * val
    resRotation = slerp (quat 0 0 0 1) Mat.rotation val
    resMat = resRotation as matrix3
    resMat[4] = resPos
    return resMat
    )
    )

    With a practical example, here’s what I understood:
    Say I have an vertex assigined to UpperArm and LowerArm with weights 50/50

    // the skinning process
    vertexBindPosition = [x,y,z]
    In bind pose
    (
    UpperArmBindPose = UpperArm.transform*inverse(UpperArm.parent.transform)
    ForeArmBindPose = ForeArm.transform*inverse(ForeArm.parent.transform)
    )
    In Pose
    (
    UpperArmTransformPose = UpperArm.transform*inverse(UpperArm.parent.transform)
    ForeArmTransformPose = ForeArm.transform*inverse(ForeArm.parent.transform)
    )
    //matrices from bind pose to pose to correct
    UpperArmDiff = UpperArmTransformPose*inverse(UpperArmBindPose)
    ForeArmDiff = ForeArmTransformPose*inverse(ForeArmBindPose)

    skinnedVertexPosition = ( (vertexBindPosition*inverse(UpperArm.transform)) * (multiplyMatrix UpperArmDiff 0.5) * UpperArm.parent.transform) +
    ( (vertexBindPosition*inverse(ForeArm.transform)) * (multiplyMatrix ForeArmDiff 0.5) * ForeArm.parent.transform)

    // now reverse things
    correctedVertex = [x,y,z]

    correctedVertexInBindPose = (correctedVertex*inverse(UpperArmTransformPose)) * (multiplyMatrix (inverse(UpperArmDiff)) 0.5) * UpperArmTransformPose +
    (correctedVertex*inverse(ForeArmTransformPose)) * (multiplyMatrix (inverse(ForeArmDiff)) 0.5) * ForeArmTransformPose

    Where I’m wrong??!

  11. A useful read! Adapted a similar method for my own pipeline scripts with the help of yourself and a few other sources. One question, did you ever look into making correctives for meshes with DQ weighting added on top of the linear weights?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s