Access mesh outside loader callback function - three.js

I created a Mesh in blender, exported it and loaded it via the JSON loader. Everything is rendered perfectly in the scene, but when I try to access it from outside the loader's callback function, I always get an "undefined".
This is my code:
var mesh, material;
var loader = new THREE.JSONLoader();
loader.load("./models/Baccanti/Bac.js", addModelToScene);
function addModelToScene(geometry,materials){
material = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh(geometry,material);
mesh.position.set(0,0,0);
scene.add(mesh);
}
What do I miss or how do I access the mesh after loading?
Thank you!

You are probably calling it before the mesh is loaded. You can put another callback into your addModelToScene function to alert you when its done loading
Similar question:
using three.js JSONLoader

Related

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.

Three.js Mesh With Multiple Materials Disappears?

I'm trying to load a pretty simple model with two materials (applied per-face) in Three.js exported from Blender. The issue I'm running into is that with multiple materials applied via the code below the mesh disappears entirely, but I can easily use materials[0] or materials[1] in place of materials and see a solid object. My export settings from blender along with what it should look like are below and the json of the model is visible online here.
I tried your JSON file and it displayed just like your image. Here's the code I used (three.js r83):
var mesh = new THREE.Object3D();
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load('/js/models/cube.json',
function (geometry, materials) {
mesh = new THREE.Mesh(geometry,
new THREE.MultiMaterial(materials));
scene.add(mesh);
}
);
http://www.threejsworld.com/tutorials/working-with-materials-in-threejs

Materials loaded event with JSONLoader

I would like to detect when JSONLoader loaded the model and all of its UV textures.
I tried to use the LoadingMonitor, but it was not useful. It didn't log "Loaded" message.
I don't know why. I did everything according to the example. What did I wrong?
var manager = new THREE.LoadingManager(function() {
console.log("Loaded");
});
var loader = new THREE.JSONLoader(manager);
loader.load("model.js", function(geometry, materials) {
...
});
Otherwise can it fire when textures are loaded? Or is it detectable?
Thanks for all replies.

Loading multiple objects in Three.js from Blender

I have a quite complex shape (dressed girl) that in Blender is broken down into different objects and it's loaded into Three.js with the JSON loader (with a little hack I made, that uses zipped files instead of just JSON files, as there are a lot of vertices).
As I want to change dynamically the style of the dress from a Web page, I was wondering how I can show/hide different pieces (e.g. sleeves) in the scene.
I tried traversing the THREE.Mesh, but there are no children.
When I export from Blender with the JSON exporter, I don't see anything referring to the names of the objects in the JSON. Is the structure lost?
If you are using meshes containing lots of vertices, I would advise you to use the openCTM webGL loader instead of zip hacking. Here is a link to the loader : http://threejs.org/examples/webgl_loader_ctm.html
This mesh compression tool uses LZMA compression method and can reduce the size of your files by 93%...
Concerning the JSONLoader, using an array might help:
var meshes = [];
...
var loader = new THREE.JSONLoader();
var onGeometry = function(geom)
{
var mesh = new THREE.SceneUtils.createMultiMaterialObject(geom, [material]);
meshes.push( mesh );
...
scene.add(mesh);
};
loader.load("yourfile.js", onGeometry);
Hope this helps
It is possible to load an entire scene with several meshes from a json file exported from Blender and handle them separately!
You can follow the complete process of exporting a entire scene from Blender and the right way of handling the exported meshes on my answer of this post.
So, you can get the different meshes and manipulate them separately using the getObjectByName method. But it is important to know that the loaded object isn't a Geometry anymore. It is labeled with the Scene type by now and it must be handled in a different way.
The loading code must look like this one:
loader = new THREE.JSONLoader();
loader.load( "obj/Books.json", function ( loadedObj ) {
var surface = loadedObj.getObjectByName("Surface");
var outline = loadedObj.getObjectByName("Outline");
var mask = loadedObj.getObjectByName("Mask");
scene.add(surface);
scene.add(outline);
scene.add(mask);
} );
Besides, you can handle the multiple materials of single mesh using THREE.MeshFaceMaterial like in the following code:
var mat1 = new THREE.MeshLambertMaterial( { map: texture1 } );
var mat2 = new THREE.MeshLambertMaterial( { map: texture2 } );
var materials = [mat1, mat2];
var faceMat = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh( geometry, faceMat );
scene.add( mesh );
Hope this helps :)

Can't seem to make a functional THREE.js collada loader

I'm having issues getting a custom made collada object with no built in camera or lighting to render. I more or less copied what I had seen in a few collada examples to create my own loader, which looks like this:
var loader = new THREE.ColladaLoader();
var room, scene, stats;
loader.load('../Models/Rooms/boot.dae', function colladaReady( collada ){
collada.scene.getChildByName('Cube',true).doubleSided = true;
room = collada.scene;
room.scale.x = room.scale.y = room.scale.z = 1;
room.updateMatrix();
init();
});
The init function is fairly basic and looks like this
scene = new THREE.Scene();
scene.add( room );
scene.add( camera );
renderer.render(scene, camera);
Here is the actual object I'm trying to render. I have also tried it out with the monster.dae file that is in the examples folder without success. The Chrome javascript console isn't showing any errors, so I'm not quite sure where to look in my code. It all resembles functional examples, so I'm not sure why it's not functional. Is there something I'm unaware of that is relevant to collada loading?
RESOLVED: The item was rendering, but had no skin or texture associated with it. So it was rendering at the same colour as the background, which understandably appears to not be rendering at all. Discovered by adding a grid to the ground just to check.

Resources