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