如何为从 .json 文件加载的 three.js 中的网格旋转设置动画?

How can I animate a mesh rotation in three.js loaded from a .json file?

我刚刚开始学习 three.js 并且正在努力为对象设置动画。

我需要能够加载一个 .json 文件(从 Blender 导出)并让对象连续水平旋转(作为动画),有点像 this example。旋转场景也可以。

我见过的大多数解决方案都涉及旋转网格,但每当我尝试引用网格变量时,我都会收到一个控制台错误,提示它未定义或为空(取决于我是否初始化它),这我假设是因为它只在我的 .json 加载器中使用。另一个解决方案建议引用场景,但这给了我一个错误 "Disallowing antialiased backbuffers due to blacklisting."

我目前的代码是:

<!DOCTYPE html>
<html>
  <head>
    <title>Rotating Sphere</title>
    <meta charset="utf-8">
    
    <!-- https://cdnjs.com/libraries/three.js -->
    <script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/three.min.js"></script>
    <script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/OrbitControls.js"></script>
    <!-- Tween.js: https://cdnjs.com/libraries/tween.js/ -->
    <!--<script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/Tween.js"></script>-->
  </head>
  <body style="margin: 0; background-color:#6cdbf5;">
    <script>

      // Set up the scene, camera, and renderer as global variables.
      var scene = null,
          camera = null,
          renderer = null,
          mesh = null;

      init();
      animate();

      // Sets up the scene.
      function init() {

        // Create the scene and set the scene size.
        scene = new THREE.Scene();
        var WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight;

        // Create a renderer and add it to the DOM.
        renderer = new THREE.WebGLRenderer({antialias:true, alpha:true});
        renderer.setSize(WIDTH, HEIGHT);
        document.body.appendChild(renderer.domElement);

        // Create a camera, zoom it out from the model a bit, and add it to the scene.
        camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 20000);
        camera.position.set(0,6,0);
        scene.add(camera);

        // Create an event listener that resizes the renderer with the browser window.
        window.addEventListener('resize', function() {
          var WIDTH = window.innerWidth,
              HEIGHT = window.innerHeight;
          renderer.setSize(WIDTH, HEIGHT);
          camera.aspect = WIDTH / HEIGHT;
          camera.updateProjectionMatrix();
        });

        // Set the background color of the scene to transparent
        //renderer.setClearColor(0x000000, 0);
        
        // Create a light, set its position, and add it to the scene.
        var light = new THREE.PointLight(0xffffff);
        light.position.set(-100,200,100);
        scene.add(light);

        // Load in the mesh and add it to the scene.
        var loader = new THREE.JSONLoader();
        loader.load( "http://www.amdesigngroup.com/clients/AM_6292_Learning/models/circle.json", function(geometry){
          var material = new THREE.MeshLambertMaterial({color: 0x55B663});
          mesh = new THREE.Mesh(geometry, material);
          mesh.translation = THREE.GeometryUtils.center(geometry);
          /*mesh.rotation.x = 0;*/
          scene.add(mesh);
        });

        // Add OrbitControls so that we can pan around with the mouse.
        controls = new THREE.OrbitControls(camera, renderer.domElement);

      }
        
      /* rotate mesh */
      /*var duration = 5000; // ms
      var currentTime = Date.now();
      function rotate() {

          var now = Date.now();
          var deltat = now - currentTime;
          currentTime = now;
          var fract = deltat / duration;
          var angle = Math.PI * 2 * fract;
          scene.rotation.y += angle;
      }*/
      
      // Renders the scene and updates the render as needed.
      function animate() {

        // Read more about requestAnimationFrame at http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
        requestAnimationFrame(animate);
        //rotate();
        // Render the scene.
        renderer.render(scene, camera);
        controls.update();
      }

    </script>
  </body>
</html>

正如发布的那样,它会显示模型,但不会动画化 - 注释掉的各个部分是我尝试完成旋转动画的失败尝试。

谁能给我一些指点?

另一种选择是将 cameraControls 添加到您的相机

