# Using a Parameter Dial to select which face of a PP2 die (dice) is upwards ?

• Back to barnardino's suggestion. I've used valueOpDeltaAdd and deltaAddDelta stuff occasionally (and a long time ago) following the principles of Nerd3D's 2005 Extended Motion Control http://www.nerd3d.com/modules.php?name=Content&pa=showpage&pid=8 , so I'm sort-of familiar. But I thought that it was only possible to make a master/slave dial pair work in a linear fashion? E.g. if the master is my 'UpwardFace' dial (with values 1, 2, 3, 4, 5, 6) and the slaved x/y/zRotation dial has a 'slavingfactor' (I know that's not what it's called, but you know what I mean) of 90 then I thought the x/y/zRotation dial could only be made to work in the same linear fashion as the master, i.e. 1->90, 2->180, 3->270, 4->360, 5->450, 6 ->540.

If by 'keyed' delta adds and 'keyed' valueops you mean that there's a way to apply arbitrary values to the slave dial for each value of the master dial, then that's the solution I'm after! Working out the three rotations required for each face of a 20-sided dice to be 'up' is something I'd be willing to do (I'd use trial and error dial-twiddling rather than try and calculate them) since it would only have to be done once and I could hard code the values into the PP2.

I assume that the keys you're referring to are something to do with the key{} sections in the x/y/zRotate bit of the PP2? (I've never used them and am completely in the dark about what they do) Edit: looking at Kuroyume'sCR2 spec I see that it's to do with animation,so that may not be what you're talking about:

``````	rotateY yRotate
{
name yrot
initValue 0
hidden 0
forceLimits 0
min -100000
max 100000
trackingScale 1
keys
{
static  0
k  0  0
sl  1
spl
sm
}
interpStyleLocked 0
}
``````

Further enlightenment requested please !

• @3dcheapskate "keyed" refers to valueOpKey value operations, which add a discrete value to the output for each specified input key, unlike the valueOpDeltaAdd which is a linear interpolation without specific endpoints to its effect, other than the output parameter's own limits.

Here's an example with the Lunariad 6 sided die, which has the numbers physically modelled into its surface and opposite sides add to 7 as per standard, gambling dice.
The rotation order for this prop is XYZ, which is important, as one can generally avoid gimbal lock by never modifying the middle rotation.
So, after creating a new Master Parameter called 'Roll', and setting its limits to 0 and 6 and sensitivity (trackingScale in the poser .pp2 sample below) to 1, and using the Poser Pro Edit Dependencies function, I can select the simplest rotations which get the required die face uppermost to match the value of the Roll parameter.

This is the relevant section of the prop after I save it back to the library:

``````		rotateX xRotate
{
name xrot
initValue 0
hidden 0
enabled 1
forceLimits 0
min -100000
max 100000
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
valueOpKey
_NO_FIG_
6 side
Roll
strength 1.000000
beginValueKeys
valueKey 0 0
valueKey 1 -90
valueKey 2 -180
valueKey 3 -90
valueKey 4 -90
valueKey 5 0
valueKey 6 -90
endValueKeys
}
rotateZ zRotate
{
name zrot
initValue 0
hidden 0
enabled 1
forceLimits 0
min -100000
max 100000
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
valueOpKey
_NO_FIG_
6 side
Roll
strength 1.000000
beginValueKeys
valueKey 2 0
valueKey 3 90
valueKey 4 -90
valueKey 5 0
valueKey 6 -180
endValueKeys
}
valueParm Roll
{
name roll
initValue 0
hidden 0
enabled 1
forceLimits 1
min 0
max 6
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  4
}
interpStyleLocked 0
}

``````

NOTE: the default orientation of the die had 5 on top, so you see that when Roll is 5 (or 0), both rotations are 0. ZRotation isn't changed at all until you Roll from 2 to 3.

• Thanks anomalaus, that seems to do the trick - I've just tried it for the first five numbers on a 20 sided dice and it's looking good.

A couple of queries though:

1. I'm creating the dependencies in PP2014.The resulting PP2 works in Poser 9, but in Poser 6 the master dialdoes nothing. I assume that's because the valueOpKey wasn't introduced till Poser 7/8/9 ? Can anybody confirm that, and confirm which version it was introduced in ?

