Reputation: 65
I'm trying to implement an experimental version of a 2x2x2 Rubiks Cube. I have adopted instructions from two previous posts with issues regarding child objects attachment and detachment: Three.js: Proper way to add and remove child objects using THREE.SceneUtils.attach/detach functions and Three.js: Adding and Removing Children of Rotated Objects and have been able to successfully understand how to rotate two faces independently.
However, when I implement the same in code, I get weird results when the rotations are applied in succession, which suggests that some transforms are getting wrong somewhere, though I can't seem to understand where. But then again, every matrix related to the parent object is reset after the rotation ends, so I don't really understand why it should happen. The rotations work appropriately when applied independently, though, which confirms that I did about 50% things right :). The sample can viewed here: sample 2x2x2 cube.
Here are the relevant code samples: --> For the event handler for rotating the right face
function rotateR()
{
for(var i = 0; i < cubies.length; i++)
if((pos(cubies[i]).x >= 53) && (pos(cubies[i]).x <= 55))
active.push(cubies[i]);
for(var i = 0; i < active.length; i++)
console.log(active[i]);
//reset pivot rotation
pivot.rotation.set( 0, 0, 0 );
pivot.updateMatrixWorld();
//attach active[i] cubies to the pivot
for (var i = 0; i < 4; i++)
THREE.SceneUtils.attach(active[i], scene, pivot);
console.log("attached!");
attachedR = true;
}
And in the render function:
if((pivot.rotation.x <= 1.580000000000001) && (attachedR === true))
{
pivot.rotation.x += 0.02;
console.log(pivot.rotation.x);
if(pivot.rotation.x == 1.580000000000001)
{
attachedR = false;
for(var i = 0; i < active.length; i++)
console.log(pos(active[i]).x + ", " + pos(active[i]).y + ", " + pos(active[i]).z);
//Detach active[i] cubies from the parent pivot
pivot.updateMatrixWorld();
for(var i = 0; i < active.length; i++)
{
active[i].updateWorldMatrix();
THREE.SceneUtils.detach(active[i], pivot, scene);
}
}
}
The event handler and incremental animation functions for the Upper face are the same and in the same place. The pos(cubies[i]) function returns the world coordinates of the mesh object. Where am I going wrong with the rotations of the faces? Any help would be highly appreciated. Thank you.
Upvotes: 0
Views: 1254
Reputation: 64164
I think that the biggest problem was that the active array never got emptied
Also, you are doing extensive matrix update, when there is none really needed
I have redone your javaScript, now it just attaches the cubes, does the rotation, and finally detaches the cubes and resets the rotation.
JavaScript
//Rotate Right face of cube
function rotateR()
{
//Find cubies that lie in the right face of cube and store them in active[i]
for(var i = 0; i < cubies.length; i++) {
var x = pos(cubies[i]).x;
if(x >= 54 && x <= 56)
active.push(cubies[i]);
}
if (active.length != 4) alert ("active num wrong");
//attach active[i] cubies to the pivot
for (var i = 0; i < 4; i++)
THREE.SceneUtils.attach(active[i], scene, pivot);
attachedR = true;
}
//Rotate Upper face of the cube
function rotateU()
{
//Find cubies that lie in the up face of cube and store them in active[i]
for(var i = 0; i < cubies.length; i++) {
var position = pos(cubies[i]);
if(position.y >= 54 && position.y <= 56) {
active.push(cubies[i]);
}
}
if (active.length != 4) alert ("active num wrong");
//attach active[i] cubies to the pivot
for (var i = 0; i < 4; i++)
THREE.SceneUtils.attach(active[i], scene, pivot);
attachedU = true;
}
function detachAndReset()
{
for(var i = 0; i < active.length; i++)
{
THREE.SceneUtils.detach(active[i], pivot, scene);
}
active.length = 0;
attachedR = false;
attachedU = false;
pivot.rotation.x = 0;
pivot.rotation.y = 0;
}
//get world position of cubies[i]
function pos(object)
{
var position = new THREE.Vector3();
position.setFromMatrixPosition( object.matrixWorld );
return position;
}
function render()
{
var endAnimation = false;
//Math.PI / 2 == 1.580000000000001
//Rotate Right face of cube
if(attachedR === true)
{
pivot.rotation.x += 0.02;
if(pivot.rotation.x >= Math.PI / 2.0) {
pivot.rotation.x = Math.PI / 2.0;
endAnimation = true;
}
}
//Math.PI / 2 == 1.580000000000001
//Rotate Upper face of cube
if(attachedU === true)
{
pivot.rotation.y += 0.02;
if(pivot.rotation.y >= Math.PI / 2.0) {
pivot.rotation.y = Math.PI / 2.0;
endAnimation = true;
}
}
renderer.render(scene, camera);
if (endAnimation) {
detachAndReset();
}
}
Upvotes: 2