What is the best way to animate a mesh rotation in three.js that has been imported from a .json file?

Currently in the process of learning three.js and finding it challenging to animate an object.

I am looking to load a .json file (exported from Blender) and have the object rotate horizontally continuously as an animation, similar to this example. Alternatively, rotating the scene could also be a viable option.

Most solutions I've come across involve rotating the mesh. However, every time I try referencing the mesh variable, I encounter a console error indicating that it is either undefined or null (depending on whether I initialize it or not). This issue likely arises because the mesh variable is only used within my .json loader function. Another suggestion was to reference the scene instead, but this resulted in an error message stating "Disallowing antialiased backbuffers due to blacklisting."

The code snippet I am currently using is:

<!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>

      // Declaration of global variables for the scene, camera, renderer, and mesh.
      var scene = null,
          camera = null,
          renderer = null,
          mesh = null;

      init();
      animate();

      // Initializing the scene setup.
      function init() {

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

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

        // Creating a camera, setting its position relative to the model, and adding it to the scene.
        camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 20000);
        camera.position.set(0,6,0);
        scene.add(camera);

        // Adding an event listener to resize 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();
        });

        // Setting the scene's background color to transparent
        //renderer.setClearColor(0x000000, 0);
        
        // Creating a light source, specifying its position, and adding it to the scene.
        var light = new THREE.PointLight(0xffffff);
        light.position.set(-100,200,100);
        scene.add(light);

        // Loading the mesh and incorporating it into 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);
        });

        // Integrating OrbitControls for mouse panning functionality.
        controls = new THREE.OrbitControls(camera, renderer.domElement);

      }
        
      /* Function to rotate the 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;
      }*/
      
      // Rendering the scene and updating as needed.
      function animate() {

        // Details about requestAnimationFrame available 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>

At present, the code renders the model without any animation. Sections commented out highlight failed attempts at achieving a rotation animation.

Seeking guidance on how to proceed with achieving the desired animation effect.

Answer №1

I successfully resolved the issue by utilizing a function within the loader, passing the object as a variable for access. A helpful StackOverflow post introduced me to Tween for creating animations. By adapting and modifying the provided code, I achieved the desired rotation.

This link leads to the now functional code:

<!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>

      // Initializing global scene, camera, and renderer variables.
      var scene = null,
          camera = null,
          renderer = null,
          mesh = null;

      init();
      run();

      // Scene setup function.
      function init() {

        // Creating the scene with specified size.
        scene = new THREE.Scene();
        var WIDTH = window.innerWidth,
            HEIGHT = window.innerHeight;

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

        // Setting up the camera and positioning it in the scene.
        camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 20000);
        camera.position.set(0,6,0);
        scene.add(camera);

        // Event listener to resize renderer with window resize.
        window.addEventListener('resize', function() {
          var WIDTH = window.innerWidth,
              HEIGHT = window.innerHeight;
          renderer.setSize(WIDTH, HEIGHT);
          camera.aspect = WIDTH / HEIGHT;
          camera.updateProjectionMatrix();
        });

        // Creating light source and position then adding to scene.
        var light = new THREE.PointLight(0xffffff);
        light.position.set(-100,200,100);
        scene.add(light);

        // Loading mesh and adding to 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);
        });

        // Adding OrbitControls for mouse panning.
        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() {
              // Checking for full 360 degrees of rotation and calculating remainder division.
              if (Math.abs(mesh.rotation.z)>=2*Math.PI) {
                  mesh.rotation.y = mesh.rotation.z % (2*Math.PI);
              }
          })
          .start();
        tween.repeat(Infinity)
      }
      
      // Render scene and update as needed.
      function run() {

        // Utilizing requestAnimationFrame for smart rendering.
        requestAnimationFrame(run);
        TWEEN.update();
        
        // Rendering the scene.
        renderer.render(scene, camera);
        controls.update();
      }

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

Answer №2

If you're looking for another solution, consider incorporating cameraControls into your camera setup.

By using THREE.OrbitControls, you can attach orbitControls to your camera, set a lookAt target position, and enable the camera to rotate automatically at all times.

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

In this scenario, scene.postion represents the center of your world space in the render. You have the flexibility to adjust the rotation speed by setting:

cameraControl.autoRotateSpeed = //value

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to change the AJAX variable that was returned

