CSS3矩阵旋转

23

我有一个CSS 3D立方体,我想让它直接向左/右/上/下旋转,就像用户看到的那样。如果我使用CSS rotation函数,则会旋转坐标轴而不是立方体本身。

网络上有很多关于X、Y、Z矩阵旋转计算的文章,但我花了几天时间尝试设置这个东西,但是这些信息都没有真正帮助到我。

解决我的问题的方法是使用WebKitCSSMatrix对象,它具有自己的旋转函数,可以像魔术一样工作。Fiddle上的示例:http://jsfiddle.net/joecritch/tZBDW/。但是,这仅依赖于Webkit,我需要在跨浏览器方面进行兼容。

现在,成功需要经历三个步骤:

1)我需要获取当前矩阵,设置方向向量(上/下为(1,0,0),左/右为(0,1,0)),并设置角度。完成。

2)我需要根据当前矩阵计算新的旋转向量。完成。

3)我需要实际旋转我的当前矩阵,使用新向量和角度。问题。

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[0]*angle;
angleY = newV[1]*angle;
angleZ = newV[2]*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

我将新的变换矩阵应用到了我的CSS魔方上。但问题是,它没有按照预期旋转。目前我正在使用 Sylvester 插件进行所有矩阵计算。

请帮助我如何使用新向量来正确地进行矩阵旋转。


9
“+1 for 'crossbrowsy' >.<” 的翻译是“支持‘跨浏览器’ >.<”。 - Barrie Reader
你的意思是它根本不旋转还是发生了一些疯狂的事情? - backdesk
嗯,它只是没有很好地旋转。发生了一个叫做“万向锁”的问题。所以我找到的这个问题的解决方案是使用CSS来在两个轴相交时互换它们之间的位置。对于更复杂的解决方案,有四元数,但同样地 - 一切都必须手动编写,因为CSS中没有这样的方法或库。 - Alex Under
2个回答

4
我很难跟上你的代码。但如果我理解正确,你是在绕过一个基本问题。你的起点是一个具有矩阵变换的对象。你想改变这个变换。此时非常诱人的是尝试各种方法并看看哪些有效。不冒犯,但你的代码看起来就是这样做的。你真正需要的是了解矩阵的工作原理。有很多好的教程。(第一个谷歌搜索结果:http://chortle.ccsu.edu/vectorlessons/vectorindex.html)这会花费一些时间,但从长远来看会有很大帮助。
你面临的基本问题是矩阵乘法不满足交换律。对于矩阵,A * B != B * A。根据你所设置的矩阵,包括许多转换,其中顺序很重要:(A)将对象移动到其原点(B)围绕其原点旋转对象(C)将对象移动到世界上的位置(D)将对象移动到摄像机位于原点的位置(E)围绕摄像机旋转。你看到的矩阵只是A * B * C * D * E。现在,根据你想要做什么,你最好有一个好的计划。在大多数情况下,你要么想旋转对象,要么想旋转相机,你可以将它们之一乘在左边或右边。你的代码看起来有点像你在错误的一侧进行乘法,并试图通过跳过这个问题来弥补这个问题,因为很多矩阵都是单位矩阵。
所以更实际的是:获取你的立方体矩阵,制作一个与其独立的旋转矩阵(没有角度!),并将旋转 * 立方体矩阵设置回你的新变换。

2
西尔维斯特也能生成旋转矩阵。观察小提琴示例 - 似乎执行旋转的webkit函数:
// Rotate the Matrix around the transformed vector
var newMatrix = m.rotateAxisAngle(vector.x, vector.y, vector.z, angle);

看起来更像是使用Matrix.Rotation(angle [, axis])函数,我认为您需要提供axis作为 Sylvester Vector 对象,而不是webkit的x、y、z参数- http://sylvester.jcoglan.com/api/matrix.html#rotation 将x、y、z矩阵相乘效果不太好,因为附加变换将应用于新上下文。我刚刚在这个js/canvas页面中掉进了这个陷阱:http://benjaminbenben.com/projects/twittny_test/

谢谢伙计,但过了一段时间后,我完全转向THREE.js,并尝试使用CSS完成的那个立方体是这样的:http://qbizm.ru。 - Alex Under

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接