Showing posts with label matrix. Show all posts
Showing posts with label matrix. Show all posts

Tuesday 27 August 2024

creating orient and rotating points around vector

I think Toadstorm posted this somewhere on odforce... but it's a useful little vex snippet


 vector fwd = v@N;

vector up = {0,1,0};
// if you don't have a defined up vector but want to compute one the way houdini does it natively,
// compute the rotation that rotates +Z to N and apply this to +Y...
// matrix3 d = dihedral({0,0,1}, fwd);
// up = normalize(d * up);matrix3 m = maketransform(fwd, up);
// now you can rotate this around whatever axis you want.
vector axis = normalize(chv("axis")); // or use an existing vector attribute!
float angle = @noiseVal*radians(ch("angle")); // or use a random float attribute!
rotate(m, angle, axis);// now convert this rotated matrix to a quaternion and bind to p@orient. copy to points and/or DOPs will understand this.
@orient = quaternion(m);

Thursday 9 March 2023

Wednesday 26 October 2022

using a transform that relies on $CEX $CEY $CEZ with a differently shaped/sized object

Use the julian matrix - (point wrangle)

matrix M=detail(1,"xform");

@P=@P*M;

plug the transform you want to "copy" into input 2 ("1") and the object you want to transform with said transform into input 1 ("0"). 

MAKE SURE the transform node has the xform ticked at the bottom, so the wrangle can actually access the "xform"

This is especially relevant for when you overuse $CEX etc bounding box for pivots & you suddenly change the geo size. Eg you rotate your thing into place, and do so using the centre of a short object, but suddenly you need to substitute it with a much taller thing.

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;

Tuesday 3 September 2019

rotating point normals, with vops

To rotate a point's normals (or any vector for that matter) you need to multiply it with a matrix and an angle (usually in radians) and around a specified axis.

A much neater/easier-to-grasp method is to use a VOP.
Give your points some initial Normal values, eg point them in X.

Make a point VOP.
Connect the N output into a multiply. We want to multiply this N vector and get a vector output.
The output of the multiply should go to the N output.

Make a DegToRad node (skip if you speak radians) and connect that to the angle input of a Rotate node. Promote the DegToRad's angle input so you can tweak it at object level.

In the Rotate node, set the vector that you wish to spin the normal vector around. It might be Y. 0,1,0.
Or you could be doing something  cool like calculating the vector that an edge lies on and spinning something around that.

Connect the output of the Rotate to the second input of the Multiply.

Now jump back out of the VOP and you should be able to see your normals rotating when you change the angle input.

-------------------------------------------------------

Of course this is just a couple, maybe one, of lines in VEX, but who really has time to memorise that? heh.

Wednesday 19 June 2019

rotate packed primitives/ WALTER ROTATE

how to rotate a/bunch of packed primitive/s -
Use a WALTER ROTATE.

in a primitive wrangle:


float randomFactor=rand(@primnum+2323)*chf("randomMult");
matrix3 rot = primintrinsic(0, "transform", @primnum);
vector4 orient = quaternion(rot);
vector x = normalize(qrotate(orient, {1,0,0}));
vector y = normalize(qrotate(orient, {0,1,0}));
rotate(rot, radians(chf("angle") * randomFactor), x);
rotate(rot, radians(chf("angley")), y);
setprimintrinsic(0, "transform", @primnum, rot);

//////////////////
what we are doing is:
  • making a random factor to multiply the rotations, using primnum as a seed
  • creating a matrix called "rot", and initialising it to the transform of the primitive
  • create a vector called "orient", using the quarternion of the rot matrix
  • create vectors x and y
  • rotate the rot matrix using input angles for x and y
  • then finally set the primitive intrinsic using the rot matrix