2

I am trying to do skeletal animation with GLSL. For each bone, I have a translation(x,y,z) and a rotation(pitch, roll, yaw) (in degrees). I could construct a 4x4 matrix for each bone but that would take alot of register space in the shader, so I would like to only have to store the 6 values I have per bone, but I don't know how to do this.

Jonathan
  • 489
  • 1
  • 7
  • 18
  • What don't you know how to do? You can pass the values in as either 6 floats, or as 2 vec3s. Do you mean you don't know how to calculate the composed matrix of all the operations using those values? Also, are you sure that a single 4x4 matrix in a register is really a space problem? I imagine calculating the 4x4 matrix for each vertex or pixel is going to be processor intensive. Is that the trade-off you want to make? – user1118321 Jan 27 '12 at 17:18
  • Its not a single 4x4 matrix, its a 4x4 matrix per bone. What I don't know how to do is how to rotate a point using the rotation vec3 I have. – Jonathan Jan 27 '12 at 17:21

1 Answers1

6

What I don't know how to do is how to rotate a point using the rotation vec3 I have.

Simple: don't.

Yaw-pitch-roll is a terrible way to encode an orientation, especially for an animation system. Use a quaternion instead. It's 4 values rather than 3, and the code for rotation is well-known.

Also, it doesn't require heavy-weight operations like sin and cos.

If you want to compare and contrast the effort needed, consider the math.

Given a quaternion q, a position v, you need to do this to rotate it:

vec3 temp = cross(q.xyz, v) + q.w * v;
vec3 rotated = v + 2.0*cross(q.xyz, temp);

That's a fair bit of math. Now, consider what you have to do for your YPR case, given :

vec3 cosYPR = cos(ypr);
vec3 sinYPR = sin(ypr);

That's not everything. But that's enough. That's three cos and three sin operations. These are not fast operations. That alone probably takes about as long as the entire quaternion/vector rotation computation. But after doing this, you now have to do several multiplies and adds to compute the 3x3 matrix. And then, after all that, you still have to do the actual matrix multiply to rotate the vector.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • what would be more efficient? using quaternions or constructing a rotation matrix in the shader? – Jonathan Jan 27 '12 at 17:30
  • 3
    Shouldn't `vec3 rotated = v + 2.0*cross(q.xyz, temp);` be even more efficient (avoids 1 DOT and 1 MAD)? Though not sure if that requires unit quat and yours doesn't (but then again, who uses non-unit quats for rotations?). – Christian Rau Feb 06 '13 at 10:58
  • 1
    You say that `sin` and `cos` are heavy-weight. However, I've seen some people on the web say they are just one clock cycle on many GPUs. Can you point to any proofs about them being slow? – v.shashenko Dec 20 '17 at 17:12
  • @v.shashenko: I've seen people on the web say lots of things. Do you have any actual links? Also, do note that, even if each of those *vector-wise* sin/cos operations were one cycle, that doesn't take into account the cost of using them to build a matrix and then doing a matrix multiply. – Nicol Bolas Dec 20 '17 at 18:16
  • @NicolBolas: One of such links https://stackoverflow.com/a/11823383/1894053 – v.shashenko Dec 22 '17 at 16:09
  • @v.shashenko: Yes, one guy with 18 posts on Gamedev said they're single-cycle, so it totally must be true... The actual conversation on that link is kind of missing the point. For example, on AMD's pre-GCN hardware, they did indeed support single-cycle sin/cos operations. But it's one cycle *per-component*. Note that you actually need 3 sins and 3 coses. That's a lot more than 1 cycle. And again, as I pointed out, that doesn't take into account building the matrix from those values and doing the matrix multiply. Direct quaternion transform *always wins*. – Nicol Bolas Dec 22 '17 at 16:14