Apply rotation matrix to single vertex?
Hi, I'm designing code to animate a simple 3D character model in openGL, and I have read about the concept of a "mesh": the notion of having one global list of triangles, which aren't owned by any particular part/bone, but rather assigning the vertices to parts & subjecting the vertices alone to appropriately interpolated translations and rotations at each frame (and then drawing triangles between those transformed vertices).
Translating a single vertex is easy, but I am unsure as to how to subject individual vertices to rotation matrices efficiently (glRotatef says it won't work in between "glBegin" and "glEnd" which strikes me as odd). I realize I can do all the calculations "by hand" on the CPU, but given all the hardware acceleration options in openGL and what seems to be a problem inherent to mesh-animation I would think there would be a way to do it on the GPU.
Any ideas? Why doesn't openGL want you applying standard glTranslatef/glRotatef to vertices within Begin/End blocks? Or is doing the matrix multiplication manually my best bet? Thanks in advance for any assistance in this matter.
I think you safest bet would be to do the matrix multiplication manually and use glMultMatrixf. I have skeletal animation in my engine and it does not contribute a huge performance hit to manually calculate each matrix.
Hmm... I looked at glMultMatrixf and it said something like "GL_INVALID_OPERATION is generated if glMultMatrix is executed between the execution of glBegin and the corresponding execution of glEnd" same as for glTranslate and glRotate. I can easily enough write code to explicitly multiply out each row of a matrix with a vertex position vector, but it seems like you are doing something better.
How does your engine do the glMultMatrix operation to only one or two of the vertices in a triangle and not the whole shape? Once again to clarify I am talking about the skin/mesh triangles drawn between vertices on different body parts, like the flap of skin that covers up the elbow joint for example.
How does your engine do the glMultMatrix operation to only one or two of the vertices in a triangle and not the whole shape? Once again to clarify I am talking about the skin/mesh triangles drawn between vertices on different body parts, like the flap of skin that covers up the elbow joint for example.
Your mention of glMultMatrix implies you're trying to coerce the engine into doing matrix math for you.
I don't what language you're using but if it's OOP, I'd suggest creating a MATRIX class. It will make life pretty simple for animation. Include class operations like creating Identity, Rotation, and Translation matrices, and operator overrides for MATRIX*MATRIX and VECTOR*MATRIX.
The "mesh" you mention is just a buffer of structures, each holding a vertex, a normal (maybe), a set of tex coords, influence bone indices and bone weights.
Just for the sake of definition, a "bone" is a transformation matrix. The "bones" can be nothing more than an array of matrices*. Each vertex in the mesh has a set of bones that influence it and a bone "weight," or what fraction of 1.0 is to be applied to the result of the vertex being multiplied by the bone matrix. All the influences for a vertex add up to 1.
*If you think about it, you'll want each "bone" to have a parent bone. When a shoulder bone is rotated, the upper arm bone, the lower arm bone and the hand bones all need to rotate, too, so the upper arm is parented to the shoulder, the lower arm bone to the upper arm bone, and the hand bones to the lower arm, etc.
Using, as an example, the skin at the elbow: the "skin" at the elbow would be described by a set of vertices (forming triangles which, when rendered, appear to "skin" the elbow). Each of those vertices would be influenced by the Bicept bone and the Arm bone. The vertices closer to the Bicept would be weighted more by the Bicept (and similarly for the vertices closer to the Arm).
Each frame:
1. update each bone matrix (by the delta time from the last frame) - easy to say but you'll have to figure out how to tell each bone what it's to do at a particular time - that's the animation problem.
2. with the bones "positioned," for each vertex, calculate a vector = vertex * bone-matrix for each influence bone. The vertex position = vector1*weight1 + vector2*weight2.
If you have (or can have) DirectX libraries linked, you can use the D3DXMATRIX and D3DXVECTOR3 classes for all the manipulations. You don't need to initialize Direct3D to use the D3DX library functions and classes.
I don't what language you're using but if it's OOP, I'd suggest creating a MATRIX class. It will make life pretty simple for animation. Include class operations like creating Identity, Rotation, and Translation matrices, and operator overrides for MATRIX*MATRIX and VECTOR*MATRIX.
The "mesh" you mention is just a buffer of structures, each holding a vertex, a normal (maybe), a set of tex coords, influence bone indices and bone weights.
Just for the sake of definition, a "bone" is a transformation matrix. The "bones" can be nothing more than an array of matrices*. Each vertex in the mesh has a set of bones that influence it and a bone "weight," or what fraction of 1.0 is to be applied to the result of the vertex being multiplied by the bone matrix. All the influences for a vertex add up to 1.
*If you think about it, you'll want each "bone" to have a parent bone. When a shoulder bone is rotated, the upper arm bone, the lower arm bone and the hand bones all need to rotate, too, so the upper arm is parented to the shoulder, the lower arm bone to the upper arm bone, and the hand bones to the lower arm, etc.
Using, as an example, the skin at the elbow: the "skin" at the elbow would be described by a set of vertices (forming triangles which, when rendered, appear to "skin" the elbow). Each of those vertices would be influenced by the Bicept bone and the Arm bone. The vertices closer to the Bicept would be weighted more by the Bicept (and similarly for the vertices closer to the Arm).
Each frame:
1. update each bone matrix (by the delta time from the last frame) - easy to say but you'll have to figure out how to tell each bone what it's to do at a particular time - that's the animation problem.
2. with the bones "positioned," for each vertex, calculate a vector = vertex * bone-matrix for each influence bone. The vertex position = vector1*weight1 + vector2*weight2.
If you have (or can have) DirectX libraries linked, you can use the D3DXMATRIX and D3DXVECTOR3 classes for all the manipulations. You don't need to initialize Direct3D to use the D3DX library functions and classes.
I think I'm making some faulty assumptions about how openGL modelview matrix operations work...
Yeah, I am trying to coerce openGL to do the matrix math for me, at least to do it efficiently & on the GPU if possible. I figured having to constantly be sending vectors from the CPU each frame would be inefficient in the same way that drawing primitives in immediate mode is inefficient compared to putting the vertex arrays into GRAM.
But I guess that doing dynamic modelview transformations on, say, display lists is just as inefficient... you still have to send the transformation vectors from main memory, right. I suppose the matrix multiplication in that case is in fact done on the GPU since thats where the display list data is stored, but in a per-vertex case it doesnt really matter I would have to send a vector over the bus in either case. So I guess I'm just looking for an optimization that isn't possible. My bad.
Thanks for the help.
Yeah, I am trying to coerce openGL to do the matrix math for me, at least to do it efficiently & on the GPU if possible. I figured having to constantly be sending vectors from the CPU each frame would be inefficient in the same way that drawing primitives in immediate mode is inefficient compared to putting the vertex arrays into GRAM.
But I guess that doing dynamic modelview transformations on, say, display lists is just as inefficient... you still have to send the transformation vectors from main memory, right. I suppose the matrix multiplication in that case is in fact done on the GPU since thats where the display list data is stored, but in a per-vertex case it doesnt really matter I would have to send a vector over the bus in either case. So I guess I'm just looking for an optimization that isn't possible. My bad.
Thanks for the help.
Your best off using shaders, you can send the matrices for each bone, and also have per-vertex ID's like "bone1" (same as per-vertex normals,texcoords), then you would multiply by bone1 matrix.
AFAIK you have two options:
1) Do the animation on the CPU, i.e. transform each vertex manually before sending it to the GPU. The advantage is the flexibility and that you don't have many restrictions (you may have an arbitrary number of bones and bone weights), the disadvantage is the performance problem, since it's more work for the CPU and the vertices need to transferred to video memory every frame or at least whenever the vertices change.
2) Use the GPU, but for that you'll need shaders. You flag the vertices with vertex attributes (boneID, weight) and pass the matrices as shader constants. The advantage is better performance since all you have to transfer to the GPU are the matrices and the CPU has a lower workload, but you have a limit on the number of bones (depends on the number of constant registers) and the number of bones per vertex (depends on the number of vertex attributes).
1) Do the animation on the CPU, i.e. transform each vertex manually before sending it to the GPU. The advantage is the flexibility and that you don't have many restrictions (you may have an arbitrary number of bones and bone weights), the disadvantage is the performance problem, since it's more work for the CPU and the vertices need to transferred to video memory every frame or at least whenever the vertices change.
2) Use the GPU, but for that you'll need shaders. You flag the vertices with vertex attributes (boneID, weight) and pass the matrices as shader constants. The advantage is better performance since all you have to transfer to the GPU are the matrices and the CPU has a lower workload, but you have a limit on the number of bones (depends on the number of constant registers) and the number of bones per vertex (depends on the number of vertex attributes).
A skinned mesh example is available at moon-labs. It's written for DirectX, but, from it, you can get an idea the concept of the matrix manipulations.
It also comes with an HLSL shader which you should be able to translate for OGL. That will also give you an idea of the per-vertex information that's needed.
Certainly getting the GPU to do as much as you can is the way to go. Unfortunately, there's a lot of work per-frame that has to be CPU based (e.g., updating the bone hierarchy matrices) which are not per-vertex.
It also comes with an HLSL shader which you should be able to translate for OGL. That will also give you an idea of the per-vertex information that's needed.
Certainly getting the GPU to do as much as you can is the way to go. Unfortunately, there's a lot of work per-frame that has to be CPU based (e.g., updating the bone hierarchy matrices) which are not per-vertex.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement