# Difference between revisions of "JoyOfVex5"

MattEstela (talk | contribs) |
MattEstela (talk | contribs) (→Modulo) |
||

(7 intermediate revisions by the same user not shown) | |||

Line 5: | Line 5: | ||

% is modulo. When you first learn to divide in primary school, and you do remainders, well, modulo is the remainder. That's it. | % is modulo. When you first learn to divide in primary school, and you do remainders, well, modulo is the remainder. That's it. | ||

− | Ask a 10 year old kid '5 divided by 2' , they'll tell you '2, remainder 1'. In the same way, 5 % 2 = 1. | + | Ask a 10 year old kid 'What is 5 divided by 2?' , they'll tell you '2, remainder 1'. In the same way, 5 % 2 = 1. |

This is useful because it sets up loops; when the first and second number are the same, the remainder is 0. If you're doing modulo by 5 on an input that smoothly increases, like @ptnum or @Frame, you'll get a sawtooth waveform that goes 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4... | This is useful because it sets up loops; when the first and second number are the same, the remainder is 0. If you're doing modulo by 5 on an input that smoothly increases, like @ptnum or @Frame, you'll get a sawtooth waveform that goes 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4... | ||

− | <source> | + | <source lang="javascript" > |

@P.y = @ptnum % 5; | @P.y = @ptnum % 5; | ||

</source> | </source> | ||

Line 15: | Line 15: | ||

Modulo works on fractional values too, so you can give it a float input, and smoothly varying float input like @Time, you still get a sawtooth pattern: | Modulo works on fractional values too, so you can give it a float input, and smoothly varying float input like @Time, you still get a sawtooth pattern: | ||

− | <source> | + | <source lang="javascript" > |

− | @Cd.r = @Time % 0. | + | @Cd.r = @Time % 0.7; |

</source> | </source> | ||

Line 25: | Line 25: | ||

Go back to the usual trick of P.y based on distance to the origin: | Go back to the usual trick of P.y based on distance to the origin: | ||

− | <source> | + | <source lang="javascript" > |

float d = length(@P); | float d = length(@P); | ||

d *= ch('scale'); | d *= ch('scale'); | ||

Line 41: | Line 41: | ||

Ie, the smoothly increasing original values are now stepped. But what if the original values are really small, say ranging from 0.001 to 0.003? If you remove values after the decimal point, it all goes to 0, thats no good. Similarly, if the values were between 1000 and 4000, it won't make much of a difference. | Ie, the smoothly increasing original values are now stepped. But what if the original values are really small, say ranging from 0.001 to 0.003? If you remove values after the decimal point, it all goes to 0, thats no good. Similarly, if the values were between 1000 and 4000, it won't make much of a difference. | ||

