Reputation: 11
I´m trying to build a Rubik's Cube using Three.js. In order to turn one side I put all of the small cubes that have to be turned in a group and then rotate it. To specify a turning point, I use this function I found:
//Turn Group Around Center function
THREE.Object3D.prototype.rotateAroundWorldAxis = function () {
// rotate object around axis in world space (the axis passes through point)
// axis is assumed to be normalized
// assumes object does not have a rotated parent
var q = new THREE.Quaternion();
return function rotateAroundWorldAxis(point, axis, angle) {
q.setFromAxisAngle(axis, angle);
this.applyQuaternion(q);
this.position.sub(point);
this.position.applyQuaternion(q);
this.position.add(point);
return this;
}
}();
When I use it to rotate the group once, everything works, but when I use it twice:
myGroup.rotateAroundWorldAxis(rotationPoint, zAxis, Math.PI / 2);
myGroup.rotateAroundWorldAxis(rotationPoint, zAxis, Math.PI / 2);
nothing happens on the second turn.
I guess this is because the function only applies a rotation to an unturned object instead of adding it. (rotation = 90 instead of rotation += 90)
My question: How could I solve this and let the function remember the previous rotations?
Upvotes: 1
Views: 198
Reputation: 320
I'm not sure I understand perfectly your problem but I would recommand to use quaternions, which simplify a lot rotations.
If you want a simple example instead of the doc, I've coded a small tuto to three.js (to visualize all camera parameters) where I represented a small solar system, in which I rotate different planets around a sun, on different orbits.
You can visualize it here, and the code is hosted on my Github. What I do is that in main.html
, I use the following animate function for my planets :
function animatePlanets() {
requestAnimationFrame(animatePlanets);
var quaternion, rotationSpeed, rotationSpeedMoon, pivotPoint, pivotPointMoon, rotationAxeMoon, subgroup, planetPosition, planet
for ( var i = 0; i < views.length; ++ i ) {
var view = views[ i ];
var camera = view.camera;
for (let i=1;i<group.children.length;i++){
// Rotate the planet around the sun
pivotPoint = group.children[i]
planetPosition = pivotPoint.children[0].position
// Defining the rotation axe and speed
rotationAxe = (new THREE.Vector3(-planetPosition.y,planetPosition.x,0)).normalize()
rotationSpeed = pivotPoint.speed
// Applying the rotation to the planet
quaternion = new THREE.Quaternion().setFromAxisAngle(rotationAxe,rotationSpeed)
pivotPoint.applyQuaternion(quaternion)
// Applying local rotation to the planet if not satellites
if (pivotPoint.children[0].children.length == 0){
planet = pivotPoint.children[0]
quaternion = new THREE.Quaternion().setFromAxisAngle(rotationAxe,rotationSpeed*10)
planet.applyQuaternion(quaternion)
}
// Render the scene, using the camera specifications
renderer.render(scene, view.camera);
}
}
I hope the example it clear enough, I actually just define a rotation point and apply a rotation at rotationSpeed
to each of the planets in my group around this point.
Tell me if you have further questions !
Upvotes: 1