Accessing multiple objs using .getObjectById() with JSONLoader in Three.js - javascript

Is it possible to differentiate between the meshes within one .js file exported from blender and animate them separately using Three.js?
The cube I would like to select is named "Cube" loads properly. However, when I try to get it by Name or Id, it doesn't recognize the var item1.
loader = new THREE.JSONLoader();
loader.load('engine.js', function (geometry, materials) {
var mesh, material;
material = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh(geometry, material);
mesh.scale.set(1, 1, 1);
var item1 = scene.getObjectByName("Cube");
item1.position.x = 15;
scene.add(mesh);
});
I found this post but it seems unresolved: Three.js load multiple separated objects / JSONLoader
What is the best approach to loading multiple meshes via JSONLoader? I'd prefer to load them together as one .js file and just select the ones I would like to animate.
Thanks for your help!

In your blender scene you need to name every mesh you want to access independently in three.js. Then you can use Object3D.getObjectByName() to access your mesh in three.js.

Yes, it is possible to load an entire scene with several meshes from a json file exported from Blender!
You can see the complete process described on my answer of the cited post
So, you can differentiate between the meshes using the getObjectByName method and manipulate them separately. 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.
You must change the loading code for one like this:
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");
mask.scale.set(0.9, 0.9, 0.9);
scene.add(surface);
scene.add(outline);
scene.add(mask);
} );
In the above code we can indeed animate the surface, outline and mask meshes independently.

Related

THREEJS - How to traverse all layers of model loaded with GLTFLoader?

How does one traverse a mesh loaded with GLTFLoader properly to walk through all layers?
I am trying to do a simple selective bloom pass on a model by traversing the model’s all parts, setting them to the bloom layer, and then rendering the combined original + bloomed layers. However, as we can see in the images below, only the yellow outer part of the model is actually found during the traversal, does anyone know how to extract the rest of the model for layer setting?
For reproduction, the model can be downloaded from here:
https://github.com/whatsmycode/Models/blob/master/PrimaryIonDrive.glb
This is the code I currently use:
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
let BLOOM_LAYER = 1;
new GLTFLoader().load( 'models/PrimaryIonDrive.glb', function ( gltf ) {
const model = gltf.scene;
model.traverse( function( child ) {
child.layers.enable(BLOOM_LAYER);
});
scene.add( model );
});
This is the resulting image, bloom is applied to the yellow outer rings only.
This is the bloom-mask only
The issue was that I had not added the point- and ambient lights to both layers. The bloomed object has properties that requires light to show color for all parts except for the emitting yellow rings. To fix the problem, I simply enabled the lights for both layers before adding the lights to the scene.
const pointLight = new THREE.PointLight(0xffffff);
pointLight.layers.enable(ENTIRE_LAYER);
pointLight.layers.enable(BLOOM_LAYER);
const ambientLight = new THREE.AmbientLight(0xffffff);
ambientLight.layers.enable(ENTIRE_LAYER);
ambientLight.layers.enable(BLOOM_LAYER);
scene.add(pointLight, ambientLight);

Collada loader: Is there anyway to get several meshes from the scene object?

I recently tried some experiments with Blender and the Collada Loader in three.js. In my Blender scene, I have three objects, but of course I only can manage one scene object with three.js with the loader. Everything works fine, even materials imported from Blender, but I was wondering if there is anyway to get the several objects from the scene object, turn them into three.js meshes, and then animate them individually, without turning them into several .dae files.
Posting my code here if it is useful:
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load( 'scene.dae', function ( collada ) {
dae = collada.scene;
dae.position.set(0, 0, 0);
dae.scale.set(50, 50, 50);
scene.add(dae);
});
Thanks for your help!
If you console.log(collada.scene) you'll see that you have a child array. This is where all the meshes live.
E.g. you can access the first one like so:
collada.scene.children[0].children[0];

Can't create a mesh from a loaded Three.js object

