Getting rotation (normal?) from 3 points

If I have 3 points in space, how do I get the rotation of the triangle they form in either quaternion, angle/axis, or just x y z rotation format?

After looking at some forums I’ve been finding the normal by:

taking points a b &c
getting the cross product of: [a - b] and [b - c]

and I’ve tried finding the rotation of that vector with a cartesian to polar coordinate function, and some other secondary uses of cross products.

Should I be using a dot product in there?

I have a semi-functioning system to get the rotation between 2 points - I’m just trying to lock down erratic rotation when the points align on a certain plane. Using the methods above and others I’ve found, I still seem to be getting that erratic rotation when points align on a plane.

I don’t understand the question. You can rotate the triangle at will. Do you want to rotate around some particular axis which passes through a particular point in space?

No, it is not a good formula. If you assume that positive direction is CCW (mathematical orientation and default in GL), than normal can be get by either of the following formulae:

  • (b-a)x(c-a),
  • (c-b)x(a-b) or
  • (a-c)x(b-c)

It is a secondary school math. :slight_smile:

What for? If yo want to calculate angle between those edge-vectors, than yes. Dot product gives a cosine of the angle between vectors.

If I understand this well, you want to rotate an object around the axis that is perpendicular to a plane (that’s why you need a normal of the plane, since it is the axis you want to rotate around) in such way that two points define the angle of rotation (that’s why you need dot product). You also have to translate the rotation point to the center of the coordinate-system.

The problem is that you can get the rotation angles of the normal formed by that plane, but it will be mising at least one angle of rotations, because one normal is a vector and a vector can only give you two angles of rotation, one rotation to the sides and one to the front and back

since you know a vector is a line and a line can rotate by it self, it won’t change everytime you rotate it by its own axis, and thats the missing angle you will never get, you need at least two vectors, like a system of objects you will need a vector pointing top and a vector pointing the side of that vector

you already have the top vector, the normal, now you can use the cross product with one vector from the plane to give you the side vector, and from that you will have two vector perpendicular from them, having that you can get all the three rotation angles

but it will be much simpler if you start by having an object with all the three properties on it, the X, Y, Z rotation values stored by the start, and everytime it rotates it chages that values, because its too hard to get them everytime you rotate it

Hi Manuel - thanks for that, you’ve summarized what I’m trying to do, and the troubles I’ve had, well.

Maybe it would help if I described the problem I am solving - I am using a Kinect to get the position of joints from a human body - hands, elbows, shoulders, hips, etc. I then want to position 3d models joining those points (to create a humanoid form).

I have so far been grabbing 2 points for the limbs, minus one from the other for the vector, working out the rotation using a 3d cartesian-to-polar coordinate function then positioning the model with that rotation (just asimuth/elevation) at the midpoint between the two points.

This of course leads to the unknown 3rd axis you describe. So far I found it was controllable for the limbs by flipping the whole world ‘on its back’ so the y plane becomes the z plane. Before the arms would rotate erratically when they were hanging down in their natural position, now they only do it when pointing directly at the ‘camera’ that is the kinect and my viewpoint (not ideal, but minimizing their profile is enough for me).

I am working in an unusual development environment - Max/MSP; more well-known for its audio patching than 3d ability. This means I have some odd constrictions beyond the usual - for example I can access some gl commands (including setting the point of rotation for glrotate) directly using one technique, but it is slow with many models and doesn’t allow for advanced texture mapping, animation from 3d packages etc.

So I am left with a partial port of the mesh-handling from Ogre3d, which allows me to interact directly with meshes in limited ways like ‘rotation’ (axis/angle) ‘rotatexyz’ (self-explanatory) and position. AFAIK the translation point is always taken from the mesh, and can’t be moved.

With this in mind, I’m settling for what I’ve got when it comes to the limbs, but the torso (rotation taken from the shoulders) flips all the way over when the shoulders align along the apparent z plane (e.g. if the person turns sideways, it appears their own stomach jumps up and tries to swallow their head). This isn’t ideal either, so I was hoping to use one of the hip points as well to provide that third axis. But that then leaves me worried because it feels like theres nothing tying it to the broader ‘world-space’. In my (admittedly undeveloped) 3d gut I feel like I should be using a world-axis at some point.

And this is the state I find myself in - neither a programmer, nor a mathematician (I did get an ‘A’ in secondary school though- without knowing what a cross-product is!), but willing and able to learn.

So when we speak about using the method you posted

I’m afraid even that is challenging for me. For example, I can follow up to getting the two vectors, but then I’m unsure how to turn my two asimuth/elevations into 3 angles. And if you provide the maths, I’m unsure if I’ll be looking at quaternions, angle/axis, or straight up x y z (even then, 0-1 or 0-360, or radians…). I appreciate any guidance anyone can provide even just a link to a tutorial page and what format the end result will be (something I’m sure is taken for granted in opengl, but I’m using a lot of different units in Max/MSP world!).

First the method I said its only used to get the rotation angles from the vectors direction, wich means that having a vector pointing from 0, 0, 0 to 1, 0, 0 will give you a vector in the X axis with these rotations:

1, 0, 0
0, 0, 0

assuming the rotation starts from 0 to 360
the problem here are more than one, you dont know where the rotation starts because I only have one vector and that doensn’t give a starting point to count the rotation, and the ohter problem is that even if I have, wich one will I pick knowing that a perpendicular vector to this one can be infinite of them, because they belong to the same plane

but if you have:

this only works for the entire object, one cube or one piece made from many vertices and only one central point of rotation, wich you can change later

top vector
0, 1, 0 -> pointing Y, is pointin up
side vector
1, 0, 0 -> pointin X, is pointing side

these will be:
0, 0, 0 -> means 0 rotation on X, 0 rotation on Y, and 0 on Z

if I change the side vector to this:

0, 0, 1
0, 1, 0 -> the top remains the same because the rotation on side vector didn’t afect it

the rotation angles will be:

0, 90, 0
now you can see, why the top vector remains unchanged, and why a rotation can not affect the normal vector, so a rotation made in Y axis won’t change the top, and thats why you need the side for that

now for this, you have
a simple equation to get the angle from the direction of a vector:

  Size      = (VectorLength(Side)*VectorLength(YAxis));
  RotationVector = VectorCrossProduct(Side, YAxis);
  if Size == 0
      AngleOnY = 0
  else AngleOnY = arccos(VectorDotProduct(V, YAxis) /Size));

  if AngleOnY < 0
     AngleOnY := -AngleOnY;

this can give you a way to calculate the angles from each axis, and having each angles you can calculate other things

Hi Manel, I just got in late so I’ll have to read this tomorrow, but just wanted to apologise for calling you Manuel! Your code section looks like it will be very enlightening.