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

• I have a PP2 model of a simple six-sided die* (dice if you prefer) and I want to provide a simple way for the end Poser 6+ user to select which face is upwards. To manually do this the user would adjust the x or z rotation in 90 degree steps**

My first thought is to have a parameter dial that can be set to 1, 2, 3, 4, 5, or 6. But I can't see a sensible way to use that to set the required rotations - iirc dials can only control other dials via deltaAddDelta (or something like that).

Here are some things that came to mind:

1. Geometry swapping - a separate geometry for each number seems a bit overkill, especially when you consider the icosahedral die. And anyway, does geometry swapping even work with props?

2. UV mapping to a 6x1 rectangle with the numbers in a single row and modifying the Image_Map node's U_Offset dependent on the selected number. But either the user has to go into the Material Room, or I think I'd need to use Parmatic?

3. A Python script.

I'd be interested in any thoughts that anybody has on these or other ways forward.

*The six-sided die is the simple case - the method must work with dice having different numbers of sides as well, e.g. an icosahedral twenty-sided die.

**With non-cubic (i.e non-six-sided) dice the user would have to adjust x and/or y and/or z rotations by not-immediately obvious amounts.

• i think it's possible to do it w/ one 'dice' dial linked to your xrot/yrot/zrot and ValueOps, you will prefer keyed delta adds.
For your 'dice' dial first change limits from min 1 to max 6, and sensitivity to 1.
And you have to find the combinaison with keyed valueops to rotate the dice by 90° on your xrot/yrot/zrot
ex : when dial Dice is '3' u need to rotate on y axis (yrot) by 90° so keyed value for this should be 90° .

• I think you'll also run into problems with gimbal lock, so good planing ahead of your rotation axes is necessary.
The more sides the die has, the more complex the rotation axes control will become.

How about a bunch of pose files?
You click the number you want on top, and the die is rotated the correct amount.

K

• for 4 of the 6 possibilty you can use only 1 axe rotation. xrot for example
so for "dice' dial vs xrot it's keyed :
1 -> 0
2 -> 90°
3 -> 180°
4 -> 270°
5 -> 0
6 -> 0

now 'dice' dial vs yrot should be keyed :
1 -> 0
2 -> 0
3 -> 0
4 -> 0
5 -> 90°
6 -> 270°

you don't need to key zrot in this case.

Probably, it's not totally corerct since number on a dice are not obligatory is this roder, but you have the idea.
When one 'rot' parameter is keyed to a x° the other 'rot' parameter should be keyed to 0.

• @barnardino

That's correct and will work on a simple cubic die.

But as "3Dcheapskate" said, he also wants it to work on 20-faced dice, and then it's becoming really complicated!

"Mission Impossible" I guess.
Thus my suggestion of simple "pose" injections before you'll have 20MB heavy dice with all the morphs and dependencies necessary. (OK, 20 MB is a tad exaggerated - let's say 19 MB)
:D

K

• If you do the U_Offset as an animated material parameter, it does show up on the prop as a dial and does not require the user to enter the material room at all. No need for parmatic since you would not need it to operate multiple material zones. Parmatic's job is to synchronize one dial to operate N node parameters, where N is more than one. If N is just one, then you do not need parmatic - just Poser.

I would go this way because I cannot imagine the complications of rotating a 20-sided die.

Also, using the scrolling texture approach, you could still use bullet physics to bounce the prop around. At the end you dial in the number you want using the parameter, then go back in time to first frame and set the U_Offset there as well.

This way you cheat, peak into the future to learn which face ends up, place the number you want on that face, and then all is amazingly coordinated without interfering with the physics.

• Thanks barnardino, karina. bagginsbill. I'll get back to barnardino's keyed delta adds soon (the 'keyed' bit is something I'm not aware of and may be the answer). Karina's pose files is an option I hadn't thought of.
bagginsbill's suggestion works great, with one observation.

Here's the texture map, the material (with Math_Functions Value_1 as an animated parameter), the dial, and the dial settings:

I placed six dice side-by-side and set the parameter dial to adifferent value for each. The UV mapping puts 1 on the top face, 2 on the front, 3 on the bottom, 4 on the back, 5 on the right (from our POV), and 6 on the left if the texture map is plugged directly into diffuse.

iIn the preview pane they all look the same, with 1 facing up, but when you render we get the correct number uppermost.

Here's a render of the top, front and right (from our POV) faces:

Here's a render of the bottom,back and left faces (just for completeness):

But note that the relative locations of each number with respect to the others varies depending on what number you select to be 'up'. E.g on the default UVs (and with the dial set to 1) 2 and 4 are on opposite sides, but with the dial set to four or five the 2 and 4 are on adjacent sides.

This may or may not be a problem - it just depends on what the end user's doing.

• 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
}
``````

• @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.

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