Computing Bounding Sphere after static .OBJ loading with Three.js - three.js

I got the following code for loading a simple, non-animated .OBJ with a .MTL into Three.js. It's very simple indeed and works well, but when I add the line with computeBoundingSphere(), it fails with a "TypeError: object.computeBoundingSphere is not a function" :
var callbackIrali1 = function ( event ) {
var object = event.content;
object.computeBoundingSphere();
scene.add( object );
};
var loaderIrali1 = new THREE.OBJMTLLoader();
loaderIrali1.addEventListener( 'load', callbackIrali1);
loaderIrali1.load( 'models/obj/irali/irali.obj', 'models/obj/irali/irali.mtl' );
The issue is, I can't find what type of object might be this event.content returned by the callback, and so I can't find how to apply the computeBoundingSphere() function to it.

Finally found it out by myself :
- The object returned by the Loader is an Object3D,
- Thus, it has 2 children : mesh and materials,
- So you have to find the first child, then extract its geometry, and then compute the bounding sphere.
Which gives the following line :
object.children[0].geometry.computeBoundingSphere();

Related

Threejs cover single image on each box face without repeat

Suppose i have one gltf model like given here: https://sketchfab.com/3d-models/box-d919737a5a5b464f809d12f7e1fad78f. and cover image like given below:
I have to cover this image on full box not each layer separately.
Below is my code to apply texture on object.
var loader = new GLTFLoader().setPath( 'models/gltf/box/' );
loader.load( 'scene.gltf', function ( gltf ) {
var model = gltf.scene;
model.traverse ( ( o ) => {
if ( o.isMesh ) {
o.material.map = texture;
}
} );
scene.add( model );
render();
} );
Results of code is like given in below image but i have to wrap single image in continues manner to all side.
Thanks in advance for any kind of help.
That's the default texture-mapping behavior of a standard Three.js cube. If you need to modify the way the texture is mapped, then you'll have to perform your own UV Mapping and import the geometry into Three.js so they follow the pattern that you desire. For example, if you want to create a 6-sided die, you'll have to edit your UVs so they follow this pattern:
I recommend you use Blender to do this because it's free, easy, and it has a built-in GLTF exporter that you can use with Three.js.

Three.js FBXLoader2, change color of single Mesh (in Group or detached)

I have a .fbx model which load via FBXLoader2.
When I add the model (which include 3 meshes) to the scene, it is added as a Group. Now I try to change the color of a single Mesh in the Group, but all 3 meshes are getting the color. Then i thought they might be "linked" because of the Group. So i detached them (SceneUtils.detach).
Now I have all the meshes in the scene. Still, when I change the color of a single mesh, all three of them get the color. When I console.log the mesh (in the group or detached) it shows me the correct mesh.
var loader = new THREE.FBXLoader( manager );
loader.load( 'somemodel.fbx', function( object ) {
model = object;
var modelLength = model.children.length;
for (i=0;i<modelLength;i++) {
THREE.SceneUtils.detach(model.children[0], model, scene);
}
scene.children[0].material.emissive.setHex( 0xff0000 );
}
When i try to change position or scale the mesh, it works fine.
Anybody had the problem before?
Just clone the material and replace it with original once.
scene.children[0].material = scene.children[0].material.clone();
scene.children[0].material.emissive.setHex( 0xff0000 );

THREE JS converting to BufferGeometry from Geometry not working when loading PLY file

I am loading a very complex 3D model from a PLY file (over 60Mb). In my project I need to use the orbit-control to move around the object. Obviously due to the large file the operation is painfully slow in some couputers. In order to speed up things a bit I am trying to convert my geometry into a Buffer geometry with the following lines of code:
this.loader.load('assets/data/GuyFawkesMask.ply', function (geometry) {
var bufferGeometry = new THREE.BufferGeometry().fromGeometry( geometry );
console.log(bufferGeometry);
// Create object
let object =
new THREE.Mesh(bufferGeometry,
new THREE.MeshPhongMaterial(
{
color: 0xFFFFFF,
//vertexColors: THREE.VertexColors,
shading: THREE.FlatShading,
shininess: 0
})
);
_this.add(object);
});
But I am getting the following error:
TypeError: Cannot read property '0' of undefined
at DirectGeometry.fromGeometry (three.module.js:12219)
at BufferGeometry.fromGeometry (three.module.js:14307)
at threed-viewer.component.ts:379
at index.js:52
at XMLHttpRequest. (three.module.js:29263)
at ZoneDelegate.webpackJsonp.818.ZoneDelegate.invokeTask (zone.js:367)
at Object.onInvokeTask (ng_zone.js:264)
at ZoneDelegate.webpackJsonp.818.ZoneDelegate.invokeTask (zone.js:366)
at Zone.webpackJsonp.818.Zone.runTask (zone.js:166)
at XMLHttpRequest.ZoneTask.invoke (zone.js:420)
Any idea?
Thank you,
Dino
Just posting prisoner849 comment (as an answer) for future reference:
If I get it right, looking into the source code of PLYLoader.js, the
geometry, which the callback function returns, is already of
THREE.BufferGeometry()

Three.js Calculating Vertex Normals

I'm experimenting with one of the examples, namely the webgl_loader_obj.html to load an .obj file exported from blender into three.js
This works and displays the model exactly as expected.
Now i was looking at the use of material.shading = THREE.SmoothShading.
For this to work, the model needs to have vertex normals.
the exported file from blender has no normals defined.
So i looked at using computeVertexNormals to calculate the required normals.
however this doesn't appear to be doing anything, the resulting view is of the unsmoothed model.
further to this, as a test, i exported the same model, with normals.
loading it straight in, it appeared smoothed.
If i then did computeFaceNormals() & computeVertexNormals() it would result in the unsmoothed mesh again.
var loader = new THREE.OBJLoader( manager );
loader.load( 'test.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = new THREE.MeshLambertMaterial( { color: 0xff6600 });
child.geometry.computeFaceNormals();
child.geometry.computeVertexNormals();
child.material.shading = THREE.SmoothShading;
}
} );
Geometry.computeVertexNormals() "smooths" the vertex-normals by computing each vertex-normal to be the average of the face-normals of all faces that share that vertex.
If each face of your geometry has unique vertices (i.e., no vertices are shared with a neighboring face), then computeVertexNormals() will result in each face's vertex-normals being the same as the face-normal, and the mesh shading will appear faceted.
three.js r.71

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 :)

Resources