Convert a normal to a rotation


#1

Hey!

I want to take a surface normal, and rotate a directional light to point in the same direction as the normal. This is for a Nuke gizmo, and I only get normalized normals.

My first thought was to remap the normal, -0 = 0, 1 = 360, but I’m interested if there is a better approach.

Cheers!

Nick D


#2

i think i have not yet completely understand your issue. however you can create a matrix with your normal and two orthogonal normals to get a rotationmatrix which should make point the light in the same direction as the normal.

google for rotationmatrix and for look-at matrix

does that help?

grs
Patrik


#3

Take the normal (Y), take an upVector (it can be the lowest axis value of the vector), cross product the two, and the result is your second axis (call it X). Cross product the normal and the second axis again to have a third (Z).

Then just create a matrix with those three vectors, and set it as the rotation matrix of the light. I believe Nuke has all the facilities for this :slight_smile:


#4

Thanks guys, this just made me realise how much more I need to learn about vector maths (I just got my head around cross products about a week ago, havn’t even touched on rotation matricies yet!)


#5

You’re in luck, that’s the easy part :slight_smile:
Once you have your three vectors (remember to normalize them for good measure if you’re not sure whether your normal and upvector are guaranteed normalized and to avoid precision issues), you have your rotation matrix.
Depending on whether Nuke uses row matrices or column matrices, it will be:
X1, X2, X3
Y1, Y2, Y3
Z1, Z2, Z3

Or
X1, Y1, Z1
X2, Y2, Z2
X3, Y3, Z3

With X, Y and Z being your three vectors, and 1, 2 and 3 being their respective x, y and z components.

Formed that way, and if it comes from an upvector and a double crossproduct, you will have a 3x3 orthonormal matrix that’s your intended rotation matrix.


#6

Hey,

Just looking into this now and then while waiting on renders.

Did some tranformation/rotation matrix tutorials, and I have a much better idea on that now.

I’m not so sure about this “up vector”. A lot of resources refer to an up vector as (0,1,0). What is the context here?

Feel free to send me a book/website reference for all this :slight_smile:


#7

Next question: To convert the matrix to a XYZ rotation am i looking for a “matrix to euler rotation converstion”? The built in nuke function for this only works on 4x4 matrices

BTW: There are so many term in this area that go over my head, terms like afine and hetrogenous mean nothing to me. What’s a good resource that goes through all this?

Just for someone reference, this is where i’m up to (temp up vector)


 x = nuke.toNode("norm").knob("color").value()[0]
 y = nuke.toNode("norm").knob("color").value()[1]
 z = nuke.toNode("norm").knob("color").value()[2]
 
 normX = nuke.math.Vector3(x,y,z)
 upVector = nuke.math.Vector3(0,1,0)
 normY= normX.cross(upVector)
 normZ = normX.cross(normY)
 
 # convert the three vectors into a 3x3 matrix
 
 matrix = nuke.math.Matrix3()
 matrix.set(normX[0],normY[0],normZ[0],normX[1],normY[1],normZ[1],normX[2],normY[2],normZ[2])
 
 

#8

An UpVector is simply a reference vector that helps consolidating a transform.

Very simply, think of a (rotation) transform as a set of three orthonormal arrows (your X, Y and Z vectors).
If you have only one arrow (usually considered the AtVector, or the dominant axis of any derivative/heuristic process), your transform could be any of an infinite number of transforms rolling around that axis.

When you give it an UpVector, you are literally telling your process “this is up”, which is why it’s often assumed to be world Y. In the case of aligning something not roll sensitive (such as a circular spot light with no gobos) to a normal, you can take any given vector that’s not aligned to your AtVector, and you will be fine.
Once you have an At and an Up, you can always get a single consistent transform out of it.

As for 4x4 matrices, they are an extension of 3x3 that adds translation and homogeneization factors.
If you only need a world rotation and don’t care about the position (IE infinite lights), you can just pump your 3x3 into a 4x4 and leave the remaining values to those of an ID matrix.

In this case:
X1, X2, X3, 0
Y1, Y2, Y3, 0
Z1, Z2, Z3, 0
0, 0, 0, 1

That last row normally is your translation. So if you want your transform to also be positioned somewhere in space, pump a vector describing where it should be in that last row (again, I assume row matrices here, but I think that’s the case for Nuke).
The last column, 0,0,0,1 you can just ignore for now to save yourself some headaches, they aren’t needed when dealing with homogenous transforms. They will come into play though if you start dealing with distortion and space projection (perspective cameras, particular types of transforms and so on).

BTW: There are so many term in this area that go over my head, terms like afine and hetrogenous mean nothing to me. What’s a good resource that goes through all this?

