10.10.4.8. Harmonizer

If the key-value pair in the description has a key harmonizer_type, it defines a harmonizer. A harmonizer constrains how a mutable attribute randomizes.

Mutable attribute harmonizer

If harmonizer_type is mutable_attribute, it is a mutable attribute harmonizer. When the harmonizers harmonize, a value is resolved for it just as in any other mutable attributes.

We often want to randomize a value that is shared across different mutable attributes, but is different across different frames. Consider a scene where there are 2 penguins standing side by side.

penguin:
  count: 2
  type: geometry
  subtype: mesh
  usd_path: [PATH_TO_PENGUIN]
  transform_operators:
  - translate:
    - ($[index] % 2 - 0.5) * 600
    - 0
    - 0
../../_images/harmonizer-1.png

We rotateY them by 30 degrees each, which looks fine:

transform_operators:
- translate:
  - ($[index] % 2 - 0.5) * 600
  - 0
  - 0
- rotateY: 30
../../_images/harmonizer-2.png

But once we want to specify rotateY as a mutable attribute, they rotate differently within the same frame:

transform_operators:
- translate:
  - ($[index] % 2 - 0.5) * 600
  - 0
  - 0
- rotateY:
    distribution_type: range
    start: -180
    end: 180
../../_images/harmonizer-3.png

Now we want them to rotate the same angle the same frame, but different angles accross different frames. This is where the harmonizer comes to the rescue. Define a harmonizer

rotate_H:
  harmonizer_type: mutable_attribute
  mutable_attribute:
    distribution_type: range
    start: -180
    end: 180

This will be evaluated only once per frame in the harmonize stage. Then the penguin mutables will retrieve this value per frame, from the harmonizer:

- rotateY:
  distribution_type: harmonized
  harmonizer_name: rotate_H

Now we have them rotating the same amount.

../../_images/harmonizer-4.png ../../_images/harmonizer-5.png

This can be used in all other transform operators as well, and all other distribution types.

Permutation harmonizer

If harmonizer_type is permutate, it is a permutation harmonizer. When we free randomize a harmonized mutable attribute, we can specify a pitch as the input to the permutation harmonizer. Then the permutation harmonizer shuffles these input, and sends back the value to the harmonized attribute, which in turn can be used in a transform operator in the harmonized randomize stage

Let’s see an example. We define 3 penguins, facing 3 directions:

penguin:
  count: 3
  type: geometry
  subtype: mesh
  usd_path: [PATH_TO_PENGUIN]
  transform_operators:
  - translate:
    - ($[index] % $[count] - 1) * 600
    - 0
    - 0
  - rotateY: ($[index] - 1) * 60

These 3 penguins have X-axis position -600, 0, 600; and they are rotated around Y-axis by -60, 0, 60 degrees.

../../_images/harmonizer-6.png

Now we want to shuffle the positions of these penguins. So that penguin that rotate -60 degrees can appear to the right, for example.

First we define a mutable attribute permutated_index as harmonized. At free randomize stage, it submits its index as its pitch to the harmonizer permutate_H, which is a permutation harmonizer.

penguin:
  ...
  permutated_index:
    distribution_type: harmonized
    harmonizer_name: permutate_H
    pitch: $[index]
permutate_H:
  harmonizer_type: permutate

At harmonize stage, permutate_H shuffles the received pitches from all relevant harmonized mutable attributes, and resonate them back to each of them.

At harmonized randomize stage, permutated_index gets the shuffled value back. Now, we can use it in transform operators just as using an index.

penguin:
  ...
  transform_operators:
  - translate:
    - ($[permutated_index] % $[count] - 1) * 600
    - 0
    - 0
  - rotateY: ($[index] - 1) * 60
../../_images/harmonizer-7.png ../../_images/harmonizer-8.png

This feature can be used with any values within scope.