How do I change the texture of a GLTF model dynamically? - three.js

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.

Related

GLFT with Basis Universal texture in Three.js: Is mipmap required?

I change a PNG texture of a GLTF file to Basis Universal and try to read it through the GLTFLoader of Three.js.
I use basisu executale from https://github.com/BinomialLLC/basis_universal.
Loading a texture which was converted using -mipmap option of basisu executable is successful. The textures looks well.
But when a GLTF file with a basis texture which was converted without -mipmap option is loaded, it looks all black. I would like to load also texture not having mipmap.
Am I missing something? Or is mipmap required to load Basis texture in Three.js ?
I learned how to use BasisTextureLoader and GLTFLoader from Three.js documents. And my initialize code is like the attached code.
https://threejs.org/docs/?=GLTF#examples/en/loaders/GLTFLoader
https://threejs.org/docs/#examples/en/loaders/BasisTextureLoader
let basisLoader = new BasisTextureLoader()
.setTranscoderPath('examples/js/libs/basis/');
.detectSupport(viewer.renderer);
THREE.DefaultLoadingManager.addHandler(/\.basis$/i, basisLoader);
let dracoLoader = new DRACOLoader().setDecoderPath( 'examples/js/libs/libs/draco/' );
let gltfLoader = new GLTFLoader()
.setCrossOrigin('anonymous')
.setDRACOLoader( dracoLoader );
To use Basis Universal compression in a glTF file, don't use the .basis format or BasisTextureLoader – the standardized way to do that is with a .ktx2 file. There's an artist guide for updating a glTF asset to use .ktx2 textures available, which includes some details on mipmaps. You'll almost always need mipmaps, unless you know enough about mipmap filtering to be sure you can disable it without causing rendering issues (this is rare).
three.js provides an example of how to load these files, which would look something like this:
const ktx2Loader = new KTX2Loader()
.setTranscoderPath( 'path/to/basis/transcoder/' )
.detectSupport( renderer );
const loader = new GLTFLoader();
loader.setKTX2Loader( ktx2Loader );
loader.load( 'path/to/model.glb', function ( gltf ) {
...
}, undefined, console.error );

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

Aframe Load lightmap after loading GLTF - lightmap not showing

I'm trying to add a lightmap to some mesh after loading them from a GLTF file.
All my objects have 2UV channel.
I'm waiting 'object3dset' and here is my code :
const mesh = this.el.getObject3D('mesh');
var textureLoader = new THREE.TextureLoader();
textureLoader.load("lightmap.png", function(lmap){
mesh.traverse((node) => {
if (!node.isMesh) return;
node.material.lightMap = lmap;
lmap.flipY = node.material.map.flipY; //needed to flip the texture
node.material.needsUpdate = true;
});
});
If I replace the material with a new one and set the lightmap, it's working.
But I want to find a way without recreating all materials.
The lightmap was loaded, but not easy to see.
By default metalness from Khronos Blender Exporter converted in threejs after loading GLTF result to a level 1.0. With this configuration, the lightmap is hard to see and is not corresponding to what we see in Blender.
I hope my mistake can help someone else losing too much time.

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.

Three.js - collada model not loading when specifying a texture

I try to load a converted collada model (obj -> collada [opens without a problem in max, including working uvs]) with the three.js collada loader. The model was converted using assimp, an open source 3d model converter.
A thing I noticed is that the converted collada model has children inside children but I heard that would be no problem. However if I change the material to something with a texture, I get an error: "TypeError: uv2i is undefined".
As long as I do not use a texture the model loads.
https://dl.dropbox.com/u/2705276/bachelorShowcases/001/webGL_museum_wire.html
Model not loading when specifying a texture:
https://dl.dropbox.com/u/2705276/bachelorShowcases/001/webGL_museum.html
Is this a bug or am I doing something wrong?
function load( model ){
loader.load( 'https://dl.dropbox.com/u/2705276/bachelorShowcases/001/xerox404_webglCONV.dae', createScene1 );
}
function createScene1( geometry ) {
dae = geometry.scene;
mesh = dae.children[0].children[0];
mesh.material = new THREE.MeshPhongMaterial({map:THREE.ImageUtils.loadTexture('https://dl.dropbox.com/u/2705276/bachelorShowcases/001/xeroxD.png')});
}
If you check the console you'll see this error:
webGL_museum.html:461
Uncaught TypeError: Cannot read property 'u' of undefined three.js:17814
That basically means that your model doesn't have UVs. In order to use a texture with a model it needs to have UVs.

Resources