Using the same bone structure to share skeletons among SkinnedMeshes in Three.JS

I've been grappling with the challenge of incorporating and removing clothing pieces to an existing skeleton (Clothing meshes and body meshes should share skeleton) but I always seem to encounter strange results.

All the clothing items that I intend to connect to the shared skeleton have been exported from Blender with the same skeleton, they all possess identical bone names and structure, which led me to believe it would be a simple process.

I managed to achieve this effortlessly in Native iOS SceneKit by simply performing something like

clothing.skeleton = body.skeleton

However, when attempting the same in Three.JS, it didn't prove as straightforward.

I experimented with approaches such as

clothingMesh.bind(bodySkeleton,clothingMesh.worldMatrix);

And also tried:

clothingMesh.skeleton = bodySkeleton;
bodySkeleton.update();

Yet, the results were consistently odd. While exploring solutions, I came across some code utilizing "retargeting" functions, though these are typically used when bone names of skeletons do not align, which isn't my case here.

JSFiddle playground link:

I've been tinkering with this on JSFiddle through this link, where you can find the complete code detailing my attempts.

In addition to resolving the binding issues with skeletons, my aim is to replicate Skeleton animations from different sources so they can be downloaded on-the-fly and applied dynamically to various characters. Unfortunately, I'm encountering bizarre outcomes even when the animated skeleton shares identical bone names and structure with the target skeleton for animation.

Here are some online resources and examples related to this topic:

Example 1

Example 2

Example 3

Example 4

https://i.sstatic.net/gPMHf.jpg

The ultimate goal is to seamlessly integrate and remove clothing pieces from a character's body, ensuring all meshes utilize a single shared skeleton (for optimal performance), and simultaneously facilitate the addition and removal of animations from external sources.

Answer №1

Hello, I am encountering the same issue and attempted to address it using the function provided below, but unfortunately, I was unsuccessful in resolving the problem. Have you found a solution yet?

My approach involved utilizing bakeSkeleton(MyCharacterName) after modifying the geometry skinnedMesh of my character. Although the function did not generate any console errors, the character appeared deformed as if exploded.

    function bakeSkeleton ( target ) {
      var v1 = new THREE.Vector3();

      target.traverse( function ( object ) {
            if ( !object.isSkinnedMesh ) return;
            if ( object.geometry.isBufferGeometry !== true ) throw new Error( 'Only BufferGeometry supported.' );

            var positionAttribute = object.geometry.getAttribute( 'position' );
            var normalAttribute = object.geometry.getAttribute( 'normal' );

            for ( var j = 0; j < positionAttribute.count; j ++ ) {
                  object.boneTransform( j, v1 );
                  positionAttribute.setXYZ( j, v1.x, v1.y, v1.z);

                  getBoneNormalTransform.call( object, j, v1 );
                  normalAttribute.setXYZ( j, v1.x, v1.y, v1.z );
            }

            positionAttribute.needsUpdate = true;
            normalAttribute.needsUpdate = true;

            object.skeleton.bones.forEach(bone => bone.rotation.set(0,0,0));
      } );
}

const getBoneNormalTransform = (function () {

      var baseNormal = new THREE.Vector3();

      var skinIndex = new THREE.Vector4();
      var skinWeight = new THREE.Vector4();

      var vector = new THREE.Vector3();
      var matrix = new THREE.Matrix4();
      var matrix3 = new THREE.Matrix3();

      return function ( index, target ) {

            var skeleton = this.skeleton;
            var geometry = this.geometry;

            skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
            skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );

            baseNormal.fromBufferAttribute( geometry.attributes.normal, index ).applyNormalMatrix( matrix3.getNormalMatrix(this.bindMatrix) );

            target.set( 0, 0, 0 );

            for ( var i = 0; i < 4; i ++ ) {

                  var weight = skinWeight.getComponent( i );

                  if ( weight !== 0 ) {

                        var boneIndex = skinIndex.getComponent( i );

                        matrix.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );

                        target.addScaledVector( vector.copy( baseNormal ).applyNormalMatrix( matrix3.getNormalMatrix(matrix) ), weight );

                  }

            }
            
            matrix3.getNormalMatrix(this.bindMatrixInverse);
            
            return target.applyNormalMatrix( matrix3 );

      }; 
      
}());

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

Tips for achieving proper styling and formatting of elements in jQuery UI

I've encountered an issue when trying to use jQuery UI after downloading it multiple times. In the examples provided with the download, the UI elements appear perfectly formatted, but when I implement them on my own pages, the styles and formatting ge ...

Guide to dividing a URL in reactjs/nextjs

