我有一个类似魔方的拼图,我正在尝试使用 Three.js 在 webgl 中建模:
每个双色中心都可以旋转。当他们旋转时,他们会带动周围的所有棋子一起旋转。例如,如果我们旋转橙蓝色中心,会发生以下情况:
当你完成一个轮换后,一切都排成一行:
但是,现在当我尝试旋转橙白中心时,第一次旋转后从橙蓝中心继承的两 block 出现奇怪的行为:
我希望它们像其他部分一样旋转,但它们的旋转方式不同。
我正在使用 Three.js 的 Object3D.rotateOnAxis() 函数进行旋转:
function rotate ( center, distance ) {
var axis = center.axis;
center.model.rotateOnAxis ( axis, distance );
for ( var i in center.stickers ) {
center.stickers[i].rotateOnAxis ( axis, distance );
}
for ( var i in center.children ) {
center.children[i].model.rotateOnAxis ( axis, distance );
//Note: the stickers are just the colored faces
for ( var s in center.children[i].stickers ) {
center.children[i].stickers[s].rotateOnAxis ( axis, distance );
}
}
}
这是我的按键代码:
function showCube() {
//set stuff up, then...
count = 0;
parent.onkeypress = function(event) {
if ( count < 6 ) {
rotate( blocks.centers [ "BO" ], Math.PI / 6 );
count++;
if ( count == 6 ) {
moveFace ( blocks, "O1", "OY", "BW" );
moveFace ( blocks, "O2", "OW", "BY" );
moveFace ( blocks, "B1", "BW", "OY" );
moveFace ( blocks, "B2", "BY", "OW" );
moveCorner ( blocks, "BOW", "OW", "OY" );
moveCorner ( blocks, "BOW", "BW", "BY" );
moveCorner ( blocks, "BOY", "OY", "OW" );
moveCorner ( blocks, "BOY", "BY", "BW" );
}
} else {
rotate( blocks.centers [ "OW" ], Math.PI / 6 );
}
}
}
function moveFace ( blocks, child, oldParent, newParent ) {
var index = blocks.centers [ oldParent ].children.indexOf ( blocks.faces [ child ] );
blocks.centers [ oldParent ].children.splice ( index, 1 );
blocks.centers [ newParent ].children.push ( blocks.faces [ child ] );
}
function moveCorner ( blocks, child, oldParent, newParent ) {
var index = blocks.centers [ oldParent ].children.indexOf ( blocks.corners [ child ] );
blocks.centers [ oldParent ].children.splice ( index, 1 );
blocks.centers [ newParent ].children.push ( blocks.corners [ child ] );
}
有趣的是,为了让蓝-橙-黄角正确旋转,我需要围绕 BO 向量和 OW 向量之间的差异进行旋转。
也就是说:
- 蓝橙轴是 (0, 1, 1) 的归一化向量
- 橙白轴是 (1, 0, 1) 的归一化向量
- 第一次旋转完成后,如果我尝试旋转 BOY 围绕 (1, 0, 1) 的法线转角,我得到如下所示的行为 图片。
- 但是,如果我尝试围绕 (0, 1, 1) - (1, 0, 1),即 (-1, 1, 0),我得到了想要的行为。
我不明白发生了什么。你能帮我更新我的旋转功能,这样我就可以得到我想要的行为,而不必保留一长串过去某个片段经历过的旋转吗?
我怀疑在我完成第一次旋转后,我需要告诉该部件在不引起任何运动的情况下将其旋转状态“归零”,但我不太确定该怎么做,或者这是否是正确的方法。
你可以在这里玩这个东西:http://joshuad.net/clover-cube/so-question/
谢谢!
最佳答案
我通过将我的旋转方法更改为此来修复它:
function rotate ( center, distance ) {
var axis = center.axis;
center.model.rotateOnAxis ( axis, distance );
applyStatesToMatrixDirectly ( center.model );
for ( var stickerIndex in center.stickers ) {
center.stickers[stickerIndex].rotateOnAxis ( axis, distance );
applyStatesToMatrixDirectly ( center.stickers[stickerIndex] );
}
for ( var childIndex in center.children ) {
center.children[childIndex].model.rotateOnAxis ( axis, distance );
applyStatesToMatrixDirectly ( center.children[childIndex].model );
for ( var childStickerIndex in center.children[childIndex].stickers ) {
center.children[childIndex].stickers[childStickerIndex].rotateOnAxis ( axis, distance );
applyStatesToMatrixDirectly ( center.children[childIndex].stickers[childStickerIndex] );
}
}
}
function applyStatesToMatrixDirectly ( model ) {
model.updateMatrix();
model.geometry.applyMatrix( model.matrix );
model.position.set( 0, 0, 0 );
model.rotation.set( 0, 0, 0 );
model.scale.set( 1, 1, 1 )
model.updateMatrix();
}
想法是函数 applyStatesToMatrixDirectly() 将旋转直接应用于模型矩阵,然后重置所有旋转数据(以及其他所有数据)。这允许模型“忘记”它已被旋转,从而允许新的 rotateOnAxis 工作。
关于three.js - 轮换后的轮换不符合我的预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35676643/