Tuesday 10 March 2020

delaying per point.... using CHOPS

For some reason, the timeshift node doesn't work within For Loops. Eg. you have a bunch of points going from A to B and you want to offset each point by an arbitrary number of frames.

Matt Estella mentions -
The core issue is that the for-begin node doesn't split and cook the geo as you'd expect. Instead you have to set the begin node into 'fetch input', so it just grabs everything, then use a split sop to get the element you want, using the metadata node to read the value or iteration detail attribute.

To be honest, I don't really understand the problem & his example file doesn't quiiiiite do what I want. One of his other ones does though, albeit with a little tweaking. Bastian J Schiffer's video is very useful.
(https://vimeo.com/280537925)

At SOP level, make an integer point attribute called something like "timeshift" with some values. Make a null after this and call it TO_CHOPS


Then what we want to do is access a point attribute in CHOPS. The method isn't immediately obvious.
Make a chopnet, and two geometry nodes. Point them to TO_CHOPS  and make sure they're both "animated" and not "static. With the first one (geometry-transform), leave the default P, tx,ty,tz values... With the second (geometry-timeshift), set the Attribute scope to "timeshift" and the Rename scope to "timeshift" too.



Next make a channel wrangle. This behaves like a point wrangle, for the most part..there are, however, some CHOPS-only variables. Stick the geo-transform into input 1, and the geo-timeshift into input2.
Type this into the vex-box -

V=chinput(0,C, I+chinput(1,C,I));
"V" stands for value.
"chinput" is like the "point" function, but here it fetches channels instead of attributes. There're a few ways to use the function, but here we're going for the chinput(0,C,I) easy mode...

The first 0 is the 0th input (geo-transform), it fetches C, the channels (which are tx, ty, tz) and....
"I" is the index/iteration...we modify this by chinputting the geo-timeshift input and grabbing it's channels (the timeshift attribute)
Finally add a null, name it OUT (ignore the math/noise node for now, that's some other crap)
Jump up to SOP level and put a channel node to the TO_CHOPS, switch it to Animate mode. The default value of t[xyz] and P are fine here.

Your points should now be delayed....
You could make the delay a bit more fancy by adding a multiplier, either to the expression above, or in the bit where you define the timeshift attribute in the first place..

Monday 9 March 2020

orient point attribute


I always seem to forget/ignore the orient attribute, and it always bites me in the ass.. (think instancing objects onto points with random rotations etc) Usually I randomise/mess up the target points' normals, but if you forget to give your source object clean normals, this can lead to some messy point normals..
If instead, you mess up the target points' orient, you avoid this nonsense. It's worth creating a custom vector attribute display to visualise the orients!

Another snippet stolen from Rich Lord's notes/tools page - https://www.richlord.com/tools/

I suspect that there's a shortcut for building the matrix at the end, but from my understanding this setup should be quite clean..

// create an axis and an up vector.
// The axis will represent the Z direction of the final matrix
vector axis = chv("axis");
vector up   = chv("up");
// normalise these two vectors
axis = normalize(axis);
up = normalize(up);
// build a vector for each axis, then build a matrix out of it.
// I may be normalizing a bit much here, but it cant hurt.
vector zaxis = axis;
vector xaxis = normalize(cross(up, axis));
vector yaxis = normalize(cross(axis, xaxis));
matrix3 default = set(xaxis, yaxis, zaxis);
// create the orient quaternion as a point attribute
p@orient = quaternion(default);

Rotation in vex

Rotation round an arbitrary axis, in vex

nicked from Rich Lord's handy notes and scenes - https://www.richlord.com/tools/
Placed here, jusssst in case it all vanishes!
The general gist is -


  1. define an axis to rotate around
  2. specify the angle of rotation
  3. create an identity matrix
  4. rotate the matrix by the angle, along the axis
  5. multiply the Position of each point by the transformed matrix

Here's the code -
vector axis = normalize(chv("rotate_axis"));
float angle = radians(chf("rotate_angle"));
// create the matrix representing the rotation, and rotate the points
matrix3 m = ident();
rotate(m, angle, axis);
@P *= m;
Be sure to press the create slider/input button!

A separate example Rich provided has the points rotate around a point in space -

The same technique applies, except a little bit of subtraction/addition of the point position (we move the points-to-be-rotated to the position-of-the-rotation-origin first). Pretty useful, as you're probably not just doing everything at the origin :D

Code -
vector rotate_point = chv("rotate_point"); //this is the origin of the rotation
vector axis = normalize(chv("rotate_axis")); //the axis
float angle = radians(chf("rotate_angle")); //the angle of rotation...
// move the points before the rotation
@P -= rotate_point;
// build the matrix that does the rotation and apply it to the points
matrix3 m = ident();
rotate(m, angle, axis);
@P *= m;
// move the points back to their original position
@P += rotate_point;