.vertices array does not give the vertices in THREE.js - three.js

I am using OBJloader to load an .obj file in WEBGL , Three.js.
I want to access the vertices and faces of the objects but the geometry.vertices does not return the vertices positions and it gives me undefined.
Here is a piece of code:
var tool= new THREE.OBJLoader();
tool.load( '../obj/tool.obj', function ( object ) {
var material = new THREE.MeshLambertMaterial({color:0xA0A0A0});
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
console.log( "child" + child.geometry.vertices);} }
r.70
I am thankful for your helps in advance.

This answer only applies to versions of three.js prior to r.125.
If the loader you are using is returning BufferGeometry, you can convert the returned geometry to Geometry in the loader callback using a pattern like so:
var geometry = new THREE.Geometry().fromBufferGeometry( bufferGeometry );
three.js r.124

Related

How to get all materials from a scene in THREE.JS

I'm importing a .glb model and have in this file some materials that are not applied to any meshes.
So my question is in in THREE.JS exist something like a array of all materials that are in the scene or if I can get some how my materials when load the model with GLTFLoader.
You can traverse through the parsed glTF asset and collect all materials in a set. Something like:
const materials = new Set();
const scene = gltf.scene;
scene.traverse( function( object ) {
if ( object.material ) materials.add( object.material );
} );

Three.js - Can we intersect with material ID of a model using raycaster?

I'have been trying to intersect only one material among 3 materials of the loaded model onclick using their ID's, however, the control continues to the entire model. Let me know if it is possible to intersec on basis of material ID's
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i++ ) {
object.scene.traverse(function(child) {
if ( child instanceof THREE.Mesh ) {
if (child.material.name == "heap") {
child.material.color = new THREE.Color( 0x00ff00 );
}
}
})
}
You can update the material of a raycast object by means of accessing the material property on the object of an intersection result.
Something to keep in mind is that, when you do update the properties of a material object, you need to set needsUpdate = true so threejs knows that the material needs updating internally.
Consider the following code that achieves what you're after:
// If only interested in one intersection, you can use .intersectObject()
var intersection = raycaster.intersectObject( scene.children );
// If intersection found, update material in some way
if(intersection) {
// Extract object and material from intersection
var object = intersection.object;
var material = object.material;
/*
Manipulate your material as you need to
material.color = new THREE.Color( 1, 0, 0 );
*/
// Tell threejs that the material was changed and
// needs to be updated internally
material.needsUpdate = true;
}

Undefined vertexUv on merging BufferGeometries loaded from an .obj file?

I am loading an .obj file using THREE.OBJLoader with three.js r86.
I would like to merge the children of this object into a single mesh.
Since the loaded geometries of the meshes are BufferGeometry objects, first I transform them into Geometry objects then I perform the merge.
From my understanding there is no way to perform the merge easily directly on the BufferGeometry objects as of yet.
var material = new THREE.MeshBasicMaterial({color: 0xffffff});
var loader = new THREE.OBJLoader( manager );
loader.load( 'Temple-model.obj', function ( object ) {
var geometry = new THREE.Geometry();
for (var i = 0; i < object.children.length; i++) {
var c = object.children[i];
if (c instanceof THREE.Mesh) {
var g = new THREE.Geometry().fromBufferGeometry( c.geometry );
geometry.merge(g);
}
}
var merged = new THREE.Mesh(geometry, material);
scene.add(merged);
});
This seems to work but provokes raises this warning on the line on calling the render function of the renderer.
THREE.DirectGeometry.fromGeometry(): Undefined vertexUv 18483
Why does this happen and what are some better alternatives to achieve this?

Three.js - About storage of geometries and materials

We can create multiple meshes with the same geometry and material. But are there duplicates in the properties of each meshes ?
I'm concerned about memory problems. Thanks !
As you can see in THREE.Mesh code :
THREE.Mesh = function ( geometry, material ) {
THREE.Object3D.call( this );
this.type = 'Mesh';
this.geometry = geometry !== undefined ? geometry : new THREE.Geometry();
this.material = material !== undefined ? material : new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } );
this.updateMorphTargets();
};
And in the clone method :
THREE.Mesh.prototype.clone = function () {
return new this.constructor( this.geometry, this.material ).copy( this );
};
That is to say when creating a mesh from a geometry/a material, or cloning a mesh, its geometry and material properties are references to the same objects. If you modify the material's color, or the geometry's vertices, both original and copy will have the new color/geometry.
I think the best idea is cloning
var Box_geometry = Box_geometry.clone();
var Box_material = Box_material.clone();
I've prepared a simple example in JSFIDDLE.
r.73

threejs wireframe not working with OBJMTLLoader

am loading my object in threejs using OBJMTLLoader, the wireframe control is working alone for OBJLoader, but for the OBJMTLLoader it doesn't working
var loader = new THREE.OBJMTLLoader();
loader.load( 'obj/male02/male02.obj', 'obj/male02/male02_dds.mtl', function ( object ) {
object.children[0].geometry.computeFaceNormals();
var geometry = object.children[0].geometry;
console.log(geometry);
THREE.GeometryUtils.center(geometry);
geometry.dynamic = true;
var material = new THREE.MeshLambertMaterial({color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors });
mesh = new THREE.Mesh(geometry, material);
scene.add( mesh );
} );
function wireframe(){
//alert('hhhhhh');
mesh.material.wireframe = true;
mesh.material.color = new THREE.Color( 0x6893DE );
}
but it causing the following error, so my model is not showing on the viewer,
so here i want to know that we can create wireframe on any kind of 3d models??
object.children[0].geometry is undefined
Even though the OBJMTLLoader returns a THREE.Object3D object which does have .children, you should not assume that the .children is of type THREE.Mesh. So you should actually traverse() the THREE.Object3D in order to find the THREE.Mesh.
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh )
// do something with the geometry
} );

Resources