Apply rotation to a single vertex

Moderator
Posts: 133
Joined: 2008.05
Post: #1
I have an object that rotates around it's origin. I want to be able to apply the rotation to a single vertex to figure out what the new vertex is.

Basically, I pick a vertex that is connected to another object that could be anywhere in the object, and want to find out where to move it in order for them to be connected at that same spot again after the rotation.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #2
Multiplying all your object vertices by the same rotation matrix will get you a properly rotated object. Are you asking for the transform order or the basics of matrix multiplication?

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #3
I understand matrix math, but either I'm doing it wrong or I am ... doing it really wrong.

Let me just use an example...

in my modelchain class, there is a vertex called jointVertex, which is a vertex that could be located anywhere on the object, depending on where it's connected to it's parent. I also have variables called xRot, yRot, and zRot which are the angles which the object should be rotated.

When I draw it, I call glRotatef and draw it. Obviously, this just rotates it around the origin and it detaches itself from the parent at that vertex. I need to take this vertex, jointVertex, and perform a calculation on it based on how much the object was rotated in order to find out where that vertex is after the rotation. Then I can translate the object to a place where the jointVertex is in it's original location and the model is essential "hanging" from that vertex after the rotation.
Quote this message in a reply
kberg
Unregistered
 
Post: #4
LongJumper Wrote:I understand matrix math, but either I'm doing it wrong or I am ... doing it really wrong.

Let me just use an example...

in my modelchain class, there is a vertex called jointVertex, which is a vertex that could be located anywhere on the object, depending on where it's connected to it's parent. I also have variables called xRot, yRot, and zRot which are the angles which the object should be rotated.

When I draw it, I call glRotatef and draw it. Obviously, this just rotates it around the origin and it detaches itself from the parent at that vertex. I need to take this vertex, jointVertex, and perform a calculation on it based on how much the object was rotated in order to find out where that vertex is after the rotation. Then I can translate the object to a place where the jointVertex is in it's original location and the model is essential "hanging" from that vertex after the rotation.

Ah, now thats not too bad...
Code:
glTranslatef(-center_vertex.x, -center_vertex.y, -center_vertex.z);//Move object so that vertex you want to rotate about is at 0, 0, 0...
glRotatef();//perform rotation
glTranslatef( center_vertex.x,  center_vertex.y,  center_vertex.z);//Return object to original position
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #5
Er, sorry, I don't think I'm explaining it well enough.

I will explain the problem in more detail.

I have a figure I created in poser, broken up into important limbs(at least important to what I am doing). Now, when I load it in with your obj loader, I call a function I created called DropToGround, which basically puts the center point of every single limb at 0,0,0. Here is where I do my rotations, so that they are properly rotated around their origin instead of the circle that Poser creates.

So now, if I translate back to it's original position(which I have retained), the object is rotated properly, but it is not connected to the body as it should be. In order to account for this, when the object is loaded and attached to a parent(say, left shoulder to the torso), it finds every single vertex that the torso and left shoulder share. These are my shared vertices.

In order to keep the person "together", I've selected one of the shared vertices to be the joint vertex. This joint vertex is where the two objects always touch, and they are picked in a way to prevent skewing. As an example, the thigh and calf connect behind the knee, so that when I bend it and reconnect the two objects, I can draw extra triangle strips to draw the knee, while the back of the knee is just a straight connection.

The problem is this, however, when I rotate my object about it's origin, the joint vertex has obviously been moved a small amount. Example, if I rotated -45 degrees, the joint vertex of the left shoulder, which is on the left edge of the left shoulder, the joint vertex would be moved up and to the right some. ( Here is bicep before rotation: - , here is bicep after rotation: \ )

What I need to find is where the joint vertex has been moved after rotation, because then I can simply take the difference of where the joint vertex is on the torso that the left shoulder is supposed to append to and the new location of the joint vertex on the arm, and translate it to that new position.

