Question about negative weight inbetween and blendshape docs

Hello,
I’m implementing an importer for blendshapes, but the docs on the negative weights aren’t clear to me.

The docs says:

So at a weight value of -0.25, the shape at 0.25 is applied with a weight of -1.

My understanding is that, that is the case for the example described right before that paragraph which had an inbetweens defined from 0~0.25.
For the pixar’s human female usd sample, it has several inbetweens with weight of -1. For this sample file, is it the case that from weight 0 to -1 I should map to whatever the inbetween has in defined there? or does the math also map those cases to positive numbers as the previous example?

The wording in the BlendShape Schema documentation to me reads as:

NOTE: I think this actually the wrong interpretation.

  • Negative values follow the same ‘inbetween’ state as positive values, but applying their vertex deformation in the opposite direction (= weight of -1)

Say a blendshape has:

  • 0 - no deformation
  • 0.25 - first in-between
  • 0.75 - second in-between
  • 1.0 - implicit primary shape

Then at:

  • a value of -0.25 it has the first in-between (of 0.25) applied with a weight of -1.
  • a value of -0.5 has the first in-between (0.25) and second in-between (0.75) both applied with a weight of -0.5 (it’s directly in the middle of both in the ‘negative weight direction’)
  • a value of -1 has the last blendshape pose applied with a weight of -1.

Basically it lerps between the closest two ‘blendshape’ in-betweens, when in the negative range applying there deformation in the opposite direction.

Whether this interpretation is correct - I’m not sure. :smiley:


or does the math also map those cases to positive numbers as the previous example?

I’m not sure I understand what you’re describing here. Could you explain what that’d look like?

Nevermind - reading you question again I see what you’re basically asking is what it means if a blendshape authors an in-between blendshape position at -1. Which indeed is a very good question.

And if that’s valid authoring (which the documentation doesn’t seem to mention?) I also wonder whether my given example above would be invalid. Then reading this line in the docs:

Finally, if the weight is less than 0.25, we interpolate between the implicit null shape (weight = 0) and the shape at 0.25. Note also that this interpolation is unbounded, so if the input weight is, say, -0.25,

This makes it sound like you’re always interpolation between the two closest indexes (which I think the mathematical function description on the page also tries to explain).

I think this might be the correct interpretation

Meaning that:

With

  • 0 - implicit zero
  • 0.25 first in-between
  • 0.5 second in-between
  • 1 - implicit primary shape

A value of 1.5 would provide the primary shape at a weight of 2?
A value of -0.5 would provide the shape of 0.25 (first in-between) with a weight of -2

And if an authored in-between was at -1 then a value of -1 would mean that particular pose to be at a weight of 1. And at -2 that pose would be at weight 2.


Anyway, very good question. :slight_smile:

@BigRoyNL
Very nice breakdown on the possible scenarios! As you already pointed out, it’s not clear which values we should be using for different values when they are out of bounds. If we were to use the already authored blendshapes, then the offsets would be somewhat similar, but looking at a piece of their sample, we can see that there’s no apparent correlation between the blendshape and the inbetween.

 def BlendShape "HumanFemale_Anim_Face_Mouth_JawSquetch"
{
    uniform point3f[] inbetweens:IBT_0 = [(0, 1.6589397e-11, 1.2343554), (0, 1.6572521e-11, 1.2343554), ...)] (
        weight = -1
    )
    uniform vector3f[] offsets = [(0, 0, 0), (0, 0, 0), (0, 0, 0), ...]
 }

so, for the blendshape above. Is it the case that, for negative weights, do we use the inbetween offset values and for positive weights we use the actual blendshape offset values?

Hello, and thanks for raising this! Venkat on our crowds-dev team did some investigation into this, and reports the following… we’re also going to work on the documentation to improve it. (not sure what’s going on with the boldface in the examples below - please ignore it)

Overall I think what has been described after ‘I think this is the correct interpretation’ is mostly accurate.
From the documentation here are the things that are relevant:
i) The general formula for interpolating in the presence of in-between shapes at any given animated blendshape weight Wi involves determining
a blendshape pair (B_lower, B_upper) to interpolate between.
where ‘lower’ is the index of the blendshape with nearest weight <= Wi
OR
the index of the blendshape with the lowest weight value otherwise. (here I think there is a little inaccuracy in the doc which says
in-between with the lowest value otherwise - this should just be blendshape with lowest value since it may also be the null shape).

Once we find this pair then the offset to apply to a point Pi is found by interpolating between the offsets associated with these two
blendshapes like so:

Offset_i = (1 - alpha)*Offset_lower + alpha * Offset_upper
where alpha = (Wi - Wlower) / (Wupper - Wlower)

This is straightforward to understand if Wi is in the range of the authored blendshape weights. If it lies outside is when this next item becomes relevant

ii) “Note also that this interpolation is unbounded, so if the input weight is, say, -0.25, then we have alpha=-1 :So at a weight value of -0.25, the shape at 0.25 is applied with a
weight of -1.” (This was wrt an example with in-between shapes at [0.25, 0.5] in addition to the null shape at 0 and the primary blendshape at 1).

So applying this information to the example given in the thread response:
Given this blendshape set:
0 - implicit zero
0.25 first in-between
0.5 second in-between
1 - implicit primary shape

If we have blendshape wt (Wi) of 1.5
   lower would correspond to the in-between@0.5 and upper would
   correspond to primary shape@1
   alpha = (1.5 - 0.5)/(1 - 0.5) = 2
   i.e: the offset at the primary shape@1 would apply with a weight of 2 interpolated
   with that at the in-between@0.5 at a weight of -1.

If we have a blendshape wt (Wi) of -0.5
   lower would correspond to the null shape@0 and upper to the
   in-between@0.25
   alpha = (-0.5 - 0)/(0.25 -0) = -2
   i.e: the offset at the in-between@0.25 would apply with a weight of -2

If we have an authored in-between @ -1 in that previous set it would
slot in before the implicit zero.

Then if we have a blendshape wt (Wi) of -1
   lower would be the in-between@-1 and upper the null shape@0
   alpha = (-1-(-1))/(0-(-1) = 0
   i.e: the offset at the in-between@-1 would apply with a weight
   1-alpha = 1

If we have a blendshape wt (Wi) of -2
   lower would be the in-between@-1 and upper the null shape@0
   alpha = (-2-(-1))/(0-(-1) = -1
   i.e: the offset at the in-between@-1 would apply with a weight
   1-alpha = 2

Hope that helps clarify things a little more.

Hi @spiff , thank you for the detailed explanation,
I have a much better understanding of how it works now.
I appreciate your time. Thank you

Hi @spiff ,
Sorry to bring this up again, I was continuing doing some tests and notice some inconsistencies when usdview is animating blendshape weights.

I have attached a sample file with just a box with a blendshape in it. and it has the following weight animation:

float[] blendShapeWeights.timeSamples = {
    0: [-1],
    1: [-0.75],
    2: [-0.5],
    3: [-0.25],
    5: [0, 0],
    7: [0.25],
    10: [1],
}

Scrubbing the timeline I noticed this:

  • Changing from 3 to 4, there’s no visual change on the box.
  • Changing from 5 to 6, there’s no visual change on the box.
  • changing from 7 to 10. there ARE visual changes.

Is it expected that usd does some linear interpolation on some of the time code and does not interpolate on some others?

simple_morpher_box2.usd (4.3 KB)

I think it might be best to file an Issue at this point, please?