Here is the complete URL: /search-results?query=home+floor&categories=All+Categories. I am looking to separate it into two sections - /search-results and query=home+floor&categories=All+Categories. My objective is to extract the second part of t ...

Trigger event when user ceases to click

I have successfully implemented a click event using jQuery. Here is the code: $('#myButton').click(function(){ // perform desired actions }); However, I am facing an issue where multiple intermediate events are triggered if the user clicks on ...

Top recommendation for showcasing a numerical figure with precision to two decimal points

Within my function, I am tasked with returning a string that includes a decimal number. If the number is whole, I simply return it as is along with additional strings. However, if it's not whole, I include the number along with the string up to 2 deci ...

How can I extract the initial values from PHP after receiving the JSON + serialized data in the Ajax response following the first submission?

I am currently utilizing ajax to store data for multi part forms. My goal is to save each form's data upon clicking the next button. I have utilized form data to serialize the information, however, the format of the data is not aligning with my expect ...

When developing a multi-page application using React, encountering the error "TypeError: Cannot read property 'pathname' of undefined" may indicate an issue

I am facing an issue while trying to develop a multi-page application using react-router. As I am new to React, I find it difficult to explain the problem clearly. My goal is to incorporate a login page into the application. Suggestions and alternative app ...

Submitting the form without utilizing Ajax, but instead sending data directly to a PHP script

I've encountered an issue while posting a form to a PHP file using AJAX. Despite my efforts, the form is bypassing AJAX and posting directly to the PHP file. Here is my form: <form id="editform" name="editform" action="ajaxeditform.php" method= ...

Retrieving Blocked Images with Selenium: A Step-by-Step Guide

HTML: <html> <head> <body onload="document.getElementById('a').style.display='block';"> <div id="a" align="center" onclick="document.location.reload();" style="display: block; cursor: pointer;"> <img width="9 ...

Leverage AJAX for real-time Django Model updates

Seeking insights on how to effortlessly update a Django model through AJAX without reloading the page or requiring user input for saving. Various tutorials address fetching data from Django models using AJAX, yet resources on updating models remain scarce. ...

What is the best way to effectively adjust the code structure in a Node.JS project?

[Summarized] Focus on the bold parts. Although I am relatively new to Node.JS, I have been able to successfully build some projects. However, I have come across a burning question that has left me frustrated after searching Google for answers without much ...

Converting Typescript objects containing arrays into a single array

Looking for some assistance with this problem :) I am trying to convert the object into an array with the following expected result: result = [ { id: 'test-1', message: 'test#1.1' }, { id: 'test-1', mess ...

Issue with Angular Route Guard - Incorrect redirection to login page

I'm encountering an issue with my Angular app where even after the JWT token has expired, I am still able to navigate within the application without any API data being accessible. I've double-checked my setup and it seems right, but for some reas ...

Showcasing Portfolio Work in a User-Friendly Mobile Design

Currently revamping my portfolio website and looking for ways to optimize the display of my personal projects. I have a card-like interface in place that works well on desktop but only shows one project at a time on mobile devices. Seeking solutions to imp ...

Error: ...[i] has not been defined

What seems to be the issue with this part of the script: function refreshLabels() { // loop through all document elements var allnodes = document.body.getElementsByTagName("*"); for (var i=0, max=allnodes.leng ...

Issue with background image resizing when touched on mobile Chrome due to background-size property set to cover

My current challenge involves setting a background image for a mobile page using a new image specifically designed for mobile devices. The image is set with the property background-size: cover, and it works perfectly on all platforms except for mobile Chro ...

Using functions as properties in React.js

I am facing an issue while trying to pass a function as a prop. Although I have done this successfully in the past, now I am getting an error (this.props.functionName is not a function). I have a child component called Navbar and a parent component named ...

Checking for correct HTML tags using JavaScript

Looking to validate some input in javascript and confirm if it is a valid HTML tag. Any straightforward methods with JQuery for this task? If not, any suggestions on how to achieve this using Regex? Thank you! ...

Is Protractor compatible with Internet Explorer 9?

For my Angular App that is running on IE9, I need to create end-to-end acceptance tests. I'm curious to know if the browser simulated by Protractor matches the behavior of IE9 or a newer version? ...

JavaScript seems to have difficulty correctly parsing objects from JSON

Having trouble populating a Repeat Box with objects from a JSON document. Despite my efforts, it keeps duplicating the first item instead of adding each one individually. Any ideas on what might be causing this issue? Below is the code I am currently usin ...

What are some strategies for improving search efficiency in arrays containing over 50,000 elements?

I am working with a large array of strings containing about 50,000 elements. export const companies = [ "000014", "000016", "000017", "000019", "000020", "000021", "000023" ...