What I was thinking was, there was some way to apply the rotation matrix to a single vertex in order to find it's new coordinates.
Quote this message in a reply
Member
Posts: 184
Joined: 2004.07
Post: #6
I think what you want to do is take your vertex and multiply it by the same matrix you're using for your model transform.

Normally you'd do something like

glmatrixmode(modelview)
glrotate(your rotation)
glvertex(your joint vertex)

and I assume that instead of sending the vertex to the OpenGL pipeline, you want to just figure out where it's going to be transformed to. You can get the matrix with glGetDoublev(GL_MODELVIEW_MATRIX, your matrix). So it'd be something like this:

glmatrixmode(modelview)
glloadidentity()
glrotate(your rotation)
glDouble m[16];
glGetDoublev(GL_MODELVIEW_MATRIX, m);
your transformed joint vertex = matrixMultiply(your joint vertex, m); //you have to write this yourself or copy it from somewhere.
Quote this message in a reply
kberg
Unregistered
 
Post: #7
Code:
struct Matrix4
{
   float e[16];
};

//Set matrix dst to the identity matrix
void  Mat4_idnt(Matrix4& dst);

//Multiply matrices src1 and src2 together and put the result in dst
void  Mat4_mul (Matrix4& dst, const Matrix4& src1, const Matrix4& src2);

//Make a GL style rotation matrix (axis, angle..) and multiply it with the matrix in src
void  Mat4_rot (Matrix4& dst, const Matrix4& src, float a, float x, float y, float z);

//Multiply x, y, z by the matrix src
void  Mat4_vmul(const Matrix4& src, float& x, float& y, float& z);

Code:
void Mat4_idnt(Matrix4& dst)
{
   dst.e[ 0] = 1.0;
   dst.e[ 1] = 0.0;
   dst.e[ 2] = 0.0;
   dst.e[ 3] = 0.0;
   dst.e[ 4] = 0.0;
   dst.e[ 5] = 1.0;
   dst.e[ 6] = 0.0;
   dst.e[ 7] = 0.0;
   dst.e[ 8] = 0.0;
   dst.e[ 9] = 0.0;
   dst.e[10] = 1.0;
   dst.e[11] = 0.0;
   dst.e[12] = 0.0;
   dst.e[13] = 0.0;
   dst.e[14] = 0.0;
   dst.e[15] = 1.0;
}