I have a JavaScript/jQuery script that fetches an external HTML page using AJAX and then applies a function to all its text nodes. $.get('webpage.html', function (html) { $(html).find('*').each(function () { $(this).content ...

Enhance your threejs project by incorporating post-processing effects alongside a captivating static background image

Stumbling upon an impressive code snippet by Andrew Berg, I discovered a method to create volumetric lights inside threejs. The mesmerizing effect can be witnessed here: https://codepen.io/abberg/pen/pbWkjg?editors=0010. This technique involves post-proces ...

Disabling gyro-based rotation on mobile devices is a straightforward process that can enhance user

I am struggling to stop the camera from rotating on mobile devices. I attempted using look-controls="hmdEnabled:false" to prevent the camera from following the mobile device's movements, but unfortunately, it did not work. After researching, I discov ...

Hiding a Blogger section when its widget is not visible

Take a look at this code: <b:section id='page-list'> <b:widget id='PageList1' locked='false' type='PageList' version='2' visible='true'> </b:widget> </b:section> I wa ...

Tips for configuring Visual Studio Code to utilize path mappings for handling automatic imports

In order to streamline my project and avoid messy paths, I am implementing absolute paths that will allow for consistent imports regardless of the file's location in the project tree. For this purpose, I made adjustments to the tsconfig.json: "paths ...

The function JSON.parse(obj) is malfunctioning and throwing an error, but an online parser is displaying the data correctly

Currently, I am in the process of developing a chatApp for my portfolio. I am working with technologies such as Flask on the back-end and vanilla on the front-end to gain a better understanding of how everything works. My main goal is to display events bas ...

Press the identical button arrangement with selenium using python

How do I click on buttons with the same classes one by one? This is the Python code I am using: clk_but1 = wait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//button[@class = ('applyBtn btn btn-sm btn-red')]"))) driver.execute_s ...

JQuery isn't functioning properly on dynamically generated divs from JavaScript

I'm currently tackling an assignment as part of my learning journey with The Odin Project. You can check it out here: Despite creating the divs using JavaScript or jQuery as specified in the project requirements, I am unable to get jQuery's .hov ...

Sort through each individual column in the table

My table filtering code isn't working, and I need to add a status filter with checkboxes. Can someone guide me on how to proceed? var $rows = $('tbody > tr'), $filters = $('#filter_table input'); $filters.on("keyup", fun ...

Error: Uncaught object in AngularJS ngRoute

I keep encountering an uncaught object error in my browser console while trying to load my AngularJS application. I am unsure if this issue is related to ng-route.js or if it's something else, as the error message only says 'uncaught object' ...

The fastest method for finding the longest palindrome subsequence within a given string

I've been working on creating a function that can identify the longest palindrome subsequence within a given string. After experimenting with dynamic programming, I came up with the code snippet below: function findLongestPalindrome(str) { let lengt ...

Scrolling automatically

I'm experimenting with creating a typing effect using JavaScript and the typed.js library, found here: My approach involves using a div as a container. However, I've encountered an issue - when the text reaches the height of the div, scroll bars ...

The element type provided is not valid: it should be a string (for built-in components) or a class/function. Utilizing SSR with Node.js, React, and React-

Playground: https://codesandbox.io/s/focused-dream-ko68k?file=/server/server.js Issue Error: Encountered an error stating that the element type is invalid. It was expecting a string or a class/function, but received undefined instead. This could be due ...

"Enjoy a unique browsing experience with a two-panel layout featuring a fixed right panel that appears after scrolling

I am facing difficulty in designing a layout with two panels where the left panel has relative positioning and the right panel becomes fixed only after a specific scroll point. Additionally, I need the height of the right panel to adjust when the page scro ...

Refreshing a Vue JS component

As a beginner in VueJs, I am facing an issue with reloading a component and table when a refresh button is clicked. I have tried using the forceUpdate method and changing keys, but it has not been successful so far. If anyone has any suggestions on how to ...

Grabbing an AJAX Request

Currently, I am working on a Firefox extension that is designed to analyze the HTML content of web pages after they have been loaded in the browser. While I have successfully captured events like form submissions and link clicks, I am facing an issue wit ...

Strange characters in unicode format, struggling to convert to integer, resulting in NaN

Looking to solve a similar issue discussed on this Stack Overflow thread, which explores how to print an array of HTML entities as unicode. My specific problem involves working with an array of custom font HTML entities: const arr = ['crop_&#x31 ...

Guide on incorporating dxTreeView with AngularJS

Hello there, I am trying to utilize the dx-tree-view component. In my Home.html file, I have included the following HTML code: <div dx-tree-view="treeViewOptions"></div> And in my HomeController.js: $scope.treeViewOptions = { binding ...

Is there a Javascript tool available for creating a visual representation of the correlation between items in two separate

Does anyone have recommendations for an HTML/JavaScript/browser-based component that can map items in one list to another? Imagine a scenario where there is a list of items on the left-hand side and another list on the right, with the ability to click on a ...

AngularJS $http.get('') is throwing an error because some parameters are missing

I am currently working on an application that utilizes OAuth for authentication, but I am facing some issues with passing the URL parameters correctly. Despite trying various methods, my API keeps returning an error stating that the username and password a ...