kValueOpTypeCodeDELTAADD

kValueOpTypeCodeDIVIDEBY

kValueOpTypeCodeDIVIDEINTO

kValueOpTypeCodeKEY

kValueOpTypeCodeMINUS

kValueOpTypeCodePLUS

kValueOpTypeCodePYTHONCALLBACK

kValueOpTypeCodeTIMES

The deltaAddDelta is the only one I've used. I know that code in the CR2 snippet below will add (36 times (the 'Open Book' dial value on the BODY of 'Figure 4')) to the zRotate value of bone_4:4

```
actor bone_4:4
{
...
channels
{
rotateZ zRotate
{
...
valueOpDeltaAdd
Figure 4
BODY
Open Book
deltaAddDelta 36.000000
...
```

Can somebody enlighten me about what the maths is for each of the others -i.e. if I simply changed *valueOpDeltaAdd* to *valueOpPlus*, etc in the code snippet above. (other changes will be necessary too,I know)

This mildly useful information doesn't appear to be in the manual...

]]>kValueOpTypeCodeDELTAADD

kValueOpTypeCodeDIVIDEBY

kValueOpTypeCodeDIVIDEINTO

kValueOpTypeCodeKEY

kValueOpTypeCodeMINUS

kValueOpTypeCodePLUS

kValueOpTypeCodePYTHONCALLBACK

kValueOpTypeCodeTIMES

The deltaAddDelta is the only one I've used. I know that code in the CR2 snippet below will add (36 times (the 'Open Book' dial value on the BODY of 'Figure 4')) to the zRotate value of bone_4:4

```
actor bone_4:4
{
...
channels
{
rotateZ zRotate
{
...
valueOpDeltaAdd
Figure 4
BODY
Open Book
deltaAddDelta 36.000000
...
```

Can somebody enlighten me about what the maths is for each of the others -i.e. if I simply changed *valueOpDeltaAdd* to *valueOpPlus*, etc in the code snippet above. (other changes will be necessary too,I know)

This mildly useful information doesn't appear to be in the manual...

]]>python, poserpython, valueop ]]>

TIMES, DIVIDEBY and DIVIDEINTO are simply multiplication by a factor, division by a factor, and division of a factor by the parameter value. Divisions can, of course have undefined asymptotes (Can't divide by zero).

KEY has limitations in its interpolation. With only two key, value pairs defined, it is linearly interpolated, with the output value locked to which ever endpoint value is closest if the input is outside the specified key range.

At 3 key value pairs, KEY is probably a quadratic interpolation. Beyond that, the interpolation is unspecified and undocumented. I once tried using the NumPy package to interpolate splines based on the key, value pairs, but I did not get exactly the same values (using the NumPy.Interp1d() method). I had been attempting to calculate inverse functions for the valueOperations prior to the implementation of the parameter.UnaffectedValue() method in Poser's Python API, so that I could determine actual parameter dial values, rather than the value resulting from valueOperations or conforming, prior to saving a pose, so that reapplying the pose would not double parameters which had valueOperations applied to them.

Currently, there is absolutely no reason I can fathom why you would ever need or want (other than curiosity) to use MINUS or PLUS. DELTAADD does both of their functions perfectly well.

PYTHONCALLBACK is absolutely impenetrable, once it's been set up. A python script will be called to update the parameter value, whenever parameters normally get updated, though the conditions under which the python script may change the value can be modified. The only possible operation in this case (all of the other valOp types can have their parameters and factors or key-values inspected and changed) is to clear the callback so it ceases to update the parameter. If the callback was set up by some third-party add-on, you can't even re-instate it if you need to temporarily disable updates.

There is one more, major complication to the maths involved: Parameter limits. Regardless of what a DELTAADD, etc valOp says the output value should be, if the parameter has limits applied, the value will be constrained to those limits (another disastrous possibility if one is trying to calculate an inverse function: discontinuities). The point at which limits are applied is also undocumented, but appears to be at the end of all of the valueOperations applied to a parameter, rather than after each one (this could possibly change the calculated result!).

]]>*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?*

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.

]]>Now

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

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))

...

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):

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.

]]>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.

]]>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?

]]>