three.js gif image loader on before model load - three.js

How to show a gif image loader to indicate the status of the model on before load the 3d models using OBJMTLLoader orAssimpJSONLoader ? am using three.js version 67 and am using below code load the gif loader, but the function doesn't have any effect while load the model
var loadManager = new THREE.LoadingManager();
loadManager.onProgress = function ( item, loaded, total ) {
alert('hi');
console.log( item, loaded, total );
};
var objloader = new THREE.OBJMTLLoader(loadManager);
what am doing wrong here, am missing anything?

Having a quick read of the LoadingManager docs it seems that the class does not show progress of a single loader, but it shows the progress of many.
So if you send the loading manager 4 loaders, the onProgress event would fire 4 times with the 'loaded' variable being 1, 2, 3 and 4.

Related

How do I load texture files designed for an FBX model so that the model appears correctly in my ThreeJS scene?

I have been buying animated 3D models from TurboSquid and they fall into two starkly different categories:
Ready to use - I just load the FBX file and it looks fine in my ThreeJS scene
Missing textures - The loaded FBX model looks geometrically fine and the animations work, but all the surfaces are white
I want to know how to load the provided textures using the FBXLoader module. I have noticed that all of the FBX models, which I believe are PBR material based, have this set of files:
*002_BaseColor.png
*002_Emissive.png
*002_Height.png
*002_Metallic.png
*002_Roughness.png
*002_Normal.png
I have these questions:
How would I use the FBXLoader module to load the textures "in the right places"? In other words, how do I make the calls so that the BaseColor texture goes to the right place, the Emissive texture so it goes where it should, etc?
Do I need to pass it a custom material loader to the FBXLoader and if so, which one and how?
UPDATE: I trace through the ThreeJS FBX loader code I discovered that the FBX model that is not showing any textures does not have a Texture node at all. The FBX model that does show the textures does, as you can see in this screenshot of the debugger:
I'll keep tracing. If worse comes to worse I'll write custom code to add a Textures node with the right fields since I don't know how to use Blender to add the textures there. My concern is of course that even if I create a Textures node at run-time, they still won't end up in the proper place on the model.
This is the code I am currently using to load FBX models:
this.initializeModel = function (
parentAnimManagerObj,
initModelArgs= null,
funcCallWhenInitialized = null,
) {
const methodName = self.constructor.name + '::' + `initializeModel`;
const errPrefix = '(' + methodName + ') ';
self.CAC.parentAnimManagerObj = parentAnimManagerObj;
self.CAC.modelLoader = new FBXLoader();
self.CAC.modelLoader.funcTranslateUrl =
((url) => {
// Fix up the texture file names.
const useRobotColor = misc_shared_lib.uppercaseFirstLetter(robotColor);
let useUrl =
url.replace('low_Purple_TarologistRobot', `Tarologist${useRobotColor}`);
return useUrl;
});
// PARAMETERS: url, onLoad, onProgress, onError
self.CAC.modelLoader.load(
MODEL_FILE_NAME_TAROLOGIST_ROBOT_1,
(fbxObj) => {
CommonAnimationCode.allChildrenCastAndReceiveShadows(fbxObj);
fbxObj.scale.x = initModelArgs.theScale;
fbxObj.scale.y = initModelArgs.theScale;
fbxObj.scale.z = initModelArgs.theScale;
self.CAC.modelInstance = fbxObj;
// Set the initial position.
self.CAC.modelInstance.position.x = initModelArgs.initialPos_X;
self.CAC.modelInstance.position.y = initModelArgs.initialPos_Y;
self.CAC.modelInstance.position.z = initModelArgs.initialPos_Z;
// Create an animation mixer for this model.
self.CAC.modelAnimationMixer = new THREE.AnimationMixer(self.CAC.modelInstance);
// Speed
self.CAC.modelAnimationMixer.timeScale = initModelArgs.theTimeScale;
// Add the model to the scene.
g_ThreeJsScene.add(self.CAC.modelInstance);
// Don't let this part of the code crash the entire
// load call. We may have just added a new model and
// don't know certain values yet.
try {
// Play the active action.
self.CAC.activeAction = self.CAC.modelActions[DEFAULT_IDLE_ANIMATION_NAME_FOR_TAROLOGIST_ROBOT_1];
self.CAC.activeAction.play();
// Execute the desired callback function, if any.
if (funcCallWhenInitialized)
funcCallWhenInitialized(self);
} catch (err) {
const errMsg =
errPrefix + misc_shared_lib.conformErrorObjectMsg(err);
console.error(`${errMsg} - try`);
}
},
// onProgress
undefined,
// onError
(err) => {
// Log the error message from the loader.
console.error(errPrefix + misc_shared_lib.conformErrorObjectMsg(err));
}
);
}

