Smoother shading at object loaded via STLLoader - three.js

model loaded via STLLoader avalaible in THREE.js repo at github loads models into THREE.BufferGeometry with face normals computed in that painful way. geometry.computeFaceNormals() does not make any difference
model.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.geometry.computeVertexNormals();
}
});
model.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.geometry.computeFaceNormals();
}
});
, same with changing THREE.Smooth/FlatShading.
How to make loaded models smoother? Shaders, remap normals?

Related

Convert MeshStandardMaterial to MeshBasicMaterial for glb model

I am loading a .glb model into Three.js. All the materials get turned into MeshStandardMaterial. How can I convert them to MeshBasicMaterial?
The goal is to get the exact colors that I used in Blender without having to use any lights in the Three.js scene.
Attempts
(1) I have tried the following code, based on https://stackoverflow.com/a/61717988/795016, but the problem is that this approach appears not to work when going from a more complex to a less complex material.
// For each child in the group
loadedGroup.traverse((child) => {
// If this child has a mesh standard material
if (
child instanceof THREE.Mesh
&& child.material instanceof THREE.MeshStandardMaterial
) {
var prevMaterial = child.material;
child.material = new THREE.MeshBasicMaterial();
THREE.MeshStandardMaterial.prototype.copy.call(child.material, prevMaterial);
console.log("child.material", child.material);
}
});
(2) I have also tried to use the gltf-transform tool to change the materials in the model to be unlit, but Three.js still shows them as MeshStandardMaterial.
gltf-transform unlit model-in.glb model-out.glb

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

Is it possible to append to an animated glb object in threejs/aframe?

I have an object moving about a scene, which I exported as a .glb (model A).
Within Aframe I'm playing the animation on model A using the animation-mixer tag and can see the object moving around. Now what I'm trying to do is append another model (model B), so that model B is also moving around the scene. However, model B just stays in place - at the specified model A position.
Is there a way to accomplish this in Threejs/Aframe?
I have revisited this technique and have the below code, so far, but the position of the model flickers between it's static position and where it's being set to in the tick.
<a-entity id="mantaray-path" gltf-model="#mantaray-path-glb" animation-mixer="timeScale: 1; loop: true;" pathanim></a-entity>
<a-entity id="mantaray" gltf-model="#mantaray-glb" animation-mixer="timeScale: 1;"></a-entity>
AFRAME.registerComponent("pathanim", {
init: function() {
this.el.addEventListener('model-loaded', this.update.bind(this));
},
tick: function() {
this.el.object3D.traverse(function(child) {
if (child.name == "mantaraypath") {
mantaray.object3D.position = child.position;
}
});
}
});

How to apply texture for .fbx model in three.js?

How do i change texture of ".fbx" model in three js library at runtime?
The main problem with applying a texture to an .FBX model, is that the .FBX is loaded as a group of sub-models, each with their own materials. The way to replace these textures is to traverse the model structure:
// FBX loader returns a group containing a multiple sub-objects. Traverse and apply texture to all.
group.traverse(function (child) {
if (child instanceof THREE.Mesh) {
// apply texture
child.material.map = texture
child.material.needsUpdate = true;
}
});
For a working sample, I've modified the default three.js FBX example to demonstrate this:
http://www.eponalabs.com/experiments/FBXReplaceTexture/fbx_replace_texture.html
When you press the button, the code fragment above is used to replace the textures with a placeholder image from Unsplash.it.

How to find sub-parts of a .OBJ 3D model using three.js?

I need to implement a functionality where user can upload a OBJ 3D model and then I will show different sub-parts of that model in browser. (Same as https://www.sculpteo.com is doing.).
But I am unable to find sub-parts of OBJ model. I am using three.js to show OBJ model in browser.
Is there any way to find sub-parts to OBJ model using three.js?
I am sharing code to load OBJ model =>
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( 'path' );
mtlLoader.load( 'model.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'path' );
objLoader.load( 'model.obj', function ( object ) {
scene.add( object);
});
});
Now I don't know how to find sub-parts of this "model.obj". Kindly help. Thanks in advance.
OJBLoader returns (THREE.Object3D() (it was in r71)) THREE.Group() (r81) with children of THREE.Mesh.
You'll get sub-parts as child meshes of the object only if your .obj file has groups of objects. Without it, you'll get just a sinlge child mesh.
Read about Wavefront .obj file format.
So, if your data of sub-parts grouped under
o [object name]
tag, then you'll have as many child meshes as you have "o" groups in your .obj file and then you can traverse.
upd#1: It also works with "g" tags.
g [group name]
The example based on "webgl_interactive_cubes" from Threejs.org, the data of sub-parts grouped with "g" tags (skull, uteeth, jaw, lteeth) in the .obj file
When you load the objects you can do this inside your callback function :
objLoader.load('yourUrl.obj', function (object) {
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
console.log(child);
// here you can make what you want with the children of object
}
});
});

Resources