How to animate outside tick loop?

Salve galera!!!
I want to implement a button in this sunposition app (https://sunposition.vercel.app) that trigger an animation updating the sun position as the time goes on in arbitrary speed. Currently, there is a tick function updating the renderer, but I couldn’t figure out how to animate a position from outside the loop.

const tick = () => {
  let delta = clock.getDelta()
  for (const mixer of mixers) mixer.update(delta)
  controls.update()
  window.requestAnimationFrame(tick)
  renderer.render(scene, camera)
}

Here is a try with a function that is called when the button is pressed looping through the date range and calculating the new position and updating the light and sky (I tried to reuse the code that is working in another function that updates the sun position when the sliders change).

var animateSun = { animate: () => {
  let from = new Date('2022-01-01T07:00:00')
  from = new Date(from).setHours(control.hour)
  from = new Date(from).setMonth(control.month - 1)
  from = new Date(from)
  let to = new Date(from).setDate(from.getDate()+365)
  for (let d = from; d < to; d.setMinutes(d.getMinutes() + 10)) {
    let sunPosition = getSunPosition(d)
    // gsap.to(sphereLight.position, { duration: 1, x: sunPosition.x, y: sunPosition.y, z: sunPosition.z })
    sphereLight.position.set(sunPosition.x, sunPosition.y, sunPosition.z)
    // console.log(sunPosition)
    directionalLight.lookAt(new THREE.Vector3())
    sunPath.rotation.y = THREE.MathUtils.degToRad(control.northOffset)
    sunPosition = new THREE.Vector3().setFromMatrixPosition(sphereLight.matrixWorld)
    if (sunPosition.y < 0) {
      directionalLight.visible = false
    } else {
      directionalLight.visible = true
    }
    const uniforms = sky.material.uniforms
    uniforms[ 'turbidity' ].value = skyControl.turbidity;
    uniforms[ 'rayleigh' ].value = skyControl.rayleigh;
    uniforms[ 'mieCoefficient' ].value = skyControl.mieCoefficient;
    uniforms[ 'mieDirectionalG' ].value = skyControl.mieDirectionalG;
    uniforms['sunPosition'].value.copy(sunPosition)
    renderer.toneMappingExposure = skyControl.exposure
    controls.update()
    renderer.render(scene, camera)
  }
}};
gui.add(animateSun,'animate');

I saw that is possible animate things in different ways and I am diving into the docs to find some light, any word are wellcome!

Found a solution reading the amazing discoverthreejs.com book, so much thanks @looeee and all threejs devs!

Refactored the code with the structure suggested in the book and now it’s all working

1 Like

:star_struck: :fire: :blush:

Awesome, glad you found the book useful.

1 Like