A-Frame: Adding animationClip from another glb to one that has no animation

I have a gltf model without an animation that I've loaded in aframe, and I'd like to add an animation that is connected to a different model. I've written some javascript to pull in the animation data and even bind it to the original GLB using GLTF loader, but not sure how to replace the aframe entity beyond just replacing the url.
Any help on how to solve this, or if there's a more efficient way to do this would be much appreciated! 🙂
HTML code:
<a-entity gltf-model="https://cdn.theoasis.xyz/public/bollywoodified/01.glb" id="center" position="0 0.03 -1.6" rotation="0 0 0" scale="1.3 1.3 1.3" animation-mixer\>\</a-entity\>
Javascript code:
import { GLTFLoader } from 'https://cdn.skypack.dev/three#0.129.0/examples/jsm/loaders/GLTFLoader.js';
getAnimations('https://cdn.theoasis.xyz/glb/djland.glb');
function getAnimations(glb) {
const loader = new GLTFLoader();
loader.load(glb, function ( gltf ) {
loader.load(oasis_data.metadata[0].glb, function (data) {
data.animations = gltf.animations;
});
});
}
I tried to pull the animationClip from another glb and was successful, and then was able to replace the animation array on the intended glb with the one from the animated glb. But I do not know how to actually update the entity within AFrame, nor do i know if this is the most efficient solution!

Adding different animations to existing mixamo FBX models three.js

I have copied code for loading an animation (dancing twerk from mixamo) onto an existing fbx model (Douglas from mixamo) from the tutorial here https://www.youtube.com/watch?v=8n_v1aJmLmc but it does not work, as SimonDev uses version 118 of three.js whilst I am using version 128.
const loader = new FBXLoader();
//load model
loader.setPath('../models/characters/');
loader.load('Douglas.fbx', (fbx) => {
//scale the model down
fbx.scale.setScalar(0.0115);
/*
fbx.traverse(c => {
c.castShadow = true;
});
*/
//animate character
const anim = new FBXLoader();
anim.setPath('../models/characters/animations/');
anim.load('Twerk.fbx', (anim) => {
this.walkMixer = new THREE.AnimationMixer(anim);
//creates animation action
const walk = this.walkMixer.clipAction(anim.animations[0]);
walk.play();
});
this.object.add(fbx);
});
This is in my update function
//animation
if (this.walkMixer) {
this.walkMixer.update(this.clock.getDelta());
}
The animation worked previously when it was the same model with the animation, and with gltf, but I am trying to separate the model and animation, so that I can apply different animations from mixamo.
My code does not load the animation at all and he simply stands in a T-pose. I do not know what the current code for loading a separate animation from mixamo onto a current fbx model is. I would like to know how, as I would like to load and play multiple animations onto the same model.
I managed to sort it out-> it was due to me having multiple imports of three.js

JeelizFaceFilter and THREEJS issue with gltf and texture models

