Куб, вращающийся к другому лицу, не анимируется с помощью three.js - PullRequest
Купить гитару в Москве
1 голос
/ 23 декабря

Почему приведенный ниже код не анимирует мой куб при повороте на другое лицо? Как мне это исправить?

new Vue({
  el: '#app',
  data () {
    return {
      camera: null,
      scene: null,
      renderer: null,
      mesh: null,
      rotationPerc: 0
    }
  },
  methods: {
    init: function () {
      this.renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      let container = document.getElementById('container');
      container.appendChild(this.renderer.domElement);
      this.camera = new THREE.PerspectiveCamera(70, 1, 1, 1000);
      this.camera.position.z = 400;

      // Make a scene
      this.scene = new THREE.Scene();

      // 1. Start with empty geometry
      let geometry = new THREE.Geometry();

      // 2. Add vertices to geometry
      geometry.vertices.push(
        // verts [0-3] are in in +z
        new THREE.Vector3(-100, 100, 100),
        new THREE.Vector3(-100, -100, 100),
        new THREE.Vector3(100, -100, 100),
        new THREE.Vector3(100, 100, 100),
        // verts [4-7] in -z
        new THREE.Vector3(-100, 100, -100),
        new THREE.Vector3(-100, -100, -100),
        new THREE.Vector3(100, -100, -100),
        new THREE.Vector3(100, 100, -100),
      );

      // 3. Connect vertices in desired order to make faces
      let b = 0x1db0ec
      let y = 0xffef3a
      let r = 0xea353d
      let w = 0xffffff
      //
      geometry.faces.push(new THREE.Face3(0, 1, 2)); // blue
      geometry.faces.push(new THREE.Face3(0, 2, 3)); // yellow
      geometry.faces.push(new THREE.Face3(5, 4, 6)); // white
      geometry.faces.push(new THREE.Face3(6, 4, 7)); // red
      //
      geometry.faces.push(new THREE.Face3(1, 0, 5)); // blue
      geometry.faces.push(new THREE.Face3(5, 0, 4));
      geometry.faces.push(new THREE.Face3(1, 5, 2)); // white
      geometry.faces.push(new THREE.Face3(5, 6, 2));
      geometry.faces.push(new THREE.Face3(2, 6, 3)); // red
      geometry.faces.push(new THREE.Face3(3, 6, 7));
      geometry.faces.push(new THREE.Face3(0, 3, 4)); // yellow
      geometry.faces.push(new THREE.Face3(3, 7, 4));
      //
      geometry.faces[0].color.setHex(b);
      geometry.faces[1].color.setHex(y);
      geometry.faces[2].color.setHex(w);
      geometry.faces[3].color.setHex(r);
      //
      geometry.faces[4].color.setHex(b);
      geometry.faces[5].color.setHex(b);
      geometry.faces[6].color.setHex(w);
      geometry.faces[7].color.setHex(w);
      geometry.faces[8].color.setHex(r);
      geometry.faces[9].color.setHex(r);
      geometry.faces[10].color.setHex(y);
      geometry.faces[11].color.setHex(y);

      // Make a material
      let material = new THREE.MeshBasicMaterial({
        // color: 0x00FF00,
        vertexColors: THREE.FaceColors,
        wireframe: false,
      });

      // Create a mesh based on the geometry and material
      this.mesh = new THREE.Mesh(geometry, material);
      this.scene.add(this.mesh);

    },
    rotateTo: function (face) {
      if (face == 'yellow')
        this.mesh.rotation.set(0, Math.PI / 2 * this.rotationPerc, Math.PI / 2 * this.rotationPerc);
      else if (face == 'red')
        this.mesh.rotation.set(Math.PI / 2 * this.rotationPerc, 0, Math.PI / 2 * this.rotationPerc);
      else if (face == 'blue')
        this.mesh.rotation.set(Math.PI / 2 * this.rotationPerc, 0, - Math.PI / 2 * this.rotationPerc);
      else if (face == 'white')
        this.mesh.rotation.set(- Math.PI / 2 * this.rotationPerc, Math.PI / 2 * this.rotationPerc, 0);
      else if (face == 'yb')
        this.mesh.rotation.set(0, 0, 0);
      else if (face == 'rw')
        this.mesh.rotation.set(Math.PI * this.rotationPerc, 0, 0);

      this.renderer.render(this.scene, this.camera);

      if (this.rotationPerc < 1) {
        this.rotationPerc += 0.001
        this.rotateTo(face)
      } else {
        this.rotationPerc = 1
      }
    }
  },
  mounted () {
    this.init();
    this.renderer.render(this.scene, this.camera);
  }
})
#app {
  padding: 0.1em;
  background-color: #eff0f1;
}
<script src="https://unpkg.com/vue"></script>
<script src="https://threejs.org/build/three.min.js"></script>

<div id="app">
    <div>
      <button v-on:click="rotateTo('yellow')">yellow</button>
      <button v-on:click="rotateTo('red')">red</button>
      <button v-on:click="rotateTo('blue')">blue</button>
      <button v-on:click="rotateTo('white')">white</button>
      <button v-on:click="rotateTo('yb')">yellow/blue</button>
      <button v-on:click="rotateTo('rw')">red/white</button>
    </div>
    <div id="container"></div>
</div>

1 Ответ

1 голос
/ 23 декабря

При анимации объектов в интерактивных 2D / 3D-приложениях рекомендуется использовать цикл анимации. Вы вносите изменения без задержки, поэтому переход происходит очень быстро. Кроме того, рекомендуется избегать углов Эйлера при анимации вращения. Вместо этого используйте кватернионы. three.js предоставляет метод Quaternion.rotateTowards () , который идеально подходит для вашего случая использования. Первый параметр определяет вращение цели, второй параметр определяет угловой шаг в радианах. Это означает, что он будет постепенно поворачивать ваш объект к определенному целевому вращению. Это похоже на работу Unity's Quaternion.RotateTowards . Реализация three.js также гарантирует, что объект не «перерегулируется».

Вставьте в цикл анимации следующие две строки:

var delta = clock.getDelta(); // clock is an instance of THREE.Clock

mesh.quaternion.rotateTowards( targetRotation, step * delta );

step определяет угловое смещение всекунд. Посмотрите следующую скрипку для полного примера:

https://jsfiddle.net/hx06vn8p/1/

three.js R111

...