Kurt
Kurt

Reputation: 1897

Rotating a sphere in threejs not working if using a loop

I'm trying to have a sphere rotated a certain number of times when a button is clicked (the number of times is selected by the user). Since the number of rotations is open ended, I figured it would be easiest to have it done in a for loop:

$('#clickme').on('click', function () {
    var multiple = 4; //Change this value to rotate at different angles
    var rotationVector = new THREE.Vector3(0,1,0);
    var angle = ((360 / multiple) * Math.PI) / 180;
    for (var i = 0; i < multiple; i++) {
        sphere.rotateOnAxis(rotationVector, angle);
        alert(i);
    }
});

The alert is just a placeholder for now, but I do want other things done after each rotation. The problem here is that the rotation is never done. There's no errors and it hits that line of code, but the object never rotates. If I take the sphere.rotateOnAxis out of the for loop, then it works fine (at least it rotates once per click). I've tried various methods of re-rendering the scene, but that never does anything.

Working example here: http://jsfiddle.net/weatL3nc/2/

Upvotes: 1

Views: 175

Answers (2)

Ricardo Souza
Ricardo Souza

Reputation: 16456

To wait for the render to complete you can implement a setTimeout() insted of a for loop with an interval high enough to wait for the render:

var iteration = 0;
var multiple = 4;
var interval = 100; // ms
var angle = ((360 / multiple) * Math.PI) / 180;

function rotateAndSave() {
    iteration++;
    sphere.rotateOnAxis(rotationVector, angle);
    //alert(iteration);
    if (iteration < maxIterations) setTimeout(rotateAndSave, interval);
}

Then call this function on your click:

rotateAndSave();

http://jsfiddle.net/weatL3nc/6/

Upvotes: 1

p.s.w.g
p.s.w.g

Reputation: 149010

Notice what you're doing here:

var angle = ((360 / multiple) * Math.PI) / 180;

You're getting an angle by dividing 360 degrees (or 2 π radians) into n slices. Then here:

for (var i = 0; i < multiple; i++) {
    sphere.rotateOnAxis(rotationVector, angle);
}

You're rotating n times by that angle. That means that no matter what multiple was, at the end of the for loop, you'll have rotated precisely 360 degrees. In other words, it is working, you just won't ever notice it because the next time it draws the screen, the sphere will be right back where it was before.

As an alternative you can try to using setInterval to allow the screen to redraw between frames, like this:

$('#clickme').on('click', function () {
    var multiple = 2; //Change this value to rotate at different angles
    var rotationVector = new THREE.Vector3(0,1,0);
    var angle = ((360 / multiple) * Math.PI) / 180;
    var frame = 0;
    var ival = setInterval(function() {
        sphere.rotateOnAxis(rotationVector, angle);
        frame++;
        alert('Frame ' + frame + ' of ' + multiple);
        if (multiple == frame)
            clearInterval(ival);
    }, 1);
});

Demonstration

Upvotes: 5

Related Questions