Difference between revisions of "JoyOfVex2"

From cgwiki
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
=== Day 2 ===
 
=== Day 2 ===
  
Vex has lots of functions. LOTS. Here's an alarming list of them all:
+
Vex has lots of functions. LOTS. Here's an alarming list of them all. Bookmark it, you'll use it all the time as you get more familiar with vex:
  
 
http://www.sidefx.com/docs/houdini16.0/vex/functions/_index
 
http://www.sidefx.com/docs/houdini16.0/vex/functions/_index
Line 7: Line 7:
 
Good to start with the simple, work up. A handy starting point is to measure the length of a vector, which you do with '''length'''. (Keep with the grid geometry for now)
 
Good to start with the simple, work up. A handy starting point is to measure the length of a vector, which you do with '''length'''. (Keep with the grid geometry for now)
  
<source>
+
<source lang="javascript" >
 
  float d = length(@P);
 
  float d = length(@P);
 
</source>
 
</source>
Line 13: Line 13:
 
Applied to @P, it tells you the distance a point is from the origin. Put that into colour:
 
Applied to @P, it tells you the distance a point is from the origin. Put that into colour:
  
<source>
+
<source lang="javascript" >
 
  float d = length(@P);
 
  float d = length(@P);
 
  @Cd = d;
 
  @Cd = d;
Line 20: Line 20:
 
Boring. But we can now put this into '''sin''', get something interesting:
 
Boring. But we can now put this into '''sin''', get something interesting:
  
<source>
+
<source lang="javascript" >
 
  float d = length(@P);
 
  float d = length(@P);
 
  @Cd = sin(d);
 
  @Cd = sin(d);
Line 27: Line 27:
 
will probably need to set the range to see the sine waves better:
 
will probably need to set the range to see the sine waves better:
  
<source>
+
<source lang="javascript" >
 
  float d = length(@P);
 
  float d = length(@P);
 
  d *= ch('scale');  
 
  d *= ch('scale');  
Line 39: Line 39:
 
If you look at the geometry spreadsheet, you can see that the dark values for @Cd are going into negative values, we can't have that. Can just add an offset to get them out of negative.
 
If you look at the geometry spreadsheet, you can see that the dark values for @Cd are going into negative values, we can't have that. Can just add an offset to get them out of negative.
  
<source>
+
<source lang="javascript" >
 
  float d = length(@P);
 
  float d = length(@P);
 
  d *= ch('scale');  
 
  d *= ch('scale');  
Line 47: Line 47:
 
But our colours still aren't right, as now we're getting values going between 0 and 2. Now we can divide by 2 to get it back to a 0 to 1 range (and use brackets to make sure the operations are done in the right order):
 
But our colours still aren't right, as now we're getting values going between 0 and 2. Now we can divide by 2 to get it back to a 0 to 1 range (and use brackets to make sure the operations are done in the right order):
  
<source>
+
<source lang="javascript" >
 
  float d = length(@P);
 
  float d = length(@P);
 
  d *= ch('scale');  
 
  d *= ch('scale');  
Line 55: Line 55:
 
Some coders frown upon using divide, and prefer to multiply by a fraction. You look cooler if you do, but it doesn't really matter at this stage:
 
Some coders frown upon using divide, and prefer to multiply by a fraction. You look cooler if you do, but it doesn't really matter at this stage:
  
<source>
+
<source lang="javascript" >
 
  float d = length(@P);
 
  float d = length(@P);
 
  d *= ch('scale');  
 
  d *= ch('scale');  
Line 63: Line 63:
 
Breaking this across 3 lines is a matter of style, its perfectly valid to compact lines together, in whatever way you want. I like to break them out, others write super compressed one liners, all good. This is the same:
 
Breaking this across 3 lines is a matter of style, its perfectly valid to compact lines together, in whatever way you want. I like to break them out, others write super compressed one liners, all good. This is the same:
  
<source>
+
<source lang="javascript" >
 
  float d = length(@P) * ch('scale');
 
  float d = length(@P) * ch('scale');
 
  @Cd = (sin(d)+1)*0.5;
 
  @Cd = (sin(d)+1)*0.5;
Line 70: Line 70:
 
and this (but see how it gets harder to read at a glance):
 
and this (but see how it gets harder to read at a glance):
  
<source>
+
<source lang="javascript" >
 
  @Cd = (sin(length(@P) * ch('scale'))+1)*0.5;
 
  @Cd = (sin(length(@P) * ch('scale'))+1)*0.5;
 
</source>
 
</source>
Line 78: Line 78:
 
