Adding different animations to existing mixamo FBX models three.js - animation

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

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));
}
);
}

Can't load the right animation from a 3D model

I’m trying to execute the animation of a model found on internet.
The expected animation is to have all the fans running. But when I tried to play the animation, it’s just the computer rotating on the X abscissa. I thought maybe its animations are somewhere else, so I logged the animation, and there is an array of tracks with all the fans in it. Being new in threejs I was wondering I'm not really sure how I should manage that, if it's an error from me or from the model itself.
However, when I tried to run the model through gltf-viewer, the model works fine.
I didn't touch anything on the model in my code, I just created a canva, loaded the model and play its animation by using the following lines.
const group = useRef()
const { nodes, materials, animations } = useGLTF('/scene.gltf')
const { actions, names } = useAnimations(animations, group)
useEffect(() => {
actions[names].play()
})
Here is the link of the model if somebody would like to try on its own
3D model

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 do I change the texture of a GLTF model dynamically?

In my scene I have loaded a .gltf model and it is rendered just fine.. It has a .png texture that is rendered on the surface of the 3d model. Is it possible to swap the texture programmatically? I'm using aframe (a-asset-item and a-entity to load the gltf asset)
Once you’ve loaded a model in A-Frame or three.js, it doesn’t matter much what format it was before1. For A-Frame, you can use JS to modify the model after it loads.
var tex = new THREE.TextureLoader().load('diffuse.png');
tex.flipY = false; // for glTF models.
el.addEventListener('model-loaded', function (e {
e.detail.model.traverse(function(node) {
if (node.isMesh) node.material.map = tex;
});
});
See docs on THREE.MeshStandardMaterial to learn what properties there are to edit, although this could vary depending on the model you’re loading.
1 One exception is the tex.flipY=false setting above — you'll (probably) only need that for glTF, where the UVs have a different orientation than the three.js default.

three.js and openlayers coordinates don't line up

I'm using three.js on a separate canvas on top of a openlayers map. the way I synchronize the view of the map and the three.js camera (which looks straight down onto the map) looks like this:
// calculate how far away the camera needs to be, to
// see this part of the map
function distanceFromExtentAndFOV(h, vFOV) {
return h / (2 * Math.tan(vFOV / 2));
}
// keep three.js camera in sync with visible part of openlayers map
function updateThreeCam(
group, // three.js group, containing camera
view, // ol view
map // ol map
) {
extent = getViewExtent(view, map);
const h = ol.extent.getHeight(extent);
mapCenter = ol.extent.getCenter(extent);
camDist = distanceFromExtentAndFOV(h, constants.CAM_V_FOV_RAD);
const pos = [...mapCenter, camDist];
group.position.set(...pos);
group.updateMatrixWorld();
}
// whenever view changes, update three.js camera
view.on('change:center', (event) => {
updateThreeCam(group, event.target, map);
});
view.on('change:resolution', (event) => {
updateThreeCam(group, event.target, map);
});
updateThreeCam(group, view, map);
I'm using three.js for custom animations of objects, that in the end land on the ground. however, when I turn the objects into openlayers features, the original three.js objects and the features don't line up perfectly (although their position coordinates are exactly the same). — also, when you pan, you can see that s.th. is slightly off.
// turn three.js planes into openlayers features:
const features = rects.map((rect) => {
const point = new ol.geom.Point([
rect.position.x,
tect.position.y
]);
return new ol.Feature(point);
});
vectorSource.addFeatures(features);
as I am pretty sure that my the code for synchronizing three.js and ol is correct, I am not really sure what what is going wrong. am I missing s.th. here?
It could be that you are using PerspectiveCamera and that will change the size/position based on depth. Try OrtographicCamera instead.

Resources