ThreeJS 4. Expanding with animations

jiho·2019년 12월 20일
2

Threejs

목록 보기
5/10

scene을 animate하기원한다면 우리가 해야할 첫번째는 특정한 Interval을 가지고 re-render를 반복하는 방법을 찾는 것입니다. HTML5이전에 Javascript API에서는 setInterval이 존재했습니다.
setInterval을 가지고, 우리는 반복적으로 하는 행위를 만들수 있습니다. 하지만 이 함수의 문제점은 브라우저에 무슨일이 일어났는지를 신경쓰지 않습니다. 만약 다른 tab으로 이동했다면 이 함수는 여전히 수많은 호출이 계속 일어나고 있을 것입니다. ~그 이외에도 setInterval은 screen을 redrawing하는 것을 가지고 동기화되지않습니다.~ 이 내용은 자세한 설명이 필요할 것 같네요.
이것은 높은 CPU사용률로 이끌것입니다. 좋지않은 성능을 낸다고 생각하면 될 것 같습니다.

Introducing requestAnimationFrame

Modern browsers는 운이 좋게도 requestAnimationFrame이라는 해결책을 가지고 있습니다.

https://developer.mozilla.org/ko/docs/Web/API/Window/requestAnimationFrame
MDN 사이트를 참고하면 setInterval대신 requestAnimationFrame을 왜써야하는지 이해할 수 있을 것 같습니다.

콜백의 수는 보통 1초에 60회지만, 일반적으로 대부분의 브라우저에서는 W3C 권장사항에 따라 그 수가 디스플레이 주사율과 일치하게됩니다

requestAnimationFrame은 setInterval과의 차이점은 콜백함수는 동일하게 등록할 수 있지만 어떤 주기로 호출해야하는지는 정할 수 없습니다. Interval은 브라우저에 의해 정해집니다.
그래서 브라우저는 가능한한 부드럽고 효율적이게 그려줄것을 보장합니다. 사용예시를 보겠습니다.


var stats = initStats();
...
renderScene()
function renderScene() {
  		
        stats.update();

        // render using requestAnimationFrame
        requestAnimationFrame(renderScene);
        renderer.render(scene, camera);
}

저희는 이전처럼 한번만 renderer.render(scene, camera) 를 호출하지않고
requestAnimationFrame을 재귀적인 형태로 구성해서 지속적으로 호출되게 했습니다.

이전 포스트에서 렌더링하는 부분만 가져와서 보겠습니다.

https://blog.outsider.ne.kr/536
initStats 는 Threejs에서 제공되는 실행중인 animation의 frame rate정보를 알려주는 헬퍼함수 입니다. 아까 말했듯이 requestAnimationFrame에 의해 다른 탭으로 이동했다가 오면 frame 수가 잠시 줄어있는 것을 확인할 수 있습니다.

Stats lib의 저자 mrdoob 의 홈페이지 https://mrdoob.com/#/147/google_space 에 재미있는 결과물이 많으니 참고해도 좋을 것 같습니다.

Animating the cube

requestAnimationFrame과 statics 설정을하고 저희는 이제 큐브를 회전 시킬 것입니다.
cube.rotation.x, cube.rotation.y, cube.rotation.z 의 값을 requestAnimationFrame이 호출될 때마다 조금씩 늘려주면 됩니다. 어차피 라디안 값이라 회전하는 효과를 보일 수 있습니다.

function renderScene() {
  stats.update();
  
  cube.rotation.x += 0.02
  cube.rotation.y += 0.02
  cube.rotation.z += 0.02
  // render using requestAnimationFrame
  requestAnimationFrame(renderScene);
  renderer.render(scene, camera);
}

Bouncing the ball

공을 튀기기 위해서 다음 같이 저희의 renderScene 함수에 몇개의 line을 추가해줘야합니다.


var step = 0
function renderScene() {
  ...
  step += 0.04;
  sphere.position.x = 20 + 10 * Math.cos(step);
  sphere.position.y = 2 + 10 * Math.abs(Math.sin(step));
  ...
  requestAnimationFrame(renderScene);
  renderer.render(scene, camera);

큐브에서 rotation property를 변경했듯이 구에서는 저희는 position을 변경했습니다.
smooth curve한 공의 움직임을 위해 삼각함수를 사용했습니다. 아래 그림처럼요.

이번 포스트를 끝내기 전에 우리는 우리의 기본적인 scence에 하나의 요소를 더 추가해야합니다.
종종 3D Scenes, animation, colors, prorperties를 작업할 때 정확한 속도와 색깔을 얻기 위해 조금의 실험이 필요합니다. 만약 이런 종류의 Property를 수정할 수 있는 간단한 GUI를 가지고 있으면 이 작업이 매우 쉬워질 것입니다.

Using dat.GUI to make experimenting easier

구글 몇몇의 맴버는 dat.GUI 라는 라이브러리를 만들었습니다. 이 것은 우리가 매우 쉽게 간단한 사용자 인터페이스 컴포넌트(우리 코드에서는 다양한 변수를 변경할 수 있게)를 만들 수 있게 해줍니다. 이 포스트의 마지막으로 이 library를 사용해서

  • 움직이는 공의 속도 조절
  • 큐브의 회전 조절
    을 해보겠습니다.

위 깃레퍼지토리 에서 build버젼을 받아서 사용하시면 간단합니다.

var controls = new (function() {
    this.rotationSpeed = 0.02;
    this.bouncingSpeed = 0.03;
 })();
 var gui = new dat.GUI();
 gui.add(controls, "rotationSpeed", 0, 0.5);
 gui.add(controls, "bouncingSpeed", 0, 0.5);

위와 같이 우리가 조절할 property값들을 조절할 수 있게 controls라는 Object를 생성해줍니다.
그리고 저희가 가져온 라이브러리 dat.GUI를 이용해서 조절하려는 값정보가 들어있는 객체와 해당 프로퍼티의 이름, 그리고 이어서 0~ 0.5 라는 range값을 지정해줍니다.

그리고 마지막으로 반영하려는 객체의 프로퍼티 설정 부분에 controls 객체의 프로퍼티로 연결해주면 끝입니다.

function renderScene() {
    stats.update();

    // rotate the cube around its axes
    cube.rotation.x += controls.rotationSpeed;
    cube.rotation.y += controls.rotationSpeed;
    cube.rotation.z += controls.rotationSpeed;

    // bounce the sphere up and down
    step += controls.bouncingSpeed;
    sphere.position.x = 20 + 10 * Math.cos(step);
    sphere.position.y = 2 + 10 * Math.abs(Math.sin(step));

    // render using requestAnimationFrame
    requestAnimationFrame(renderScene);
    renderer.render(scene, camera);
  }

이제 결과를 보면 GUI를 통해 프로퍼티 값 조절이 가능해집니다. 앞으로 개발과정에서도 굉장히 유용할 툴이 될 것 같습니다.

profile
Scratch, Under the hood, Initial version analysis

0개의 댓글