使用three.js和tween.js我正在尝试创建一个rubick的立方体。它由27个小方块组成,这些小方块组合在一起,可以+Math.PI/2
或-Math.PI/2
旋转。补间库用于平滑旋转。
我的问题是,如果一个面被多次旋转(超过10个),它就会明显错误分配,我无法理解如何修复它(link到问题的可视图像。)
这是在下面的示例中旋转对象的函数:
function rotate( ii ) {
// Creates a dummy object to group multiple objects together and
// rotate (only one object in this example).
var rotationGroup = new THREE.Object3D();
scene.add(rotationGroup);
THREE.SceneUtils.attach( box[ ii ], scene, rotationGroup );
rotationGroup.updateMatrixWorld();
// Checks that no other animations are active. If so stops the
// function (this is rude, but it's not the focus of the example).
if( TWEEN.getAll().length>0 )
return;
// Creates the tween object for animation.
var tween;
var duration = 300;
var radiants = Math.PI/2;
tween = new TWEEN.Tween( rotationGroup.rotation ).to( { z: radiants }, duration );
tween.easing( TWEEN.Easing.Quadratic.InOut );
tween.onComplete(
function() {
THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
box[ii].updateMatrixWorld();
scene.remove(rotationGroup);
}
);
// Starts the animation.
tween.start();
}
我无法弄清楚如何在stackoverflow上创建一个运行代码片段,所以现在我将粘贴一些代码来复制问题(而不是rubick的那个更长且更混乱的代码)。
var camera, scene, renderer;
var canvas;
var cameraControls;
var clock = new THREE.Clock();
var box = [];
function main() {
init();
fillScene();
addToDOM();
animate();
function init() {
var canvasWidth = window.innerWidth;
var canvasHeight = window.innerHeight;
var canvasRatio = canvasWidth / canvasHeight;
// RENDERER
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.setSize(canvasWidth, canvasHeight);
renderer.setClearColor( 0xAAAAAA );
// CAMERA
camera = new THREE.PerspectiveCamera( 45, canvasRatio, 1, 1000 );
camera.position.set(20,15,10);
camera.lookAt( new THREE.Vector3(0,0,0) );
// CONTROLS
cameraControls = new THREE.OrbitControls(camera, renderer.domElement);
document.onkeydown = function(ev) {onKeyDown(ev);};
}
function addToDOM() {
var container = document.getElementById('WebGL-output');
var canvas = container.getElementsByTagName('canvas');
if (canvas.length>0) {
container.removeChild(canvas[0]);
}
container.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var delta = clock.getDelta();
cameraControls.update(delta);
TWEEN.update();
renderer.render(scene, camera);
}
function onKeyDown(ev) {
switch( ev.keyCode) {
case 65: // a
rotate(0);
break;
case 83: // s
rotate(1);
break;
case 68: // d
rotate(2);
break;
default: break;
}
}
}
function rotate( ii ) {
var rotationGroup = new THREE.Object3D();
scene.add(rotationGroup);
THREE.SceneUtils.attach( box[ ii ], scene, rotationGroup );
rotationGroup.updateMatrixWorld();
if( TWEEN.getAll().length>0 )
return;
var tween;
var duration = 300;
var radiants = Math.PI/2;
tween = new TWEEN.Tween( rotationGroup.rotation ).to( { z: radiants }, duration );
tween.easing( TWEEN.Easing.Quadratic.InOut );
tween.onComplete(
function() {
THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
box[ii].updateMatrixWorld();
scene.remove(rotationGroup);
}
);
tween.start();
}
function fillScene() {
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xAAAAAA, 2000, 4000 );
var axisHelper = new THREE.AxisHelper( 20 );
scene.add( axisHelper );
// LIGHTS
scene.add( new THREE.AmbientLight(0x333333) );
var light = new THREE.PointLight( 0x333333, 2 );
light.position.set(15,15,15);
scene.add(light);
light = new THREE.PointLight( 0x333333, 2 );
light.position.set(-15,-15,-15);
scene.add(light);
var boxGeometry = new THREE.BoxGeometry( 10, 3, 10);
var red = new THREE.MeshPhongMaterial({ color: 0xff0000 });
var blue = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
var green = new THREE.MeshPhongMaterial({ color: 0x0000ff });
var black = new THREE.MeshPhongMaterial({ color: 0x000000 });
var materials = [
[ red, red, red, red, black, black ],
[ green, green, green, green, black, black ],
[ blue, blue, blue, blue, black, black ]
];
for( var ii=0; ii<3; ii++ ) {
box[ii] = new THREE.Mesh( boxGeometry, new THREE.MeshFaceMaterial(materials[ii]) );
box[ii].rotation.x = Math.PI/2;
box[ii].position.set(0,0,3-(ii*3));
scene.add( box[ii] );
}
}
在js控制台上打印rotationGroup
和box[ii]
的旋转似乎它们不匹配:Object3D
的旋转在第四个十进制数字上引入了一点误差。
答案 0 :(得分:0)
我修改了补间完成后添加一些代码来执行的匿名函数,该代码检查旋转并设置正确的旋转值(感谢@WestLangley发现解决方案)。
function() {
THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
box[ii].updateMatrixWorld();
scene.remove(rotationGroup);
// Checks the rotation value and sets the correct one accordingly
var check = Math.floor( box[ii].rotation.z );
if( check==1 )
box[ii].rotation.z = Math.PI/2;
else if( check==3 )
box[ii].rotation.z = Math.PI;
else if( check==-2 )
box[ii].rotation.z = -Math.PI/2;
else
box[ii].rotation.z = 0;
}