Import .gLTF animation to THREE.js - three.js

I used Blender to create a 3D object with simple animation, then I export it as .gLTF file, I tried to import to THREE.js, but I only able to import the 3D object but can't load the animation, how can I load the animation to Three.js?

The most basic code for playing an animation looks like so:
loader.load( 'models.glb', function ( gltf ) {
var model = gltf.scene;
var animations = gltf.animations;
scene.add( model );
//
mixer = new THREE.AnimationMixer( model );
var action = mixer.clipAction( animations[ 0 ] ); // access first animation clip
action.play();
} );
You then have to ensure to update the instance of AnimationMixer in your animation loop like so:
var delta = clock.getDelta(); // clock is an instance of THREE.Clock
if ( mixer ) mixer.update( delta );
Check out webgl_animation_skinning_blending to see this code in action.
three.js R109

Related

Ready Player Me Avatar texture/lightning rendering in ThreeJS and Matterport

I try to import a Ready Player Me GLB avatar into a Matterport scene (in ThreeJS).
It works but the avatar is very flat (left picture) compared to the rendering into RPM (right picture) or basic GLTF Viewer. I don't understand what I missed ? Pseudo code :
const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('https://api.readyplayer.me/v1/avatars/63580183b445da7aa57b9ce3.glb',
(gltf) => {
this.mesh = gltf.scene;
const light = new THREE.AmbientLight( 0xFFFFFF, 1 );
light.castShadow = true
this.mesh.add( light );
...
}, undefined);
On the WebGL part I have access to Matterport renderer :
(renderer, THREE, effectComposer) => {
renderer.outputEncoding = THREE.sRGBEncoding
renderer.toneMapping = THREE.ACESFilmicToneMapping
}
Is it related to Antialias ? Or a paramter or lighting that flatten hair and hands ? Or is it related to texture ?
Thanks !
EDIT 11/12/2022:
Thanks to #Mugen87, I find how to use the EquirectangularShader from GLTFLoader sample. This code works with Matterport context.
let pmremGenerator = new THREE.PMREMGenerator( this.context.renderer );
pmremGenerator.compileEquirectangularShader();
let envMap = pmremGenerator.fromScene( new THREE.RoomEnvironment() ).texture;
this.context.scene.environment = envMap;
Instead of using a single instance of AmbientLight, apply a more advanced type of environmental lighting to your scene. Especially if you already enabled tone mapping, consider to use a HDR environment map. The basic GLTFLoader example of three.js is a good code template. The most important part is:
new RGBELoader()
.load( 'textures/equirectangular/royal_esplanade_1k.hdr', function ( texture ) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.environment = texture;
// more scene setup
} );
Applying an environment map to Scene.environment ensures all PBR materials in the scene are going to use it.

How to get all materials from a scene in THREE.JS

I'm importing a .glb model and have in this file some materials that are not applied to any meshes.
So my question is in in THREE.JS exist something like a array of all materials that are in the scene or if I can get some how my materials when load the model with GLTFLoader.
You can traverse through the parsed glTF asset and collect all materials in a set. Something like:
const materials = new Set();
const scene = gltf.scene;
scene.traverse( function( object ) {
if ( object.material ) materials.add( object.material );
} );

Updated textures stops animation in three.js

Moving on from yesterday. I'm swapping out a texture on a .GLTF on page refresh. The texture now works fine and dandy...
But only on files that have no animation. The texture update however, seems to stop them in their literal tracks. I've not sure what's causing it or how to reload the animations.
Here's the code:
var creaturePath = "models/gltf/creature/";
var creatureFile = "creature_roar.gltf";
// load the model
var loader = new GLTFLoader().setPath( creaturePath ); // creature
loader.load( creatureFile, function ( gltf )
{
gltf.scene.traverse( function ( child )
{
if ( child.isMesh )
{
// override textures
texture.flipX = false;
texture.flipY = false;
my_material = new THREE.MeshBasicMaterial({map: texture});
// child.material = my_material; // this is the problem line
texture.needsUpdate = true;
}
} );
var model = gltf.scene;
If you replace the material, you have to ensure to set MeshBasicMaterial.skinning and/or MeshBasicMaterial.morphTargets to true. Otherwise skeletal and/or morph target animation won't be supported by the material.
three.js R113

How textureLoader.load for more than 1 texture and assigning map names to each texture?

How can I call textureLoader.load only once and assign a map name to each texture and so that it I can call creating the material when all the textures have loaded?
Otherwise I can't control when to create the material and assign the textures correctly.
I am working with obj without loading mtl.
Thank you for your help
This is the code I'm asking to replace for one function textureLoader.load
var textureLoader = new THREE.TextureLoader(manager);
var albedoM = textureLoader.load( "vaseTextures/albedo.png", onLoad, onProgress, onError );
var normalMap = textureLoader.load( "vaseTextures/normal.png", onLoad, onProgress, onError );
var aoMap = textureLoader.load( "vaseTextures/cavity.png", onLoad, onProgress, onError );
Expected result: I call once function onLoad( texture) after the textures are loaded and saving a name for each texture, and so that I can then create one material that holds each texture and assign the textures to it.
In this case, it's best to use the onLoad() callback of THREE.LoadingManager. It will be executed as soon as all resources are loaded. Since you already pass an instance of THREE.LoadingManager to your texture loader, you just have to implement onLoad(). For example like so:
manager.onLoad = function ( ) {
const material = new THREE.MeshPhongMaterial();
material.map = albedoM;
material.normalMap = normalMap;
material.aoMap = aoMap;
// do something with your material
};
three.js R103

.vertices array does not give the vertices in THREE.js

I am using OBJloader to load an .obj file in WEBGL , Three.js.
I want to access the vertices and faces of the objects but the geometry.vertices does not return the vertices positions and it gives me undefined.
Here is a piece of code:
var tool= new THREE.OBJLoader();
tool.load( '../obj/tool.obj', function ( object ) {
var material = new THREE.MeshLambertMaterial({color:0xA0A0A0});
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
console.log( "child" + child.geometry.vertices);} }
r.70
I am thankful for your helps in advance.
This answer only applies to versions of three.js prior to r.125.
If the loader you are using is returning BufferGeometry, you can convert the returned geometry to Geometry in the loader callback using a pattern like so:
var geometry = new THREE.Geometry().fromBufferGeometry( bufferGeometry );
three.js r.124

Resources