ValueOperation Codes -What exactly is the maths?



  • Kuroyume's CR2 FileSpec only mentions valueOpDeltaAdd*, and here's whatit says about the deltAddDelta value:

    deltaAddDelta defines the modifier for this dial. Here, I'll quote directly from Kattman's "CR2 Autopsy" to avoid causing conflicting information:
    "A further explanation of this is required so you know why this value is not equal to 1.000 like all other variations on this. In order to actually figure out the value to add to the deltaAddDelta parameter we need to do a little algebriac math. Do a little addition to find the full range, for example if the min is 0 and the max is 12 then the range is 12, if it is -2 and 12 then the range is 14. Lets say the Parent range is 12 and the Child range is 2, build the equation and solve for x using this formula (x beng the unknown deltaAddDelta): 1/Parent Range = x/Child Range. This would give us 1/12 = x/2. To solve for x we have to multiply both sides by 2 giving us 2
    (1/12) = x. solving this equation we get the deltaAddDelta value of 0.167 (always round to the nearest thousandth). To simplify this we could have simply stated: Child Range * (1/Parent Range) = deltaAddDelta."*

    I think I prefer my version ;o)

    *I think the other codes were only added at Poser 8/9?



  • @3dcheapskate it's a terrible shame that document has not been kept up to date. It was a terrific source of information. Nowadays, we get new keywords added to Poser's Python API with just about every release.

    That description is all about how to do calculations to find out what the delta needs to be set to to achieve the desired outputs.



  • @anomalaus Thank you !
    Now that's the sort of stuff that should be in the manual - especially the "...PYTHONCALLBACK is absolutely impenetrable, once it's been set up" ;o)

    If I manually edit the CR2 I'm guessing that I'd need to change valueOpDeltaAdd to e.g. valueOpDividInto, and deltaAddDelta to... errr...



  • This picture is mainly for my own benefit. I added several pairs of dummy parameters named <valueOp>Master and '<valueOp>Slave' to an actor and then added the appropriate valueOp lines to each slave parameter in the CR2.
    0_1549455071420_valueops.jpg

    So do you think we could use several dummy parameters chained together to do a calculation such as...
    4xNx(180-N)/(40500-Nx(180-N))
    ...



  • It appears that we can.
    Here's that sine approximation done with six parameters and seven valueOps (the names of the parameters were to help me when I was manually adding the valueOps):
    0_1549461076157_sine.jpg

    And here's the relevant bit in the CR2:

    
    		valueParm A (angle in degrees)
    			{
    			name A (angle in degrees)
    			initValue 0
    			hidden 0
    			enabled 1
    			forceLimits 0
    			min -100000
    			max 100000
    			trackingScale 0.004
    			keys
    				{
    				static  0
    				k  0  0
    				}
    			interpStyleLocked 0
    			}
    		valueParm 180 - A
    			{
    			name 180 - A
    			initValue 0
    			hidden 0
    			enabled 1
    			forceLimits 0
    			min -100000
    			max 100000
    			trackingScale 0.004
    			keys
    				{
    				static  0
    				k  0  180
    				}
    			interpStyleLocked 0
    			valueOpMinus
    				Figure 13
    				bone_8:13
    				A (angle in degrees)
    			}
    		valueParm A x 180-A
    			{
    			name A x 180-A
    			initValue 0
    			hidden 0
    			enabled 1
    			forceLimits 0
    			min -100000
    			max 100000
    			trackingScale 0.004
    			keys
    				{
    				static  0
    				k  0  1
    				}
    			interpStyleLocked 0
    			valueOpTimes
    				Figure 13
    				bone_8:13
    				180 - A
    			valueOpTimes
    				Figure 13
    				bone_8:13
    				A (angle in degrees)
    			}
    		valueParm 4 x A(180-A)
    			{
    			name 4 x A(180-A)
    			initValue 0
    			hidden 0
    			enabled 1
    			forceLimits 0
    			min -100000
    			max 100000
    			trackingScale 0.004
    			keys
    				{
    				static  0
    				k  0  4
    				}
    			interpStyleLocked 0
    			valueOpTimes
    				Figure 13
    				bone_8:13
    				A x 180-A
    			}
    		valueParm 40500 - A(180-A)
    			{
    			name 40500 - A(180-A)
    			initValue 0
    			hidden 0
    			enabled 1
    			forceLimits 0
    			min -100000
    			max 100000
    			trackingScale 0.004
    			keys
    				{
    				static  0
    				k  0  40500
    				}
    			interpStyleLocked 0
    			valueOpMinus
    				Figure 13
    				bone_8:13
    				A x 180-A
    			}
    		valueParm 4A(180-A) / 40500-A(180-A)
    			{
    			name 4A(180-A) / 40500-A(180-A)
    			initValue 0
    			hidden 0
    			enabled 1
    			forceLimits 0
    			min -100000
    			max 100000
    			trackingScale 0.004
    			keys
    				{
    				static  0
    				k  0  1
    				}
    			interpStyleLocked 0
    			valueOpTimes
    				Figure 13
    				bone_8:13
    				4 x A(180-A)
    			valueOpDivideBy
    				Figure 13
    				bone_8:13
    				40500 - A(180-A)
    			}
    

    The value of 'A (angle in degrees)' is the ONLY dial you twiddle - the others are predefined constants.



  • @3dcheapskate excellent! I'd done sine and cosine as valOpKEY over 720 degrees in 10 degree steps, but an approximation like yours would eliminate the huge key, value tables and get rid of the locked output when the key is out of the two revolutions range. Can you give an estimate of what level of accuracy that approximation delivers? Poser's rotation dials are only sensitive down to 0.01 degrees. You can't enter smaller increments of angle than that. I assume that such limits were a tradeoff for calculation speed, but it's really hard to get accurate pointing for something more that a few metres away in the scene, without finer angular resolution.

    There are other things it's sometimes* fun to try to do with valOps, but I was never successful at performing modulo arithmetic without giving up in disgust. I've always felt it should be possible, but usually resorted to a Python callback.

    Python callbacks, provided you are the one who installs and maintains them, are very useful for doing things like extracting Euler angles from an actor's rotation matrices (provided you remember to account for the scale hierarchy of the actor!) That way I can have a magnet simulate an actor affected by gravity, which gives more control (via manipulation of the zone and weightmaps) than simply using PointAt on an actor targeting a Nadir prop.



  • @anomalaus The equation was the first one that came up when I Googled sine approximation - Bhaskara I's sine approximation formula. A spreadsheet of 1 degree steps comparing spreadsheet sine function with the approximation, gives a difference of between 0.0001 and 0.0016 with an average of about 0.00140. The larger errors are in four clusters around 12, 55, 130, and 168 degrees.



  • @3dcheapskate thanks, and just complement the angle for cosine, eh? "You stupid angle!" returns NaN, of course ;-)

    I remember reading one of @bagginsbill 's Rendo threads where he'd come up with a trig approximation that was better (consistently more accurate) than one of the famous ones, but since he wasn't famous, nobody else knew about it. I think it related to polar coordinates, maybe?


  • Poser Ambassadors

    Yep and I also found a superior Fresnel approximation than Shlick's. Computers are wonderful things and they will tirelessly search for a needle in an infinite haystack. Being a programmer is fun.



  • But from a practical viewpoint - infinite haystacks are not! :-)