I'm new to three.js and I am working on a project that helps in editing 3D objects. I have used the OBJLoader to load an object in .obj format and render it. Now I want to access the vertices of the rendered object.
Can you please help me in doing this one?
Every three.js Geometry instance has a .verticies array. See the docs.
Output your OBJLaoder object to the javasccript console of your browser and you should be able to find the verticies.
It would help if you posted some code.
loader.load( 'obj/test/testCube.obj', function ( object ) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
window.alert("CHILD"+child.geometry.vertices);
child.material.map = texture;
}
}
});
Related
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
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.
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
}
});
});
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
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();