Related to length is '''distance'''. While length(@P), measures the distance from the point to {0,0,0}, distance lets measure the distance from the point to another value you specify, so we could have these rings start at {1,0,3} for example. That's how you type simple vectors, with curly brackets btw. One of the most common errors you make in vex is accidentally swapping curly brackets for normal ones!
 
Related to length is '''distance'''. While length(@P), measures the distance from the point to {0,0,0}, distance lets measure the distance from the point to another value you specify, so we could have these rings start at {1,0,3} for example. That's how you type simple vectors, with curly brackets btw. One of the most common errors you make in vex is accidentally swapping curly brackets for normal ones!
  
<source>
+
<source lang="javascript" >
 
  float d = distance(@P, {1,0,3} );
 
  float d = distance(@P, {1,0,3} );
 
  d *= ch('scale');  
 
  d *= ch('scale');  
Line 84: Line 84:
 
</source>
 
</source>
  
There's another channel call, chv, that gives you a vector slider. Lets define a vector variable, 'center', use that:
+
There's another channel call, '''chv''', that gives you a vector slider. Lets define a vector variable, 'center', use that:
  
<source>
+
<source lang="javascript" >
 
  vector center = chv('center');
 
  vector center = chv('center');
 
  float d = distance(@P, center );
 
  float d = distance(@P, center );
Line 95: Line 95:
 
An interesting trick is to multiply vectors. For example, multiply @P by {0.5,1,1}, you're making x advance half as fast as it normally does. Feed that in rather than vanilla @P, you get squished rings:
 
An interesting trick is to multiply vectors. For example, multiply @P by {0.5,1,1}, you're making x advance half as fast as it normally does. Feed that in rather than vanilla @P, you get squished rings:
  
<source>
+
<source lang="javascript" >
 
  vector center = chv('center');
 
  vector center = chv('center');
 
  float d = distance(@P* {0.5,1,1}, center );
 
  float d = distance(@P* {0.5,1,1}, center );
Line 104: Line 104:
 
Again my tidy gene wants to kick in and make this easier to read at a glance, as well as easy to edit interactively with another slider:
 
Again my tidy gene wants to kick in and make this easier to read at a glance, as well as easy to edit interactively with another slider:
  
<source>
+
<source lang="javascript" >
 
  vector pos = @P * chv('fancyscale');
 
  vector pos = @P * chv('fancyscale');
 
  vector center = chv('center');
 
  vector center = chv('center');
 
  float d = distance(pos, center );
 
  float d = distance(pos, center );
 
  d *= ch('scale');  
 
  d *= ch('scale');  
  @Cd = sin(d)*0.5+1;
+
  @Cd = (sin(d)+1)*0.5;
 
</source>
 
</source>
  
Line 115: Line 115:
  
 
[[File:joyofvex2_sin2.gif]]
 
[[File:joyofvex2_sin2.gif]]
 +
 +
=== Clashing channel names ===
  
 
Note that I originally had both chv('scale') on the first line, and ch('scale') on the 2nd last line, which is wrong. You can't use identical names for channels, one will take priority. Moreso, once you've defined a channel by name (say from the previous example), and you change its type in vex (from ch to chv say), the 'make channels' button won't update it.
 
Note that I originally had both chv('scale') on the first line, and ch('scale') on the 2nd last line, which is wrong. You can't use identical names for channels, one will take priority. Moreso, once you've defined a channel by name (say from the previous example), and you change its type in vex (from ch to chv say), the 'make channels' button won't update it.
  
The laziest way to fix it is to delete all the channel sliders/parameters, and click the 'make channel' button again to recreate it. You can delete all the channels in one hit from the parameter menu, and choose 'delete all spare parameters'. You lose all the values you might have typed in, which is a shame, but its a lesson to not clash your names in future. :)
+
The laziest way to fix it is to delete all the channel sliders/parameters, and click the 'make channel' button again to recreate it. You can delete all the channels in one hit from the parameter menu, and choose 'Delete All Spare Parameters'.  
  
 
[[File:joyofvex2_wipe_channels.gif]]
 
[[File:joyofvex2_wipe_channels.gif]]
 +
 +
A more selective way is to right click on a channel name and choose 'More -> Delete Spare Parameter', which deletes one at a time.
 +
 +
[[File:jov2_delete_spare_parm.png]]
 +
 +
=== Fit ===
  
 
That add one and divide by 2 step can be replaced by another function, '''fit'''. You tell it the incoming min and max values ( -1 and 1 in this case), and the new min and max values you want (0 and 1).  
 
That add one and divide by 2 step can be replaced by another function, '''fit'''. You tell it the incoming min and max values ( -1 and 1 in this case), and the new min and max values you want (0 and 1).  
  
<source>
+
<source lang="javascript" >
 
  vector pos = @P * chv('fancyscale');
 
  vector pos = @P * chv('fancyscale');
 
  vector center = chv('center');
 
  vector center = chv('center');
Line 134: Line 142:
 
And finally, introduce a new handy built in attribute, '''@Time'''. If we add this to our d variable, it will push the sine wave along, causing the wave to animate.
 
And finally, introduce a new handy built in attribute, '''@Time'''. If we add this to our d variable, it will push the sine wave along, causing the wave to animate.
  
<source>
+
<source lang="javascript" >
 
  vector pos = @P * chv('fancyscale');
 
  vector pos = @P * chv('fancyscale');
 
  vector center = chv('center');
 
  vector center = chv('center');
Line 146: Line 154:
 
Something I glossed over is a subtle C-style thing that can be easy to miss if you're not used to it.
 
Something I glossed over is a subtle C-style thing that can be easy to miss if you're not used to it.
  
If you had a variable and wanted to multiply it by 5, you can do this:
+
If you had a variable and wanted to multiply it by 5, you could do this:
  
<source>
+
<source lang="javascript" >
 
foo = foo * 5;
 
foo = foo * 5;
 
</source>
 
</source>
Line 154: Line 162:
 
But there's a shorthand for that, the *= operator:
 
But there's a shorthand for that, the *= operator:
  
<source>
+
<source lang="javascript" >
 
foo *= 5;
 
foo *= 5;
 
</source>
 
</source>
Line 162: Line 170:
 
Another thing you can do with code is do a bunch of operations on one line:
 
Another thing you can do with code is do a bunch of operations on one line:
  
<source>
+
<source lang="javascript" >
 
foo = foo * 3 +1 / @Cd.x + @N.y;
 
foo = foo * 3 +1 / @Cd.x + @N.y;
 
</source>
 
</source>
Line 168: Line 176:
 
But it can be easier to understand if you break that over several lines, using the shorthand operators to do the operation:
 
But it can be easier to understand if you break that over several lines, using the shorthand operators to do the operation:
  
<source>
+
<source lang="javascript" >
 
foo *=3; // set range
 
foo *=3; // set range
 
foo +=1; // make sure values never get below 0
 
foo +=1; // make sure values never get below 0
Line 177: Line 185:
 
etc. What can trip you up is if you accidentally use an = by itself, eg:
 
etc. What can trip you up is if you accidentally use an = by itself, eg:
  
<source>
+
<source lang="javascript" >
 
foo *=3; // set range
 
foo *=3; // set range
 
foo +=1; // make sure values never get below 0
 
foo +=1; // make sure values never get below 0
Line 195: Line 203:
 
----
 
----
  
prev: [[JoyOfVex2]] next: [[JoyOfVex3]]
+
prev: [[JoyOfVex1]] this: [[JoyOfVex2]] next: [[JoyOfVex3]] <br>
 +
main menu: [[JoyOfVex]]

Latest revision as of 12:18, 3 March 2021

Day 2

Vex has lots of functions. LOTS. Here's an alarming list of them all. Bookmark it, you'll use it all the time as you get more familiar with vex:

http://www.sidefx.com/docs/houdini16.0/vex/functions/_index

Good to start with the simple, work up. A handy starting point is to measure the length of a vector, which you do with length. (Keep with the grid geometry for now)

 float d = length(@P);

Applied to @P, it tells you the distance a point is from the origin. Put that into colour:

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

Boring. But we can now put this into sin, get something interesting:

 float d = length(@P);
 @Cd = sin(d);

will probably need to set the range to see the sine waves better:

 float d = length(@P);
 d *= ch('scale'); 
 @Cd = sin(d);

3 lines of vex! woo! Set the scale slider above 1, somewhere between 5 and 10 on the grid to see the waves doing their thing.

Joyofvex2 sin1.gif

If you look at the geometry spreadsheet, you can see that the dark values for @Cd are going into negative values, we can't have that. Can just add an offset to get them out of negative.

 float d = length(@P);
 d *= ch('scale'); 
 @Cd = sin(d)+1;

But our colours still aren't right, as now we're getting values going between 0 and 2. Now we can divide by 2 to get it back to a 0 to 1 range (and use brackets to make sure the operations are done in the right order):

 float d = length(@P);
 d *= ch('scale'); 
 @Cd = (sin(d)+1)/2;

Some coders frown upon using divide, and prefer to multiply by a fraction. You look cooler if you do, but it doesn't really matter at this stage:

 float d = length(@P);
 d *= ch('scale'); 
 @Cd = (sin(d)+1)*0.5;

Breaking this across 3 lines is a matter of style, its perfectly valid to compact lines together, in whatever way you want. I like to break them out, others write super compressed one liners, all good. This is the same:

 float d = length(@P) * ch('scale');
 @Cd = (sin(d)+1)*0.5;

and this (but see how it gets harder to read at a glance):

 @Cd = (sin(length(@P) * ch('scale'))+1)*0.5;

Distance

Related to length is distance. While length(@P), measures the distance from the point to {0,0,0}, distance lets measure the distance from the point to another value you specify, so we could have these rings start at {1,0,3} for example. That's how you type simple vectors, with curly brackets btw. One of the most common errors you make in vex is accidentally swapping curly brackets for normal ones!

 float d = distance(@P, {1,0,3} );
 d *= ch('scale'); 
 @Cd = (sin(d)+1)*0.5;

There's another channel call, chv, that gives you a vector slider. Lets define a vector variable, 'center', use that:

 vector center = chv('center');
 float d = distance(@P, center );
 d *= ch('scale'); 
 @Cd = (sin(d)+1)*0.5;

An interesting trick is to multiply vectors. For example, multiply @P by {0.5,1,1}, you're making x advance half as fast as it normally does. Feed that in rather than vanilla @P, you get squished rings:

 vector center = chv('center');
 float d = distance(@P* {0.5,1,1}, center );
 d *= ch('scale'); 
 @Cd = (sin(d)+1)*0.5;

Again my tidy gene wants to kick in and make this easier to read at a glance, as well as easy to edit interactively with another slider:

 vector pos = @P * chv('fancyscale');
 vector center = chv('center');
 float d = distance(pos, center );
 d *= ch('scale'); 
 @Cd = (sin(d)+1)*0.5;

Check it, movable, squishable rings.

Joyofvex2 sin2.gif

Clashing channel names

Note that I originally had both chv('scale') on the first line, and ch('scale') on the 2nd last line, which is wrong. You can't use identical names for channels, one will take priority. Moreso, once you've defined a channel by name (say from the previous example), and you change its type in vex (from ch to chv say), the 'make channels' button won't update it.

The laziest way to fix it is to delete all the channel sliders/parameters, and click the 'make channel' button again to recreate it. You can delete all the channels in one hit from the parameter menu, and choose 'Delete All Spare Parameters'.

Joyofvex2 wipe channels.gif

A more selective way is to right click on a channel name and choose 'More -> Delete Spare Parameter', which deletes one at a time.

Jov2 delete spare parm.png

Fit

That add one and divide by 2 step can be replaced by another function, fit. You tell it the incoming min and max values ( -1 and 1 in this case), and the new min and max values you want (0 and 1).

 vector pos = @P * chv('fancyscale');
 vector center = chv('center');
 float d = distance(pos, center );
 d *= ch('scale'); 
 @Cd = fit(sin(d),-1,1,0,1);

And finally, introduce a new handy built in attribute, @Time. If we add this to our d variable, it will push the sine wave along, causing the wave to animate.

 vector pos = @P * chv('fancyscale');
 vector center = chv('center');
 float d = distance(pos, center );
 d *= ch('scale'); 
 @Cd = fit(sin(d+@Time),-1,1,0,1);

More on code style

Something I glossed over is a subtle C-style thing that can be easy to miss if you're not used to it.

If you had a variable and wanted to multiply it by 5, you could do this:

foo = foo * 5;

But there's a shorthand for that, the *= operator:

foo *= 5;

There's equivalent operators for +=, -=, /=.

Another thing you can do with code is do a bunch of operations on one line:

foo = foo * 3 +1 / @Cd.x + @N.y;

But it can be easier to understand if you break that over several lines, using the shorthand operators to do the operation:

foo *=3; // set range
foo +=1; // make sure values never get below 0
foo /= @Cd.x; // reduce range to within red value
foo += @N.y; // addition normal on y

etc. What can trip you up is if you accidentally use an = by itself, eg:

foo *=3; // set range
foo +=1; // make sure values never get below 0
foo /= @Cd.x; // reduce range to within red value
foo = @N.y; // addition normal on y

In that code, foo on the last line is just assigned the value of N.y. In other words, I've accidentally wiped out all the work of the previous lines. Its an easy mistake to make at first, watch out for it.

Exercises

  1. Change the direction the waves move from towards the center to away from the center
  2. Change the speed of the waves
  3. Make the waves be blue on black, or yellow on green
  4. Rather than affect colour, make them affect the y position of the points.

prev: JoyOfVex1 this: JoyOfVex2 next: JoyOfVex3
main menu: JoyOfVex