Goal
I'm stuck since yesterday with an issue on modifying a JeelizFilterFace example. My goal is to create my own filters, so I started the the luffy's hat tutorial, which explains that : https://jeeliz.com/blog/creating-a-snapchat-like-filter-with-jeelizs-facefilter-api-part-1-creating-your-first-filter/
Quick description of the problem
My problem is simple : I can't have the glTF example working with glTF models. It always show me a black shape, without the texture.
Details of the problem
The tutorial explains that the model have to be generated with a Blender exporter addons, in order to create the json file which is the model. But the Blender exporter is not supported anymore.
This is why I try to use ThreeJS with the GLTF loader (which is the best solution according to all the tutorials).
My problem is that I can't see any texture on any of my models, when I load it with JeelizFaceFilter/Threejs. I only have the black shape.
Here is what I did :
First, I did all the tutorial to be sure I can run the FilterFace tool, except for the exporting model from Blender part. So, I just copied the exported resources from the Jeeliz repo. The FilterFace works well : the hat is visible, with the texture and I can play with the THREEJS params.
Because I couldn't export the JSON from blender, i wanted to try to use the GLTF 2.0 model, I tried this model, which is working in the gltf-viewer tool (see picture below) : https://s3.eu-west-3.amazonaws.com/com.julianlecalvez/LuffysHat.zip
So far everything seems ok, but when I try to use this glTF loader example in the glTF demos (https://github.com/jeeliz/jeelizFaceFilter/tree/master/demos/threejs/gltf_fullScreen), it displays my hat in black. I have the good shape, but no texture (or no light?). I just replaced the model URL in this file. And I'm not even sure that the default model (the helmet) is displaying any texture.
I tried with a model from SketchFab, and I have the same : Black shape, no texture.
I put here the code to init the view, when I was trying to redo it outside of the demo file :
let init_view = function(spec) {
const threeStuffs = THREE.JeelizHelper.init(spec, null);
const SETTINGS = {
gltfModelURL: 'objects/luffys_hat_gltf/luffys_hat.gltf',
offsetYZ: [1,0],
scale: 2.2
};
// const loader = new THREE.GLTFLoader();
const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load( SETTINGS.gltfModelURL, function ( gltf ) {
gltf.scene.frustumCulled = false;
// center and scale the object:
const bbox = new THREE.Box3().expandByObject(gltf.scene);
// center the model:
const centerBBox = bbox.getCenter(new THREE.Vector3());
gltf.scene.position.add(centerBBox.multiplyScalar(-1));
gltf.scene.position.add(new THREE.Vector3(0,SETTINGS.offsetYZ[0], SETTINGS.offsetYZ[1]));
// scale the model according to its width:
const sizeX = bbox.getSize(new THREE.Vector3()).x;
gltf.scene.scale.multiplyScalar(SETTINGS.scale / sizeX);
// dispatch the model:
threeStuffs.faceObject.add(gltf.scene);
});
// CREATE THE CAMERA
THREECAMERA = THREE.JeelizHelper.create_camera();
}

How to load 3D object at runtime in aframe?

I am working on an aframe project where runtime loading of 3D object is required. I have read A-Frame documentations, and aframe doesn't seem to support runtime assets loading at all.
I discovered this aframe-asset-on-demand-component by protyze (https://github.com/protyze/aframe-asset-on-demand-component) and it seems to allow runtime loading of img, audio and video. But its documentation does not indicate the possibility of loading 3D objects like files in .obj or .dae at runtime.
Has anyone tried using the above-mentioned component to achieve runtime loading of 3D objects? Or is there any alternative ways to achieve this purpose?
Ignore <a-assets> since that is for pre-runtime network preloading.
Just set the model component with setAttribute:
el.setAttribute('gltf-model', 'path/to/model.gltf')
or
el.setAttribute('obj-model', {obj: 'path/to/model.obj'})
You can create a custom component that will use one of the three.js loaders, to load the model when you want to:
// instantiate a loader
var loader = new THREE.OBJLoader();
// load a resource
loader.load(
// resource URL
'models/monster.obj',
// called when resource is loaded
function ( object ) {
scene.add( object );
},
// called when loading is in progresses
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened' );
}
);
Links to three.js docs: Do a search for loaders to see all the ones available that you can use in an a-frame component:
https://threejs.org/docs/#examples/loaders/OBJLoader
A-frame components using the threejs loaders:
https://github.com/aframevr/aframe/blob/master/src/components/obj-model.js
https://github.com/aframevr/aframe/blob/master/src/components/collada-model.js
#ngokevin, Great answer! I've created plunker demo for that.
https://plnkr.co/edit/yOmsxOSSfkVuX7c739Q1?p=info
<a-scene embedded arjs="sourceType: webcam;">
<a-gltf-model id="lantern" src="#lantern" position="" 0 0 0"></a-gltf-model>
<a-marker-camera preset="hiro"></a-marker-camera>
</a-scene>
<script>
var lantern = document.getElementById('lantern');
setTimeout(() => {
alert('duck');
lantern.setAttribute('gltf-model', 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Duck/glTF/Duck.gltf');
}, 3000);
setTimeout(() => {
alert('cesium');
lantern.setAttribute('gltf-model', 'https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/CesiumMan/glTF/CesiumMan.gltf');
}, 9000);
</script>

Resources