THREE.OrbitControls: 为你的相机添加 orbitControls 定义一个 lookAt 目标位置并允许相机自动不断旋转

camera.lookAt(scene.position);
cameraControl = new THREE.OrbitControls(camera);
cameraControl.autoRotate = true;

scene.postion 是这种情况会成为您渲染世界的中心 space。 您可以使用

调整旋转速度
cameraControl.autoRotateSpeed = //value

我找到了解决办法!多亏了一篇文章使用了在加载器中调用的函数,将对象作为变量传递,我才能够访问该对象。然后使用Tween制作动画。我能够修改该代码以获得我正在寻找的旋转。

Here is the code that is now working for me:

<!DOCTYPE html>
<html>
  <head>
    <title>Rotating Sphere</title>
    <meta charset="utf-8">
    
    <!-- https://cdnjs.com/libraries/three.js -->
    <script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/three.min.js"></script>
    <script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/OrbitControls.js"></script>
    <!-- Tween.js: https://cdnjs.com/libraries/tween.js/ -->
    <script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/Tween.js"></script>
  </head>
  <body style="margin: 0; background-color:#6cdbf5;">
    <script>

      // Set up the scene, camera, and renderer as global variables.
      var scene = null,
          camera = null,
          renderer = null,
          mesh = null;

      init();
      run();

      // Sets up the scene.
      function init() {

        // Create the scene and set the scene size.
        scene = new THREE.Scene();
        var WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight;

        // Create a renderer and add it to the DOM.
        renderer = new THREE.WebGLRenderer({antialias:true, alpha:true});
        renderer.setSize(WIDTH, HEIGHT);
        document.body.appendChild(renderer.domElement);

        // Create a camera, zoom it out from the model a bit, and add it to the scene.
        camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 20000);
        camera.position.set(0,6,0);
        scene.add(camera);

        // Create an event listener that resizes the renderer with the browser window.
        window.addEventListener('resize', function() {
          var WIDTH = window.innerWidth,
              HEIGHT = window.innerHeight;
          renderer.setSize(WIDTH, HEIGHT);
          camera.aspect = WIDTH / HEIGHT;
          camera.updateProjectionMatrix();
        });

        // Set the background color of the scene to transparent
        //renderer.setClearColor(0x000000, 0);
        
        // Create a light, set its position, and add it to the scene.
        var light = new THREE.PointLight(0xffffff);
        light.position.set(-100,200,100);
        scene.add(light);

        // Load in the mesh and add it to the scene.
        var loader = new THREE.JSONLoader();
        loader.load( "http://www.amdesigngroup.com/clients/AM_6292_Learning/models/circle.json", function(geometry){
          var material = new THREE.MeshLambertMaterial({color: 0x55B663});
          mesh = new THREE.Mesh(geometry, material);
          mesh.translation = THREE.GeometryUtils.center(geometry);
          /*mesh.rotation.x = 0;*/
          scene.add(mesh);
          
          animate(mesh);
        });

        // Add OrbitControls so that we can pan around with the mouse.
        controls = new THREE.OrbitControls(camera, renderer.domElement);

      }
        
      /* rotate mesh */
      function animate(mesh) {
        var tween = new TWEEN.Tween(mesh.rotation)
          .to({ z: "-" + Math.PI/2}, 2500) // relative animation
          .onComplete(function() {
              // Check that the full 360 degrees of rotation, 
              // and calculate the remainder of the division to avoid overflow.
              if (Math.abs(mesh.rotation.z)>=2*Math.PI) {
                  mesh.rotation.y = mesh.rotation.z % (2*Math.PI);
              }
          })
          .start();
        tween.repeat(Infinity)
      }
      
      // Renders the scene and updates the render as needed.
      function run() {

        // Read more about requestAnimationFrame at http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
        requestAnimationFrame(run);
        TWEEN.update();
        
        // Render the scene.
        renderer.render(scene, camera);
        controls.update();
      }

    </script>
  </body>
</html>