Difference between revisions of "JoyOfVex2"

From cgwiki
Line 1: Line 1:
 
=== Day 2 ===
 
=== Day 2 ===
  
Vex has lots of functions, good to start with the simple work up. A handy starting point is to measure the length of a vector.
+
Vex has lots of functions. LOTS. Here's an alarming list of them all:
 +
 
 +
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'''.
  
 
  float d = length(@P);
 
  float d = length(@P);
  
That 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:
  
 
  float d = length(@P);
 
  float d = length(@P);
Line 21: Line 25:
 
  @Cd = sin(d);
 
  @Cd = sin(d);
  
3 lines of vex! woo!
+
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.
  
 
Those colour values are still dipping into negative though, don't like that. Can just add an offset to get them out of negative.
 
Those colour values are still dipping into negative though, don't like that. Can just add an offset to get them out of negative.
Line 28: Line 32:
 
  d *= ch('scale');  
 
  d *= ch('scale');  
 
  @Cd = sin(d)+1;
 
  @Cd = sin(d)+1;
 
The d += 1 is a handy shortcut for writing d = d+1, works the same for most maths operators (so d*=3, d/=2, d-=12).
 
  
 
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):
Line 36: Line 38:
 
  d *= ch('scale');  
 
  d *= ch('scale');  
 
  @Cd = (sin(d)+1)/2;
 
  @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:
 
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:
Line 53: Line 54:
 
  @Cd = (sin(length(@P) * ch('scale'))+1)*0.5;
 
  @Cd = (sin(length(@P) * ch('scale'))+1)*0.5;
  
Related to length is distance. Length measures the length of a vector. For @P, that means its the length to the origin. The distance function lets you specify the start and end, so we could have these rings start at {1,0,3} for example. Thats how you type simple vectors, with curly brackets btw. One of the most common errors you make in vex when starting out, and still when you get experienced, is 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 you define the start point, 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 when starting out, and still when you get experienced, is accidentally swapping curly brackets for normal ones!
  
 
  float d = distance(@P, {1,0,3} );
 
  float d = distance(@P, {1,0,3} );
 
  d *= ch('scale');  
 
  d *= ch('scale');  
 
  @Cd = (sin(d)+1)*0.5;
 
  @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:
 
There's another channel call, chv, that gives you a vector slider. Lets define a vector variable, 'center', use that:
Line 97: Line 97:
 
  d *= ch('scale');  
 
  d *= ch('scale');  
 
  @Cd = fit(sin(d+@Time),-1,1,0,1);
 
  @Cd = fit(sin(d+@Time),-1,1,0,1);
 +
 +
To be explicit about a process I'm doing here, you can refer to the same variable or attribute over several lines, and the effects will accumulate if you design them as such. For example we could make these rings be red-on-black by first setting @Cd to black, then setting the red component of @Cd with our sin function:
 +
 +
vector pos = @P * chv('fancyscale');
 +
vector center = chv('center');
 +
float d = distance(pos, center );
 +
d *= ch('scale');
 +
@Cd = {0,0,0};
 +
@Cd.r = fit(sin(d+@Time),-1,1,0,1);
 +
  
 
Exercises:
 
Exercises:
Line 102: Line 112:
 
# Change the direction the waves move from towards the center to away from the center
 
# Change the direction the waves move from towards the center to away from the center
 
# Change the speed of the waves
 
# Change the speed of the waves
# Make the waves be red
+
# Make the waves be blue on black, or yellow on green
 
# Rather than affect colour, make them affect the y position of the points.
 
# Rather than affect colour, make them affect the y position of the points.

Revision as of 05:52, 15 February 2018

Day 2

Vex has lots of functions. LOTS. Here's an alarming list of them all:

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.

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.

Those colour values are still dipping into negative though, don't like 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;

Related to length is distance. While length(@P), measures the distance from the point to {0,0,0}, distance lets you define the start point, 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 when starting out, and still when you get experienced, 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('scale');
vector center = chv('center');
float d = distance(pos, center );
d *= ch('scale'); 
@Cd = sin(d)*0.5+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).

vector pos = @P * chv('scale');
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);

To be explicit about a process I'm doing here, you can refer to the same variable or attribute over several lines, and the effects will accumulate if you design them as such. For example we could make these rings be red-on-black by first setting @Cd to black, then setting the red component of @Cd with our sin function:

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


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.