Apply rotation to a single vertex
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.
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.
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
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.
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.
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
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.
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.
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.
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.
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.
Works perfect. Karl, I love you.
LOL! Well, not exactly what I was looking for..
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...
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...
Possibly Related Threads...
Thread:  Author  Replies:  Views:  Last Post  
Changing Uniform Variables for a Single Shader  reapz  3  7,576 
Jul 15, 2010 01:29 AM Last Post: dazza 

Texture mapping single 3D object with one draw call  jeonghyunhan  1  4,174 
Jul 13, 2009 06:05 AM Last Post: ThemsAllTook 

Single buffered window  Rasterman  9  7,623 
Oct 15, 2007 10:40 AM Last Post: ThemsAllTook 

glTexImage2D() and single colour component textures  sealfin  3  6,029 
Aug 10, 2004 04:45 AM Last Post: arekkusu 

Quaternion rotation > OpenGL rotation matrix?  DJBlufire  3  5,197 
Sep 6, 2003 08:34 PM Last Post: MattDiamond 