   Problems with skinning
  Hi! I'm trying to handle skinned models with joints in my current application.However, I seem to fail to grasp how the position updates to vertices are done based on their weights and the joints they are based upon. I've also tried searching for a good tutorial or article to explain this, though none of those I've found actually gives me a good description of this. It's always some uncommented code-example or similiar that takes hours and hours to figure out and still seem to fail.What I do (which seems to fail) is:I iterate through all my skinclusters, where I iterate through each indice, where an indice is basically a 3-integer where each integer represents a vertice in a list. Each indice describes one triangle. Each vertice contains up to 4 influences. Where each influence is a weight and an integer that points to a joint in a list. So what I do each update is that a vertice's position is:first calculate the position of the vertice multiplied by the world-matrix for each joint that influences that vertice, named P. I then multiply P by its weight. I then take the position of the vertice, and updates it to the current position multiplied by P, for each joint.for each joint influencing vert with world matrix W and weight w:P = vert.pos * W;P = P * w;vert.pos *= P;Though this doesn't seem to work. All help is greatly appriciated.Edit:I thought I might add that some of my vertices gets undefined position values (which in opengl is drawn as 0, 0, 0) Best regard,Simon.[Edited by - simpeman on December 6, 2005 7:53:45 AM]
  Hi,Are you factoring in the bind position of the joints? It doesn't sound like it. If your skin is warping outwards in weird ways, there is a good chance that you need to remove the joints' initial transformation from their current world transformation, before multiplying the vert by them.Also, you didn't mention if you were summing up the weighted vert positions.;  Well, it's all in bind-pose I just want it to show up correctly. Though I'm not removing the joints bind-pose position from their current position, no. I guess that's a part of the problem. I'm also writing a maya-exporter which I'm having a few difficulties to see if I really export all correctly. I mean, I can get the model and draw it up as it looks like in maya. And I can draw the bones correctly so I'm hoping that the only problem has to do with the skinning info, which I'm not sure if I'm exporting properly. Yeah, I'm summoning up the weighted vert positions.I'm wondering though, is there any place where I can get a good article or how-to about skinning? The algorithms needed, information needed etc. I know there are a few different methods out there but isn't there one method that's sort of common? Anyway, if there's anyone that knows where there is anything similiar, I would be really grateful.And thanks for the answer TomBlind :)Best regards,Simon.   ;  Hmmm... To be honest, I've never really seen a good article on skinning. I think it's one of those guarded secrets or something. But anyway, if you've got the mesh and skeleton rendering correctly, you're probably pretty close. Here's what I do:1.) Multiply the joint's current transformation (world space) by the inverse of the joint's bind transformation (world space). This removes the bind.2.) Transform the vert by the resulting matrix from #1. If you were only using 1 influence, you would be done here.3.) Scale the result from #2 by the weight of that vert on that joint.4.) Repeat for each joint weighted to the vert. Sum the weighted verts together to get the final vert position.I hope this is helpful!;  Hi again Tom :)And thanks for the answer!I've now tried what you said, to inverse the bindpose position for all joints and multiply the current joint position for each joint position when I calculate the new position for each vertice. However I'm uncertain wether I should use the bindpose position for the vertice or their last position? Anyway, as it looks like now I get the original skin at the first frame and then it all just goes away. However I haven't debugged this to see what actually happens, though I will do that as soon as I get the time. Edit:After some debugging, it seems as if I get very big negative Z values. (really too big) though the other values for the position seems to be correct. Could this be due to me thinking in rows major instead of column major somewhere? I know for a fact that the matrix multiplication is done column major so that should be correct. However I'm uncertain about how to calculate the inverse of a matrix such as this. But I thought that the matrixes in opengl are orthonormal base and such the inverse is equal to the transpose of a matrix? Which is pretty much turning a column major matrix into a rows major matrix isn't it?Any help is greatly appriciated.Once again, thanks for helping out :) Best regards,Simon.[Edited by - simpeman on December 8, 2005 4:56:03 PM];  Careful there. The transposed of the _rotational_ part is the inverse of _rotational_ part, if it's orthonormal, if your matrices include the translation you can't just transpose the whole thing. You would have to transform the translation/position part with the transposed rotation part as well.I'm also confused about how you update your vertices, as you were talking about indices. I hope you don't step through all indices, and pick the vertices from that or you will end up transforming a lot of vertices multiple times.Also, a basic thing to consider is what your vertices look like before you do anything to them. I assume they already are in their bind pose, if only their z is looking wrong. But keep in mind that for the bind pose you are pretty much replacing all bones with identity matrices which isn't all that exciting. But at least it's easier to check for errors, if any bone is NOT the identity when you apply the transformation then something is wrong.Think of what you are doing as subtracting the bind pose from the current pose to get the difference. As all your vertices seem to come in their bind pose this difference is what you want. So obviously you always apply it to the original set of vertices.optional bla bla and ramblings ahead:Alternatively (though this might get messy) you could always use the inverse of the last bone matrix to get the difference between this and the last frame. This would then be applied to the current vertex data.The benefit of that would be that storing your animations will likely require less space, as at some point most joints will be different from their bind pose (seeing how the bind pose isn't exactly natural). By storing only the difference between the animation "frames" you would be doing what video compression does. The downside is that by only storing differences you could never "reset" the model or force it into a pose, especially if you want to apply "on the fly" changes (ragdoll physics or whatever) that would be ugly to combine with prepared animations. Unless you do what videos do and store are a "complete" keyframe with absolute (or relative to bind pose) matrices.But before you start doing clever things to optimize away, I would store the inverse of the bind pose for each bone, it's position/orientation relative to its parent and the resulting absolute data. After applying all local changes (to the relative to parent data) you traverse the skeleton, calculate the absolute data based on the parent and then do a second pass applying the inverse to the absolute data to get what you want to transform the vertices with.   ;  I'd be willing to bet the inverse is your problem. Like Trienco said, orthonormal matrices can be inverted with a transpose, but only the rotational part. If you are not doing any scaling (which I doubt you would need to) you want to:1.) Store the position part of the matrix.2.) Zero out the position in the matrix.3.) Transpose to invert the rotation,4.) Subtract the stored position from the position in the transposed matrix.;  I don't think simply subtracting will work. Unless I'm completely wasting time on three dot products between the three axes and the negated position. Unless of course you meant "multiply a matrix with the negated translation to the result".   ;  Hi, this is for xfiles, on Frank Lunas site, but the explanations also quite good, some of the links will open pdf files which you can save.http://www.moon-labs.com/ml_resources.htm   ;  You're probably right, Trienco. Transforming by a negated translation matrix would be the proper way of doing it. Just subtracting does work, the way I have implented it. I should look into why that is...