2. "...one can generally avoid gimbal lock by never modifying the middle rotation..." - I can't recall how to tell the rotation order for a prop ? Is it the order in which the rotatex{}, rotatey{} and rotatez{} datablocks appear in the PP2 ?

• @3dcheapskate that's all pretty much correct.

It is possible to emulate valueOpKey prior to Poser 7, but I can't run anything older that Poser 2010 on my iMac as Apple orphaned the older software entirely.

It's quite a bit more complicated, but if you use two hidden valueParms driven by valueOpDeltaAdd per Roll value, one of which follows roll by an increasing decrement, i.e. roll -1, roll -2, etc., with an upper limit of 1 and a lower limit equal to its initial negative offset, to delay the onset of that roll value and the other, with limits of 0..1 which records when roll reaches each value and is then turned off again, by roll reaching the subsequent values.

``````		rotateX xRotate
{
name xrot
initValue 0
hidden 0
enabled 1
forceLimits 0
min -100000
max 100000
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll1
strength -90
_NO_FIG_
6 side
Roll2
strength -180
_NO_FIG_
6 side
Roll3
strength -90
_NO_FIG_
6 side
Roll4
strength -90
_NO_FIG_
6 side
Roll6
strength -90
}
rotateZ zRotate
{
name zrot
initValue 0
hidden 0
enabled 1
forceLimits 0
min -100000
max 100000
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll3
strength 90
_NO_FIG_
6 side
Roll4
strength -90
_NO_FIG_
6 side
Roll6
strength -180
}
valueParm Roll
{
name roll
initValue 0
hidden 0
enabled 1
forceLimits 1
min 0
max 6
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  4
}
interpStyleLocked 0
}
valueParm Roll-0
{
name roll-0
initValue 0
hidden 1
enabled 1
forceLimits 1
min 0
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll
strength 1.000000
}
valueParm Roll1
{
name roll1
initValue 0
hidden 1
enabled 1
forceLimits 1
min 0
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll-0
strength 1.000000
_NO_FIG_
6 side
Roll2
strength -1.000000
_NO_FIG_
6 side
Roll3
strength -1.000000
_NO_FIG_
6 side
Roll4
strength -1.000000
_NO_FIG_
6 side
Roll5
strength -1.000000
_NO_FIG_
6 side
Roll6
strength -1.000000
}
valueParm Roll-1
{
name roll-1
initValue -1
hidden 1
enabled 1
forceLimits 1
min -1
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  -1
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll
strength 1.000000
}
valueParm Roll2
{
name roll2
initValue 0
hidden 1
enabled 1
forceLimits 1
min 0
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll-1
strength 1.000000
_NO_FIG_
6 side
Roll3
strength -1.000000
_NO_FIG_
6 side
Roll4
strength -1.000000
_NO_FIG_
6 side
Roll5
strength -1.000000
_NO_FIG_
6 side
Roll6
strength -1.000000
}
valueParm Roll-2
{
name roll-2
initValue -2
hidden 1
enabled 1
forceLimits 1
min -2
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  -2
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll
strength 1.000000
}
valueParm Roll3
{
name roll3
initValue 0
hidden 1
enabled 1
forceLimits 1
min 0
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll-2
strength 1.000000
_NO_FIG_
6 side
Roll4
strength -1.000000
_NO_FIG_
6 side
Roll5
strength -1.000000
_NO_FIG_
6 side
Roll6
strength -1.000000
}
valueParm Roll-3
{
name roll-3
initValue -3
hidden 1
enabled 1
forceLimits 1
min -3
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  -3
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll
strength 1.000000
}
valueParm Roll4
{
name roll4
initValue 0
hidden 1
enabled 1
forceLimits 1
min 0
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll-3
strength 1.000000
_NO_FIG_
6 side
Roll5
strength -1.000000
_NO_FIG_
6 side
Roll6
strength -1.000000
}
valueParm Roll-4
{
name roll-4
initValue -4
hidden 1
enabled 1
forceLimits 1
min -4
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  -4
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll
strength 1.000000
}
valueParm Roll5
{
name roll5
initValue 0
hidden 1
enabled 1
forceLimits 1
min 0
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll-4
strength 1.000000
_NO_FIG_
6 side
Roll6
strength -1.000000
}
valueParm Roll-5
{
name roll-5
initValue -5
hidden 1
enabled 1
forceLimits 1
min -5
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  -5
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll
strength 1.000000
}
valueParm Roll6
{
name roll6
initValue 0
hidden 1
enabled 1
forceLimits 1
min 0
max 1
trackingScale 1
masterSynched 0
keys
{
static  0
k  0  0
}
interpStyleLocked 0
_NO_FIG_
6 side
Roll-5
strength 1.000000
}
``````

The rotation parameter order in the file is the ultimate definition, but you can check, since parameter groupings can hide the actual calculation order, by opening the joint Editor palette (Cmd/Ctrl-Shift-J) and it is displayed there.

• Ouch!

I just looked: that's 480 lines of dependencies code for the six-sided die only :O

And, since animation w/ bullet physics was mentioned earlier:

You can't control which side ends up top (after all, that's the intended purpose of this thread).
But all calculations and dependencies only work properly from zero position of the prop!
So before you're able to dial in the number, you first have to zero the prop (e.g. bring the correct default number back to the top face), meaning to make offset calculations necessary depending on the current rotation values.

Also remember that your die won't land exactly aligned rectangular in the y axis!
So before recalculating your x and z rotations you first must set the "y" rotation back to zero (but you first have to find out which axis of the die actually aligns with the Unverse's y axis).
After you've dialed the right number on top you have to find out again which axis of the dial aligns with the Universe's y axis, and then rotate the die back to the original y orientation it had as it fell...

Though I believe it still can be done for a six sided die (though probably with another 500 lines of code), I doubt that it could be done with any reasonable amount of dependency calculation on a 20 sided die because you not only encounter 90 degree rotations there, but also odd angles in between: and then hell opens up!

While I DON'T doubt that a mathematician would be able to calculate all the rotations necessary, I definitely predict that it's far from what you can do with Poser's dependent parameters. Maybe a python script, yes.

Finally, about the idea of doing it with morphs:

That could be done eventually (provided you solve the problem of realigning the die properly after it's tossed and landed with a different orientation).

--> But then, morphs work linearly:
:---------------------------------------------------------:
You can't simulate rotations with a morph, because the vertices will move to the new destination in a straight line. So "morphing" a 180 degree rotation would only mirror the prop relative to the rotation axis: Top planes will move to bottom, and bottom plane will move to top. Normals will thus be inverted too.
The side planes would be turned upside down instead...

B.t.w., did anybody dig into the possibility of using "altGeom" instead?
I didn't try yet and don't want to because I only played with it a few times before, so I'm no expert.

In the end it's all a question of "why do you need this" vs. doing it manually with Poser's "Direct Manipulation" Gizmo vs. the system load of three poor dice with 1000+ lines of code each.

However, it's an interesting challenge; curious of what else ideas you come up with.

K

EDIT:
I still can't figure out how a 20 sided die would look like. Anybody has a model which he can share? (Or at least a picture)
Thank you.

• @anomalaus - that's the sort of solution I was originally thinking of, but I just couldn't see how to get something like that to work. I'll have to look through your code a few times to make sure I'm clear, and I'll give it a try. Poser 6 runs on my system, so that'll be my test.
And I knew I'd seen the actual rotation order displayed somewhere on the UI, but convinced myself I was thinking of DAZ Studio. So it's the Joint Editor pane.

@karina - Regarding "why do you need to do this" - I recently did a render of a role-playing game in progress ( https://www.daz3d.com/forums/discussion/comment/2873211/#Comment_2873211 ) using a freebie set of RPG dice ( https://www.sharecg.com/v/58467/browse/11/Poser/RPG-Dice-v1.0 ). I wanted to change the up-face on each die, but realized that I'd have to manually adjust the rotations of each. As a user I thought "having a parameter dial to set the up-face would be great". Then I started looking at how to do it, and here we are!

While a couple of thousand extra lines of code in the PP2 for a 20 sided die is a lot, if that allows me to easily select which face is up (for a single frame still image) without having to fiddle with the rotation dials individually then the overhead's acceptable for me.
And I'm not really concerned about the die being aligned with the axes, just which face is uppermost. So that's not a concern for me either. Although if I wanted to rotate the die around the y-axis once I'd selected the face that's uppermost, then that does become a concern.
Animation and bullet physics was introduced in bagginsbill's comment - it hadn't even crossed my mind (I never do animation). I like bagginsbills animated material parameter solution for this, although as pointed out earlier the face numbering changes dependant on the up-face selected.

A separate PZ2 file for each number is also a good option, but if the user wanted to y rotate (in world axes) the die then they still have to manually fiddle with the three rotations.

Considering morphs or altgeom I guess (even though I know nothing about it) that both of those should work with bullet physics animation. To me altgeom (if it's possible) would make more sense than morphs. I haven't tried eitheryet.

• @karina A 20 sided die would probably be somethng like an icosphere.

• Yep that's it - real world icospheres/icosahedra ! They have a wonderful feel to them.

• @karina Yes, it's a lot simpler with valueOpKey.

I would suggest that any physics animation be done with a render-invisible wireframe object of the desired shape and then interpose a grouping object (in P11) or other dummy prop (pre P11) between that and the final render object as child actors to de-couple the rotations and eliminate gimbal lock entirely. If the middle rotation is done on the grouping object/dummy prop (and can be driven by valueOperations from a dial on the visible die) then the other two axes can never coalesce and will always be orthogonal.

Fully agree about the morphs. Linear interpolation can never substitute for actual rotations.

AltGeom, unfortunately, is absolutely nicht und verboten on unimesh figures. Replace parent with prop is the way to do that with unimesh, though I've not tried. I usually just animate the visibility of the parts I want replaced and drive those parameters with valueOpKey.

Thanks @3dcheapskate for the links.

• I would suggest that any physics animation be done with a render-invisible wireframe object of the desired shape and then interpose a grouping object (in P11) or other dummy prop (pre P11) between that and the final render object as child actors to de-couple the rotations and eliminate gimbal lock entirely. If the middle rotation is done on the grouping object/dummy prop (and can be driven by valueOperations from a dial on the visible die) then the other two axes can never coalesce and will always be orthogonal.

This sounds a good approach. I recall having problems saving (or deleting) a 'parent prop + child prop' combination - only one of the two props was saved/deleted. I think there was a certain technique required to get it to work (maybe involving manually editing the PP2) ?

...AltGeom, unfortunately, is absolutely nicht und verboten on unimesh figures...

But the dice aren't unimesh figures - they're props. I had a look at Kuroyume's CR2 spec again and it seems to indicate that altgeom works on props (edited extract below). So altgeom definitely seems to still be an option - not necessarily a good one though.

``````actor|prop|hairProp <part name>:<character number>
{
name <name|GetStringRes(1024,<int>)> <on|off>
...
[alternateGeom <name>
{
}
... more alternateGeom sections
defaultGeomName GetStringRes(1037,N)]
channels
{
}
...
}
``````

• @3dcheapskate you are absolutely correct about the irrelevance of unimesh to props. I was only mentioning it as when I finally got to the point of deciding to just subdivide all the figures and clothing I was using, I ran across the necessity to convert them all to unimesh as a prerequisite for subdivision (again only relevant to figures) which A) immediately broke every piece of altGeom I was using on those figures, and B) even broke one of the figures whose geometry was so disconnected in places its UV mapping broke if subdivided at all.

IIRC, Kuroyume's document came out before unimesh became an option in Poser and hasn't been updated since. Poser certainly deprecates and purges all of the GetStringRes() references when saving to the library. Pity SMS don't publish a specification of the file formats the way DAZ at least attempted to do with DSON. At least then one could compare the specs and see what won't be supported in older versions of Poser.

• Had an hour to while away today so I made the pose files for the D6 die.
A nice extra is that the die will keep it's rotation around the y axis because it sets the orientation according to the rotations.
The pose files for other die types would look exactly the same, just different rotation values of course.

For the poses to work correctly the original geometry must have the "3" facing upwards and the "6" on the front (z+) side. If your prop has a different orientation, change it with the Joint Editor.

EDIT:
I can't get the file to upload; any ideas?
Is it allowed to link to external hosting?

• @karina yes, external links are the way to go. I use mega.co.nz, which is free, but others will work as well.

• Thank you anomalaus!

I just returned from the weekend at *** and try to catch up.

I'll upload the dice to "Zippyshare" which IMO is the best (and works with TOR too).

However I still have a few questions to be answered.
The main problem is about "animated" bump and displacement nodes, which shall follow the die's scale in order to keep relative values:
"Bump/Disp values coupled to actual scale of die".
So if you scale the die the default value will be adjusted according to the set scale automatically.
It woks as intended as long as you load the original prop.

But as soon as you try to apply a different texture (no matter whether it's .pz2, .mt5, .mc6 : It just discards the dependencies (PP2014 SR3)

I found a workaround, but it's still acting strange (sometimes you'll have to click the MAT file TWICE to make the dependencies work!).
Still fiddling with it.

I'll be more specific once you have my version of the dice for download, so, laters.

Tomorrow!
I'm a tad tired tonight ...

K

• @karina yes, in PPro2014 the first application of an animated material clears the dependencies and the second re-applies them. Weird. I also notice that dependencies tend not to get saved or apply properly from .mt5, while they do save and work better from material collections, at least in P11. There are other features which require double application to work properly, like workspace layout dots when one has dual monitors. It takes a second click on the dot to move things like the Raytrace Render Preview window back to the second monitor.

Scale is an especially problematic property in Poser. I had to resort to creating my own, hidden UnitScale parameter which I set appropriately with a python script by reading Poser's own preferences file. In that way, I can have non-translation parameter dials (which automatically display in the preferred units) containing measurements like depth of field or focus distance for cameras by dividing their internal value by the UnitScale (1 for PNU, 2.62128 for metres, etc), so when they're saved to the library, they are forced into PNU as happens with the translations. Oh, that reminds me, I need to request that feature from SMS: a way to define parameter dials as using display units.

• Thank you for the insights anomalaus.

In fact I've encountered some of the same problems (and others), but gladly I could solve most, or at least figure out a workaround.

In this example I've got the problem of the dice's yRotation solved by just realigning the xyz orientation after "tossing the dice".
So now the procedure is straightforward:
Load the die, make it show your desired number on top with the injection, and you have a die without gimbal lock, and all axes reset as they should be.

However one thing still makes me lose my hair:

Scaling with bump/displacement values automatically adjusted by shaderNodeParms!
With just one prop in the scene it works fine.

The problems start when you change the texture (per .mc6 injection)
and it gets worse when you load a second die into the scene:
"Posing" the numbers works fine, as well as applying a different texture.
Unfortunately the shaderNodeParms now go totally bonkers (also see below in the copy of the ReadMe file).

This is definitely something that SM must work on!

http://www68.zippyshare.com/v/kCPGXlBa/file.html

=================================================

NOTE:

THIS IS NOT FOR REDISTRIBUTION, only testing purposes!

For easier testing I kept all necessary files in one folder structure;
put this folder where you like.

DESCRIPTION:

A simple prop made from a primitive because the die in the link
https://www.sharecg.com/v/58467/browse/11/Poser/RPG-Dice-v1.0
has a crazy polycount (10.000something).

The die comes with improved textures for the dots and displacement map.
The UV layout is the same as in the other dice so that you can swap
texture maps to your liking.

After loading the die is exactly one metre large, to facilitate
finding it at all, and for quick testing purposes.

If you want a die of 1.5 cm, set the Scale(xyz) to 1.5 per cent.
The bump and displacement values will be scaled accordingly when you
change the Scale(xyz) dial.
This was achieved by "animating" the dials in the Material Room.

There's a set of poses included to bring the clicked die face on top while
preserving the current orientation and rotation of the y axis.
This is achieved by realigning the prop's orientation.

Use the RESET GEOM pose to zero all rotations and restore
the original orientation.

PROBLEMS:

You can choose from six different colours for the die.
However, there's a problem with Poser when injecting these any of these:
The "animated" dials for Bump and Displacement behave very strange.
Sometimes you have to click the texture twice to restore the dependency.

Another Poser weirdness:
When I have more than one die in the scene, Poser always reads the scale
value of the first die loaded and propagates it to the "shaderNodeParm"s
of the other dice loaded later.

I think the problem is in the code of the shaderNodeParms:
valueOpTimes
NO_FIG
Die 6-sided:1
Scale

I suppose Poser doesn't recognize and upcount the :1 counter in line #3.

I really wish Poser would adjust such critical values like Bump and
Displacement automatically with the scale of the figure or prop.
Could save people a lot of headaches and bad surprises.