jcms are wrong ?

Issue #2073 new
Alessandro Padovani created an issue

4.1.0.2147

This is reported in the daz forum for a specific G9 figure, but in my tests it seems a general issue. The jcms values don’t match with daz studio.

steps:

  1. in the global settings turn off quaternions, so we can use euler to compare with daz
  2. easy import G8F with jcms and flexions
  3. load the same pose in daz studio and blender and compare the jcm values, they are different

Below an example where I bended the left thigh by 70 degrees, for jcmThigh daz studio gets 12.8% while blender gets 0.224 instead of 0.128 as it should be. This is the same with other figures and G9.

Unless I miss something. Let us know.

p.s. I used a clean content folder with only G8 installed, just to be sure there’s isn’t any corrupted figure that unfortunately sometime happens in the daz shop. Also I didn’t use “optimize jcms“ in the global settings, so this is referred to the “standard jcms”.

Comments (12)

  1. Thomas Larsson repo owner

    I can see the difference between DS and Blender, but I don’t understand why. The value of pJCMThighFwd_115_L is given by the formula

    "output" : "Genesis8Female:#pJCMThighFwd_115_L?value",
    "operations" : [
        { "op" : "push", "url" : "lThigh:/data/DAZ%203D/Genesis%208/Female/Genesis8Female.dsf#lThigh?rotation/x" },
        { "op" : "push", "val" : [ -115, 1, 0, 0, 0 ] },
        { "op" : "push", "val" : [ -57, 0, 0, 0, 0 ] },
        { "op" : "push", "val" : 2 },
        { "op" : "spline_tcb" }
    ]
    

    The plugin approximates this expression with a straight line between -57 and -115 degrees:

    clamp(-0.988*A-0.983,0,1)
    

    When A = -1.222 (-70.0 degrees), this expression indeed becomes 0.224. Moreover, it equals 0.0 at A = -57 and 1.0 at A = -115. To get 0.128 the rotation would have to be A = -64.5 degrees,

    So I don’t understand what goes wrong here. Perhaps the spline_tcb driver does something nonlinear, but it is hard to see how to do that with only two defining points.

  2. Thomas Larsson repo owner

    OK, I think I figured it out. The spline is a cubic polynomial, which passes through the points (-57, 0) and (-115, 1) and has zero slope at the endpoints. Let A be the rotation in degrees, and define

    x = -(57-A)/58
    

    Then the spline polynomial

    f(x) = 3*x^2 - 2*x^3
    

    satisfies

    f(0) = f'(0) = f'(1) = 0
    f(1) = 1
    

    If A = -70, x = 0.224 and f(x) = 0.128, which is the value of the driver in DS.

    However, I’m not sure if fixing this is important enough. Adding cubic expressions for spline drivers will complicate things and risk exceeding the 256-character limit for the driving expressions, and the question is if there is a visible difference to the straight-line approximation.

  3. Alessandro Padovani reporter

    If it can help, in #1442 there’s some implementation of keyed and tcb functions using lerp() and smoothstep(), to be verified of course.

    However, I agree a linear approximation to keep expressions simple is good. Of course this way there may be some visible difference in jcm deformations, personally I’m good with it I don’t need to get in blender the exact same deformations as daz. But some advanced users don’t like it.

    One possible way would be to have the linear approximation for “optimize jcms”, then smoothstep() for “standard jcms”. Let us know what you think.

    # daz spline TCB
    
    Key 0:v0
    Key a1:v1
    Key a2:v2
    Key a3:v3
    
    driver = lerp(v0,v1,smoothstep(A/a1)) if A < a1 else 
             lerp(v1,v2,smoothstep((A-a1)/(a2-a1))) if A < a2 else
             lerp(v2,v3,smoothstep((A-a2)/(a3-a2))) if A < a3
    
    if a1=v1=0 the expression is simplified to v2*smoothstep(A/a2) if A < a2
    

    p.s. Or the important thing is this is not a bug but a known limitation, if we want to keep the linear approximation and change nothing. Let us know.

  4. Thomas Larsson repo owner

    I never understood the discussion in the earlier bug report, but now it makes sense to me. Implemented in last commit, although I have only checked the lThighBend115 morph. In Blender 4 smoothstep takes three arguments, so the lerp function is unnecessary. The new driver is

    clamp((smoothstep(1,0,A+2.007) if A<-0.995 else 0),0,1)
    

    and it gives the value 0.119, which is closer to the 0.128 that we get in DS.

    You need to enable the new setting “Spline Drivers”, otherwise the linear approximation is still used.

    The driver works in Blender 4.1 and 3.6, but gives a driver error in Blender 2.83. It don’t think that is a problem, because presumably nobody is using anything less than 3.6 at this time.

  5. Alessandro Padovani reporter

    Commit 6e975df

    Works fine in blender 4.1 and 3.6, seems to work in 2.9 too that’s the latest 2.x LTS.

    note. I don’t think clamp() is necessary since smoothstep() is already limited. Let me know.

  6. Thomas Larsson repo owner

    Then we should be able to skip the last test too. And more generally,

    driver = smoothstep(v0, v1, A/(a1-a0) if A < a1 else 
             smoothstep(v1, v2, (A-a1)/(a2-a1)) if A < a2 else
             smoothstep(v2, v3, (A-a2)/(a3-a2))
    

  7. Alessandro Padovani reporter

    I guess yes, if the ERC keys are limited from v0 to v3.

    p.s. So are we supporting keyed ERCs now, or is this a smoothstep() for non keyed ? Not to push just asking.

  8. Thomas Larsson repo owner

    So far it is only for morphs driven by bone rotations. Morphs driven by sliders, e.g. body morphs, still only use the first segment of the spline and linearizes that. Will look into that later.

    Anyway, there are some bugfixes and optimizations in the last commit. At least all G8 jcms now loads fine. Of special interest are the pJCMForeArmFwd morphs which depend on three spline points. Nevertheless a single smoothstep function is generated in this case, because two of the points have the same value.

    "output" : "Genesis8Female:#pJCMForeArmFwdL?value",
    "operations" : [
        { "op" : "push", "url" : "lForeArm:/data/DAZ%203D/Genesis%208/Female/Genesis8Female.dsf#lForeArm?rotation/y" },
        { "op" : "push", "val" : [ -135, 1, 0, 0, 0 ] },
        { "op" : "push", "val" : [ -75, 0, 0, 0, 0 ] },
        { "op" : "push", "val" : [ 0, 0, 0, 0, 0 ] },
        { "op" : "push", "val" : 3 },
        { "op" : "spline_tcb" }
    ]
    

  9. Thomas Larsson repo owner

    I made some progress on this. Properties driven by other properties can use splines, but bones driven by properties can not. So of the standard body morphs, CTRLFingersFist is driven by CTRLHandFist with splines, but CTRLNeckHeadBend drives the neck bones linearly. Fixing the latter would require a major change in the code which I don’t want to do, at least not now.

  10. Alessandro Padovani reporter

    This is fine I believe the major benefit comes from jcms anyway. We now know that there may be little differences due to tcb interpolation. I’d keep this open as a known limitation together with the others, as reference for people to be aware.

    Thank you for your work on this.

  11. Log in to comment