Three.js - animated skinned meshes, instances, and seamless blending

I am currently developing a small multiplayer game that features a single skinned player mesh utilized by multiple players. Some Background: I have experimented with loading via Maya and Blender Collada export, both of which seem to reference some sort of animation data, although I encountered difficulties in getting it to work. After trying the Maya JSON exporter (which only generated tiny 1k files with a material line), I eventually found success with the Blender JSON exporter. For those also struggling with loading skinned meshes, I came across this helpful resource: Model with bones animation (Blender export) animating incorrectly in three.js

As a result, I now possess a geometry object and a materials array from the JSON loader.

I can enable skinning=true on the materials, create a THREE.SkinnedMesh, add it to the scene, incorporate animations through THREE.AnimationHandler.add (I'm uncertain about the role of the AnimationHandler), create a THREE.Animation, invoke play() and update(dt). Consequently, I have a singular mesh with an animation playing within my scene.

Now, here are my objectives...

  1. Multiple instances - I desire to have more than one player model moving around in my scene.

    • I do not wish to load the same mesh and animation data repeatedly.
    • The animation time should be specific to each instance (thus preventing them from all animating simultaneously).

    Should I create numerous THREE.SkinnedMesh and THREE.Animation for the same model? How does THREE.AnimationHandler factor into this?

  2. Multiple animations - I want idle/run cycles that can be independently played.

    To my knowledge, there exists only a single timeline of animation keyframes. How does Three.js handle partitioning this for me, or is manual intervention required?

  3. Animation Blending - To avoid abrupt transitions when a character halts running and shifts into the idle animation, I aim to pause the run animation and blend that state back into the idle animation.

    Is this functionality achievable with skinned meshes (excluding morph targets)? Are there any examples or documentation available on this topic?

Any insights would be highly appreciated, even if just directing me towards the right path. I do not seek a comprehensive tutorial; rather, I desire some overarching information regarding these functionalities.

I could potentially implement 2 and 3, but I require informative/descriptive documents pertaining to the Three.js skinning and animation framework to initiate the process. For instance, this offers limited guidance.

[EDIT]
Thanks to @NishchitDhanani, while the provided link proves beneficial, it lacks details on multiple animations or blending skeletal animations:

This page suggests that handling multiple animations remains a current challenge but provides limited insight (discussed briefly in the comments):

The current responses include...

  1. Utilize many THREE.SkinnedMesh, still uncertain about THREE.AnimationHandler.
  2. Unknown. Potentially adjust the start/end keyframes manually in the THREE.Animation.
  3. Not presently implemented to my knowledge. Possible exploration involves creating a custom shader capable of handling two THREE.Animations and interpolating between them.

Answer №1

Starting from release 67 in April of 2014, both skeletal animation blending and the ability to use multiple animations have been incorporated into the system. Each model still requires a SkinnedMesh to be created. The AnimationHandler takes care of updating the animations every frame, so it is recommended to call update on that instead of manually updating each Animation.

Take a look at the recent example: webgl_animation_skinning_blending.html, or explore my own demos:

Basic Character Controller (featuring time-warped speed blend)

Time Warped Speed Blend Demo

Answer №2

I successfully deployed four unique animated models using Blender and JSON files. By creating individual skinned meshes for each model and utilizing tailored functions with the JSON loader, I was able to incorporate different mesh designs, animations, textures, and keyframe counts for each model.

var loader = new THREE.JSONLoader(); 
loader.load("model_1.js", createSkinnedMeshforModel_1);
loader.load("model_2.js", createSkinnedMeshforModel_2);
loader.load("model_3.js", createSkinnedMeshforModel_3);

...

var animations = [];

function createSkinnedMeshforModel_1( geometry, materials )
{
  var myModel1, animation;
  THREE.AnimationHandler.add( geometry.animation );
  myModel1 = new THREE.SkinnedMesh(geometry, new THREE.MeshFaceMaterial(materials));
  enableSkinning( myModel1 );
  scene.add( myModel1 );
  animation = new THREE.Animation(myModel1, Model1_Animation_title, THREE.AnimationHandler.CATMULLROM);
  animations.push( animation );
  for( var i = 0; i < animations.length; i ++ )
  {
    animations[ i ].play();
  }
}


function createSkinnedMeshforModel_2( geometry, materials )
{
  var myModel2, animation;
  THREE.AnimationHandler.add( geometry.animation );
  myModel2 = new THREE.SkinnedMesh(geometry, new THREE.MeshFaceMaterial(materials));
  enableSkinning( myModel2 );
  scene.add( myModel2 );
  animation = new THREE.Animation(myModel2, Model2_Animation_title, THREE.AnimationHandler.CATMULLROM);
  animations.push( animation );
  for( var i = 0; i < animations.length; i ++ )
  {
    animations[ i ].play();
  }
}

function createSkinnedMeshforModel_3( geometry, materials )
{
  var myModel3, animation;
  THREE.AnimationHandler.add( geometry.animation );
  myModel3 = new THREE.SkinnedMesh(geometry, new THREE.MeshFaceMaterial(materials));
  enableSkinning( myModel3 );
  scene.add( myModel3 );
  animation = new THREE.Animation(myModel3, Model3_Animation_title, THREE.AnimationHandler.CATMULLROM);
  animations.push( animation );
  for( var i = 0; i < animations.length; i ++ )
  {
    animations[ i ].play();
  }
}

The enableSkinning() function is based on a tutorial by DEVMATRIX.

The "Modelx_Animation_title" variable corresponds to animation titles defined in Blender and exported into the JSON file.

To sync or desynchronize animations of multiple copies of a model, I implement a pause tactic followed by resuming playback from the paused frame.

animations[ i ].pause();
... (random delay) ...
animations[ i ].play();

Exploring Three.js release r62's feature allowing "Export multiple actions" from Blender might provide insights into managing different animations for multiple instances of a single model.

A potential solution to question 3 could involve creating an additional animation within Blender that transitions the model from an active to idle state.

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

Testing a custom Angular directive that encapsulates the functionality of SlickGrid

Currently, I am working on testing an angular directive that acts as a wrapper for slickgrid. 'use strict'; describe('Unit: Grid Directive', function() { var $scope; var element; beforeEach(module('grid')); beforeEac ...

Using jQuery and regex, calculate the sum of the numbers located at specific positions within the content of div classes

My task is to extract numbers from div elements with a specific class name and then calculate the sum of those numbers. Here is an example of the code: <div class="refineItem plz3">38440&nbsp;(19)</div> <div class="refineItem pl ...

creating dynamic data objects in ajax calls

https://jsfiddle.net/c7n34e3x/1/ from data, data1, and data2, only data is functioning, but it lacks dynamism. This method works as intended. var settings = { "async": true, "crossDomain": true, "url": "https://domain/api/v2/playlists/", ...

Store fresh JSON information in a newly created JSON document

As someone new to JavaScript, I really appreciate your assistance. I'm utilizing the randomuser.me API to generate a list of users, but the names are all in lowercase. With the help of someone else, I managed to capitalize the names using a script. N ...

The back div is not retained on the second animation when flipping the card

In my card with a unique animation, clicking on the "Edit" button triggers the following actions: It smoothly transitions to the center of the screen. During this movement, it rotates by 180 degrees, revealing a blank green back content. Once the card r ...

Slider Footer Player for Rdio

I am currently working on replicating the interactive player footer design used by rdio (). When you click on the footer, a panel elegantly slides up to reveal additional content. Another example of this functionality can be seen on the website teehan lax; ...

Animate elements in Vue.js when navigating between pages is a great way to enhance user

I'm looking to add animation to a specific element once the route page finishes loading. This is not related to route page transitions. I've experimented with various methods, trying to animate a progress bar based on dynamic data values. I attem ...

Sliding panel for horizontal overflow

Currently, I am developing a web animation GUI that requires a sliding timeline area similar to this example: With a starting time of 0, there is no need to slide to negative times, but the ability to zoom in and slide side to side to view the entire time ...

Ways to obtain an attribute through random selection

Figuring out how to retrieve the type attribute from the first input element: document.getElementById('button').addEventListener('click', function() { var type = document.querySelectorAll('input')[0].type; document.getE ...

Continuously converting methods recursively until the array is fully processed

My current code has a method that is not very efficient and does not scale well. The object y is an array consisting of key/value pairs, each containing two properties: 1. A unique string property called name. This value is identified by the childre ...

Steps to add an item into an array and access specific properties of that item within the array:

I'm currently developing a blackjack game using Javascript, and I need to create objects for each card so that multiple cards add up to 10. My challenge lies in adding the values of these objects together when they are stored in an array. Here is the ...

An AJAX error occurred: Resource identified as a script but transferred with MIME type text/json

I've been attempting to retrieve data from a server using JSONP, however, I continuously encounter a warning in my console Resource interpreted as Script but transferred with MIME type text/json: Here is the ajax call I am making var loginData = { ...

Securing a downloadable file with a password on a webpage

I am looking to create a webpage with a password-protected download option for a PDF. When someone clicks on the link, they should be prompted to enter a username and password. If they try to directly access the PDF at "www.example.com/~folder_name/abc.pdf ...

Is there a way to transfer FormsAuthentication.SetAuthCookie across various layers from Data Access Layer Class to WebService and then to Javascript?

After implementing DotNetOpenAuth in my ASP.Net Website and adapting it to work with Facebook Connect, I am facing a challenge. I have inserted a Facebook Connect button on my login page, but I am struggling to retrieve information from the connection and ...

How to generate flexible arrays using an established array?

Currently, I am working on creating a new array from an existing one. The structure of my current array is outlined below. How can I ensure that adding a new object results in a new array starting from that point? myArray: [{ anima ...

Exploring the process of updating initialState within react-redux

I am currently using react-redux to retrieve data from a MongoDB database and integrate it into my React App. Below is the structure I am working with: const initialState = { Level: [{ wId: Math.random(), Level1: [ { id: Math.rando ...

Changing an array of object arrays into a consolidated array in JavaScript

I am working with an array of objects that contain nested arrays. const arr = [ { JUNE: [ { "iD": "67854", "event": " closed", "title&quo ...

What is the method for setting the current time as the default in a time picker?

Below is a snippet of code where I attempt to implement a date picker and set the current time as the default value. .HTML <input type="time" [(ngModel)]="time"> .TS time; constructor() { this.time= new Date(); } ...

Avoid having the page become unresponsive

My HTML page contains multiple script files, but I am encountering an issue with the window.onload function. When calling my method within the window.onload block, the page freezes until the function execution is completed. This problem only occurs with t ...

Socket.io filters incoming data for xss vulnerabilities

I am currently utilizing socket.io in expressjs 3 and I'm looking to sanitize incoming messages using express-validator. Here's the code snippet I have: var expressValidator = require('express-validator') , sanitize = require('exp ...