CSS3 Matrix rotation
I have a CSS 3D cube that I’m trying to rotate left/right/up/down straight as it appears to user. If I use css
rotation functions, then I rotate the axis, not the cube.
There are lots of articles on the web about X,Y,Z matrix rotation calculation, but I’ve spend days now trying to set this thing and none of this information really helps me.
The work around to my problem would be a
WebKitCSSMatrix object, which has its own rotation functions that work as magic. An example on Fiddle: http://jsfiddle.net/joecritch/tZBDW/. But again, that relies only uppon Webkit, but I need to be crossbrowsy here.
Now, there are 3 steps on the way of success:
1) I need to get current matrix, set directional vector (1,0,0 for up/down and 0,1,0 for left/right rotations) and set the angle. DONE.
2) I need to calculate new rotation vector based on current matrix. DONE.
3) I need to actually rotate my current matrix by new vector and angle. PROBLEM.
var newMArray = deMatrix(".cube");//getting current matrix from CSS var v = [vecX, vecY, vecZ, 0];//current vector (1,0,0) or (0,1,0) var newV = newMVector(newMArray, v);//calculating new vector for current matrix //getting the angle for each axis based on new vector angleX = newV*angle; angleY = newV*angle; angleZ = newV*angle; this.rotateX -= angleX; this.rotateY -= angleY; this.rotateZ -= angleZ; //calculating the rotation matrix var rotationXMatrix, rotationYMatrix, rotationZMatrix, s, transformationMatrix; rotationXMatrix = $M([[1, 0, 0, 0], [0, Math.cos(this.rotateX * deg2rad), Math.sin(-this.rotateX * deg2rad), 0], [0, Math.sin(this.rotateX * deg2rad), Math.cos(this.rotateX * deg2rad), 0], [0, 0, 0, 1]]); rotationYMatrix = $M([[Math.cos(this.rotateY * deg2rad), 0, Math.sin(this.rotateY * deg2rad), 0], [0, 1, 0, 0], [Math.sin(-this.rotateY * deg2rad), 0, Math.cos(this.rotateY * deg2rad), 0], [0, 0, 0, 1]]); rotationZMatrix = $M([[Math.cos(this.rotateZ * deg2rad), Math.sin(-this.rotateZ * deg2rad), 0, 0], [Math.sin(this.rotateZ * deg2rad), Math.cos(this.rotateZ * deg2rad), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]); transformationMatrix = rotationXMatrix.x(rotationYMatrix).x(rotationZMatrix);//getting all axis rotation into one matrix
Than I’m setting new transformation matrix to my CSS Cube. The problem is – it doesn’t rotate as it should. Now I’m using
Sylvester plugin to do all matrix calculation.
So, please help me on how to use my new vector for proper matrix rotation.
I am having a very hard time following your code. But if I understand it correctly you are going around a basic problem really backwards.
Your starting point is an object that has a matrix transform. You want to change that transform. At this point it is very tempting to just try things and see what sticks. No offense, but that is what your code looks like it is doing. What you really need is to understand how matrices work. There are lots of good tutorials. (first google hit: http://chortle.ccsu.edu/vectorlessons/vectorindex.html) It will take some time but help a lot in the long run.
The basic issue you are facing is that matrix multiplication is no commutative. A * B != B * A for matrices. Depending on what matrix you are setting it includes a lot of transformations where order matter: (A) Move the object to it’s origin (B) Rotate the object around it’s origin (C) Move the object to a position in the world (D) Move the object to where the camera is at the origin (E) Rotate around the camera. The matrix you see is just A * B * C * D * E. Now depending on what you want to do you better have a good plan. In most cases you either want to rotate the object or the camera and you can just multiply either on the left or right side. Your code looks a little bit like you are multiplying on the wrong side and trying to jump through hoops to compensate for that which somewhat works because a lot of the matrices are identity.
So even more practical: Get your cube matrix, make a rotation matrix independent of it (no -angle!), and set back rotation*cubematrix as your new transform.
Sylvester can generate rotation matrixes as well. Looking at the fiddle example – the webkit function that seems to do the rotation:
// Rotate the Matrix around the transformed vector var newMatrix = m.rotateAxisAngle(vector.x, vector.y, vector.z, angle);
Looks like it’s more along the lines of the
Matrix.Rotation(angle [, axis]) function, I think you’d provide
axis as a Sylvester Vector object, rather than the webkit x,y,z arguments – http://sylvester.jcoglan.com/api/matrix.html#rotation
Multiplying the x,y,z matrices doesn’t work too well because the additional transforms will be applied on the new context. I’ve just fallen into this trap with this js/canvas page: http://benjaminbenben.com/projects/twittny_test/