1
votes

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?

1

1 Answers

1
votes

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 !