− | The trick is to multiply all the numbers by a factor to push the interesting values to the left of the decimal point, then remove stuff after the decimal point, then divide by the original number. If you put that steppy factor on a channel slider, you have an easy way to dial in the size of the steps. The vex function to remove stuff after the decimal point is '''trunc''', short for truncate. | + | The trick is to multiply all the numbers by a factor to push the interesting values to the left of the decimal point, then remove stuff after the decimal point, then divide by the original number. If you put that steppy factor on a channel slider, you have an easy way to dial in the size of the steps. The vex function to remove stuff after the decimal point is '''trunc''', short for truncate ( http://www.sidefx.com/docs/houdini/vex/functions/trunc.html ) |

− | <source> | + | <source lang="javascript" > |

float d = length(@P); | float d = length(@P); | ||

d *= ch('scale'); | d *= ch('scale'); | ||

Line 52: | Line 52: | ||

@P.y = d; | @P.y = d; | ||

</source> | </source> | ||

+ | |||

+ | [[File:trunc01.gif]] | ||

+ | |||

+ | This process of losing precision is called '''quantising'''. | ||

=== Faking trunc with a chramp === | === Faking trunc with a chramp === | ||

Line 59: | Line 63: | ||

So if you were doing this to the default grid for example, and you wanted it to look like the earlier attempt, you'd enter the following code, set prescale to 0.1 (Because the grid is 10 units wide, so this will make 'd' go from 0 at the center to 1 at the edge), and afterwards set post-scale to 10 (because the chramp will have its maximum value output at 1, so you need to multiply it back up to 10 to get to the height from the earlier simple example). | So if you were doing this to the default grid for example, and you wanted it to look like the earlier attempt, you'd enter the following code, set prescale to 0.1 (Because the grid is 10 units wide, so this will make 'd' go from 0 at the center to 1 at the edge), and afterwards set post-scale to 10 (because the chramp will have its maximum value output at 1, so you need to multiply it back up to 10 to get to the height from the earlier simple example). | ||

+ | <source lang="javascript" > | ||

float d = length(@P); | float d = length(@P); | ||

d *= ch('pre_scale'); | d *= ch('pre_scale'); | ||

Line 64: | Line 69: | ||

d *= ch('post_scale'); | d *= ch('post_scale'); | ||

@P.y = d; | @P.y = d; | ||

+ | </source> | ||

+ | [[File:trunc_chramp.gif]] | ||

=== Exercises === | === Exercises === |

## Latest revision as of 18:31, 3 February 2021

### Modulo

Everyone understands + - * /, but % usually surprises people who haven't done much coding before.

% is modulo. When you first learn to divide in primary school, and you do remainders, well, modulo is the remainder. That's it.

Ask a 10 year old kid 'What is 5 divided by 2?' , they'll tell you '2, remainder 1'. In the same way, 5 % 2 = 1.

This is useful because it sets up loops; when the first and second number are the same, the remainder is 0. If you're doing modulo by 5 on an input that smoothly increases, like @ptnum or @Frame, you'll get a sawtooth waveform that goes 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4...

```
@P.y = @ptnum % 5;
```

Modulo works on fractional values too, so you can give it a float input, and smoothly varying float input like @Time, you still get a sawtooth pattern:

```
@Cd.r = @Time % 0.7;
```

Lots of effects involve setting up loops, modulo gives you an easy way to setup inputs or outputs that loop.

### Making smooth things stepped via quantising

Go back to the usual trick of P.y based on distance to the origin:

```
float d = length(@P);
d *= ch('scale');
@P.y = d;
```

The result is a smooth funnel shape. What we can do is make this steppy. Imagine we had slowly increasing fractional values:

1.0, 1.1, 1.2, 1.3, 1.4 ... 1.8, 1.9, 2.0, 2.1, 2.2, 2.3 ...

If we removed everything after the decimal place, you'd get this:

1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3

Ie, the smoothly increasing original values are now stepped. But what if the original values are really small, say ranging from 0.001 to 0.003? If you remove values after the decimal point, it all goes to 0, thats no good. Similarly, if the values were between 1000 and 4000, it won't make much of a difference.

The trick is to multiply all the numbers by a factor to push the interesting values to the left of the decimal point, then remove stuff after the decimal point, then divide by the original number. If you put that steppy factor on a channel slider, you have an easy way to dial in the size of the steps. The vex function to remove stuff after the decimal point is **trunc**, short for truncate ( http://www.sidefx.com/docs/houdini/vex/functions/trunc.html )

```
float d = length(@P);
d *= ch('scale');
float f = ch('factor');
d /= f;
d = trunc(d);
d *= f;
@P.y = d;
```

This process of losing precision is called **quantising**.

### Faking trunc with a chramp

An equally valid way to get stepping is to draw in a stepped graph into a channel ramp. Whatever is more useful to you at the time. Just remember that you'll probably need 2 scaling functions, the first to bring your thing into a 0 to 1 range for the channel ramp, and a second to scale it to where you need the y-values to be after quantizing.

So if you were doing this to the default grid for example, and you wanted it to look like the earlier attempt, you'd enter the following code, set prescale to 0.1 (Because the grid is 10 units wide, so this will make 'd' go from 0 at the center to 1 at the edge), and afterwards set post-scale to 10 (because the chramp will have its maximum value output at 1, so you need to multiply it back up to 10 to get to the height from the earlier simple example).

```
float d = length(@P);
d *= ch('pre_scale');
d = chramp('my_stepped_ramp', d);
d *= ch('post_scale');
@P.y = d;
```

### Exercises

- try the different interpolation modes on the points of the ramp
- using interpolation, see how few points you can use to define a sine wave
- think of other inputs you can use to drive the ramp. Components of P? Components of Cd or N? Current Time or current @Frame? If those things aren't in a 0:1 range like chramp expects, how do you
**fit**them to the range you need?

prev: JoyOfVex4 this: JoyOfVex5 next: JoyOfVex6

main menu: JoyOfVex