void Mat4_mul (Matrix4& dst, const Matrix4& src1, const Matrix4& src2)
{
   float a11 = src1.e[ 0], a12 = src1.e[ 1], a13 = src1.e[ 2], a14 = src1.e[ 3];
   float a21 = src1.e[ 4], a22 = src1.e[ 5], a23 = src1.e[ 6], a24 = src1.e[ 7];
   float a31 = src1.e[ 8], a32 = src1.e[ 9], a33 = src1.e[10], a34 = src1.e[11];
   float a41 = src1.e[12], a42 = src1.e[13], a43 = src1.e[14], a44 = src1.e[15];

   float b11 = src2.e[ 0], b12 = src2.e[ 1], b13 = src2.e[ 2], b14 = src2.e[ 3];
   float b21 = src2.e[ 4], b22 = src2.e[ 5], b23 = src2.e[ 6], b24 = src2.e[ 7];
   float b31 = src2.e[ 8], b32 = src2.e[ 9], b33 = src2.e[10], b34 = src2.e[11];
   float b41 = src2.e[12], b42 = src2.e[13], b43 = src2.e[14], b44 = src2.e[15];

   dst.e[ 0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
   dst.e[ 1] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
   dst.e[ 2] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
   dst.e[ 3] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;

   dst.e[ 4] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
   dst.e[ 5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
   dst.e[ 6] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
   dst.e[ 7] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;

   dst.e[ 8] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
   dst.e[ 9] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
   dst.e[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
   dst.e[11] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;

   dst.e[12] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
   dst.e[13] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
   dst.e[14] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
   dst.e[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
}

void Mat4_rot (Matrix4& dst, const Matrix4& src, float a, float x, float y, float z)
{
   float Sa = sinf(a);
   float Ca = cosf(a);
   float len = x * x + y * y + z * z;
   if (len != 0.0f)
      len = 1.0f / sqrtf(len);
   x *= len;
   y *= len;
   z *= len;

   Matrix4 rot;
   rot.e[ 0] = x * x * (1.0f - Ca) + Ca;
   rot.e[ 1] = x * y * (1.0f - Ca) - z * Sa;
   rot.e[ 2] = x * z * (1.0f - Ca) + y * Sa;
   rot.e[ 3] = 0.0;
   rot.e[ 4] = y * x * (1.0f - Ca) + z * Sa;
   rot.e[ 5] = y * y * (1.0f - Ca) + Ca;
   rot.e[ 6] = y * z * (1.0f - Ca) - x * Sa;
   rot.e[ 7] = 0.0;
   rot.e[ 8] = z * x * (1.0f - Ca) - y * Sa;
   rot.e[ 9] = z * y * (1.0f - Ca) + x * Sa;
   rot.e[10] = z * z * (1.0f - Ca) + Ca;
   rot.e[11] = 0.0;
   rot.e[12] = 0.0;
   rot.e[13] = 0.0;
   rot.e[14] = 0.0;
   rot.e[15] = 1.0;

   Mat4_mul (dst, rot, src);
}

void Mat4_vmul(const Matrix4& src, float& x, float& y, float& z)
{
   float a11 = src.e[ 0], a12 = src.e[ 1], a13 = src.e[ 2], a14 = src.e[ 3];
   float a21 = src.e[ 4], a22 = src.e[ 5], a23 = src.e[ 6], a24 = src.e[ 7];
   float a31 = src.e[ 8], a32 = src.e[ 9], a33 = src.e[10], a34 = src.e[11];
   float tx = x;
   float ty = y;
   float tz = z;

   x = a11 * tx + a12 * ty + a13 * tz + a14;
   y = a21 * tx + a22 * ty + a23 * tz + a24;
   z = a31 * tx + a32 * ty + a33 * tz + a34;
}

These are some code snippets from my transformation matrix library. It allows you to perform axis angle rotations just like opengl. I've left the other types of tranforms (translate, rotate) out since they are trivial to implement, however the matrices in this code are transposed from how opengl stores them; so if you want to multiply the modelview matrix with one you generate from this code for some odd reason, remember to transpose it first.

To rotate a vertex and get its new position:
Matrix4 temp;
float new_pos.x = my_vertex.x;
float new_pos.y = my_vertex.y;
float new_pos.z = my_vertex.z;

Mat4_idnt(temp);
Mat4_rot (temp, temp, angle, x, y, z);
Mat4_vmul(temp, new_pos.x, new_pos.y, new_pos.z);

Now new_pos contains the new position of that vertex.
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #8
Works perfect. Karl, I love you. Love
Quote this message in a reply
kberg
Unregistered
 
Post: #9
LOL! Well, not exactly what I was looking for.. LOL

But anyways, now that its working there is potential for lots of optimisation there. For example, a full 4x4 matrix multiply by the identity matrix is a silly thing to do if all you'll ever be doing is a single rotation with no other transformations.

I look forward to seeing what you're up to, sounds interesting...
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Changing Uniform Variables for a Single Shader reapz 3 5,219 Jul 15, 2010 01:29 AM
Last Post: dazza
  Texture mapping single 3D object with one draw call jeonghyunhan 1 2,583 Jul 13, 2009 06:05 AM
Last Post: ThemsAllTook
  Single buffered window Rasterman 9 5,613 Oct 15, 2007 10:40 AM
Last Post: ThemsAllTook
  glTexImage2D() and single colour component textures sealfin 3 4,457 Aug 10, 2004 04:45 AM
Last Post: arekkusu
  Quaternion rotation -> OpenGL rotation matrix? DJBlufire 3 3,750 Sep 6, 2003 08:34 PM
Last Post: MattDiamond