Wiki hopping imo, but Vince’s “mathematics for computer graphics 2nd edition” is also an excellent and not overwhelming intro to many of these concepts.
Principles of computer graphics (or something like that) is also sort of a staple read, but it’s very succint, covers a lot of ground, and can be overwhelming almost instantly. It’s more of a reference for the already semi-educated.

The other problem you’re facing is that a lot of articles and books tend to treat subjects in their entirety too soon.
IE: to know how to align an object to a normal you absolutely don’t need to know about homogenous or etherogenous transforms, matrix affinity or any of those things, but because they are an important part of matrices and transforms as a general abstract, and you aren’t reading “applied” literature, you will be shovelled with that kind of stuff.

If you keep studying you will eventually learn some of those things, but more importantly, you will develop filters in your brain to approach new subjects progressively and an instinct for ignoring selectively what isn’t immediately necessary :slight_smile:
In my experience as a victim and a teacher both, I have found no other way around it but persistence and constant research, stubborness, and getting advice when available.


#9

Cheers Jaco, that all makes a lot of sense.

. In the case of aligning something not roll sensitive (such as a circular spot light with no gobos) to a normal, you can take any given vector that’s not aligned to your AtVector, and you will be fine.

Just to confirm, an upVector of (0,1,0) would be fine?


#10

It depends.
If you happened to have a polar item (one at the top and centre of the world facing either way up or down), no. Its at vector (direction) would be 0,1,0 or 0,-1,0
With an up vector of 0,1,0 your cross product would be a 0 vector, and you wouldn’t have a solid transform.
Up and At can’t align, or the world implodes (literally :slight_smile: ).

Sometimes there are issues with temporal consistency (IE: a rivet constraint of an item on a mesh’s point), which means you want an up vector reliable across time, but if you don’t have that constraint (IE you only transform things once or things that aren’t affected by roll), then it’s always safest to take the smallest component of your at Vector, and use a vector facing that way as upVector.

IE: if your at vector is 0.3, 1, 0.1
Then you can upvector by Z. This guarantees a reliable transform for any given vector.
If you have more than one minimum, any of them will do anyway, so you can just pick whatever comes first from a minAxis(vec) kinda call.


#11

Up and At can’t align, or the world implodes (literally :slight_smile: ).

Ha!

If you have more than one minimum, any of them will do anyway, so you can just pick whatever comes first from a minAxis(vec) kinda call.

Is the minAxis() your refereing to a vector minimum function,eg take two vectors and return the smallest one? I’m assuming so you never get two vectors facing the same way?


#12

myVec.minAxis() minComponent would just be an hypothetical method of a vector object which is rather common for APIs that deal with vectors, it usually returns which component of the vector is the smallest, either by value or by index.
It usually won’t return another vector but rather a float (at which point you have to find which component matches that float) or an integer for which of the three axis, but once you know if it’s X, Y or Z you can just create and use 1,0,0 or 0,1,0 or 0,0,1 as a vector accordingly.


#13

Cheers Jaco.

Nukes Vector3 class doesn’t seem to have a similar function:
http://www.nukepedia.com/reference/Python/_nukemath.Vector3-class.html

Can you point me to something that explains the math of this function, or even some c/python source code, and I’ll write a new function from scratch.

Cheers,

Nicko


#14

You simply need to find an axis that’s not the biggest, and take the world axis vector corresponding (assuming you are working in world space).

since you have x, y and z properties you can just brute your way through it


 #dirVec << this is the normal you want to transform to
  #upV << this is a vector object you created to use as upV, set it to 0,0,0 so you only have to change one axis to make it into a world axis
  
  if dirVec.x <= dirVec.y:
  	#then world X is suitable
  	upV.x = 1
  elif dirVec.y <= dirVec.z:
  	#the above is false, we check y against z next, if true world Y is suitable
  	upV.y = 1
  elif dirVec.z <= dirVec.x:
  	#both the above conditions are false, this should check true, and worldZ is suitable
  	upV.z = 1
 else:
 	print("something went horribly wrong, no two components of the vector make sense :P"
  

You’d better shout beers at the Bav the next time you swing by Fox Studios :slight_smile:


#15

Sweeet. This was vaguely work related, but has become more of an exercise in learning some of those things i’ve always avoided(eg anything with the word Matrix).

If you play your cards right, I’ll get you a cookie from subway.

Cheers Jaco!


#16

Something missing from above btw is that you should check the absolute values of the vector components, or it will go south for vectors with negative component values.
This is the last of it though. A subway cookie isn’t worth further effort I’m afraid :slight_smile:


#17

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.