I used clara.io to export a model with four textures on it in the ThreeJS Object format. It results in a .json file. I am trying to load it and have it display correctly. If I do the following(taken directly from the clara.io exporting help), it loads and displays but without textures:
var loader = new THREE.ObjectLoader();
loader.load( "wsc3.json", function(obj){
scene.add(obj);
});
One thing that I have found, is, in reference to using a different kind of loader, it should be possible to convert the loaded object into a THREE.Mesh, get the textures, and then apply them to the mesh. I have a working example of this:
loader = new THREE.JSONLoader();
loader.load("wsc3.js", function(geometry, materials){
// get the materials loaded from the file
var materialsFromFile = new THREE.MeshFaceMaterial(materials);
// create our mesh with the loaded geometry and materials
mesh = new THREE.Mesh(geometry, materialsFromFile);
scene.add(mesh);
});
The problem with using the JSONLoader is that the model I am exporting has subparts, and when the .js file that the JSONLoader uses is exported, it loses the model hierarchy(I checked the .js file itself and none of the subparts are there. It is just a huge list of vertices). If I have a look at the .json file that clara.io exports, I can see the various subparts listed, so I would guess that I need to use this format.
I have looked around and seen that there is the suggestion to just create a new mesh from the obj that is generated by the ObjectLoader. Something like this:
var loader = new THREE.ObjectLoader();
loader.load( "wsc3.json", function(obj){
// get the geometry from the obj
var geometry = obj.geometry;
// get the materials from the obj
var materials = obj.materials;
mesh = new THREE.Mesh(geometry, materials);
scene.add(mesh);
});
Unfortunately, this doesn't work. Nothing displays. I can't figure out what I am doing wrong. Is there a format that Three.js will load, that not only brings the textures but the hierarchy as well?

Three.js texture on material

I'd like to apply a custom image texture (.bmp or .jpg) on a material loaded from Blender and used in my project via the JSONLoader method.
There is no bug but the render of the material with the texture is bad looking.
You can see it here: http://image.noelshack.com/fichiers/2014/18/1399215240-stack.png
I'd like to get rid of these "rays" on my material. Here is the code I use to load my material/texture:
var texture = THREE.ImageUtils.loadTexture('/Game/models/textures/black.jpg');
var currentMaterial = new THREE.MeshBasicMaterial({ map: texture });
var currentModel = new THREE.Mesh(geometry, currentMaterial);
The "geometry" variable is the result of the callback of the JSONLoader.Load method.
I'd like to know if the problem comes from the image texture or from the code. And what is the best way to load a material created in Blender and exported as a JS file and loaded with the JSONLoader. I'm not sure if I use the best method when I use the "THREE.MeshBasicMaterial" constructor.
Thanks

Parameterizing and editing a model using ThreeJS or X3DOM in the browser

I am using ThreeJs to render some STL files in the browser.
I am trying to figure out if I can add parameters to these models, so that I can edit these models using ThreeJs or X3DOM.
For example I have a cube and I want to add a text parameter to this cube.
When the text parameter is passed to ThreeJS, it embosses the text on the cube at a specific location.
I don't mind converting the STL files to the ThreeJS model Js file or X3D files as long as I can parameterize the rendering to add text to the basic structure.
I want to know if anyone has had experience doing this kind of 3D parameterization.
Is this possible in ThreeJS or X3DOM?
If yes, then is there any documentation that I could use to achieve this?
If these libraries cannot handle this case, then are there any other libraries which can achieve the same?
Edit
My question is more about how I can add parameters to the model itself. Can we have parameters in ThreeJS models themselves, which ThreeJS understands out of the box. Let me ignore the text example, if I consider a simple cube in a model file, is there a way to make Threejs understand its side length as param from the model, and any changes to this param automatically gets reflected into the visualization. I.e. IF I change the side length from 1 to 3, Threejs renders a larger cube.
I'm not sure it answers your question, but personally I would create a subclass of an empty 3D object, and apply your effects programmatically, after the base model is loaded.
Here's how I do with three.js (ideally, this is in a separated file) :
var EmbossedCube = function( text, onLoaded ) {
THREE.Object3D.apply(this);
var self = this;
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var material = new THREE.MeshPhongMaterial( { ambient: 0xff5533 } );
// apply effects on the material, or the geometry
// according to `text`
var mesh = new THREE.Mesh( event.content, material );
// transform the mesh locally if needed
self.add( mesh );
onLoaded && onLoaded( self );
} );
loader.load( './model.stl' );
};
EmbossedCube.prototype = Object.create( THREE.Object3D.prototype );
// methods of EmbossedCube
EmbossedCube.prototype.constructor = THREE.Object3D;
Then you can create such an object, and add it to your scene:
var cube = new EmbossedCube("beep", function(obj){
// you can translate/rotate the object if needed
scene.add( obj );
});
It could be not the simplest way to do it, but I think it offers a good reusability on the long term.
Explore the va3c viewer, which has options for opening files from REVIT, grasshopper etc.
You might try opening your files first in Rhino + GH, then creating those parameters that you need and then importing it using va3c.
This is a hunch and I cannot try until you give an actual file with details about the usecase.
Tell me if this works. ;)

Categories

Resources