Reputation: 173
I am loading a .obj file that builds a human dummy, and inside the .obj file there are lines that show where the meshes split E.G. "g "body_part" followed by the vertices, and faces. When I load my object it works great, and I can console log the object and see the children which are all the different meshes that build the object. The problem is that when I am using raycaster to change the color of the mesh that is hovered it will only work on specific parts. After further investigation I found that when the object is being loaded it is generating duplicates of the same mesh. Does anyone have an explaination on why it is duplicating duplicate meshes or a solution to this?
A hack to get the raycasting to work when hovering over a mesh is to choose the last index of the array returned by intersection, but this is a hack and does not fix the duplication problem. I am still investigating.
// store reference to closest object as current intersection object
this.INTERSECTED = intersects[intersects.length - 1].object;
Also, if I log the intersects it returns the correct mesh being intersected, but it returns all of the duplicates with it as well. For example when I hover over a hand it returns an array of the same object except they have different uids:
(9) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
1
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
2
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
3
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
4
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
5
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
6
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
7
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
8
:
{distance: 158.11485222188028, point: Vector3, object: Mesh, uv: Vector2, face: Face3, …}
length
:
9
__proto__
:
Array(0)
Loading object:
loadModel = (objModel) => {
//ADD Obj instantiate a loader
this.THREE = THREE;
const objLoader = new this.THREE.OBJLoader();
this.obj;
// load(URL, callback, loading, on error)
objLoader.load(objModel,
//called when resource is loaded
(object) => {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
if(child.name == "dummy_hips3 dummy_belly dummy_torso dummy_rshoulder dummy_rarm dummy_relbow dummy_rfarm dummy_rwrist dummy_rhand") {
console.log(child) <-- This will log 8x, and it should only happen once
}
child.material = new THREE.MeshBasicMaterial({color: 0x444444, wireframe: true});
}
});
object.position.y = -100;
this.obj = object;
console.log(object)
this.scene.add(object);
},
//called when loading is in progresses
(xhr) => {
this.setState({
percentageLoaded: (xhr.loaded / xhr.total * 100).toFixed(2) + '%'
});
},
//called when loading has errors
(error) => {
console.log(error);
});
}
Raycasting function
findObjIntersection = (obj) => {
// find intersections
// create a Ray with origin at the mouse position
// and direction into the scene (camera direction)
var vector = new THREE.Vector3(this.state.mouse.x, this.state.mouse.y, 1);
vector.unproject(this.camera);
var raycaster = new THREE.Raycaster(this.camera.position, vector.sub(this.camera.position).normalize());
// create an array containing all objects in the scene with which the ray intersects
// You can also pass this.scene.children for other objects
var intersects = raycaster.intersectObjects(obj);
// INTERSECTED = the object in the scene currently closest to the camera
// and intersected by the Ray projected from the mouse position
// if there is one (or more) intersections
if (intersects.length > 0) {
// if the closest object intersected is not the currently stored intersection object
if (intersects[0].object != this.INTERSECTED) {
// restore previous intersection object (if it exists) to its original color
if (this.INTERSECTED) this.INTERSECTED.material.color.setHex(this.INTERSECTED.currentHex);
// store reference to closest object as current intersection object
console.log(intersects)
this.INTERSECTED = intersects[0].object;
// store color of closest object (for later restoration)
this.INTERSECTED.currentHex = this.INTERSECTED.material.color.getHex();
// set a new color for closest object
this.INTERSECTED.material.color.setHex(0xff0000);
this.setState({
INTERSECTED: this.INTERSECTED.name
});
}
} else { // there are no intersections
// restore previous intersection object (if it exists) to its original color
if (this.INTERSECTED) this.INTERSECTED.material.color.setHex(this.INTERSECTED.currentHex);
// remove previous intersection object reference
// by setting current intersection object to "nothing"
this.INTERSECTED = null;
this.setState({
INTERSECTED: 'False'
});
}
}
I am showing what mesh is intersected, and it turns red as it is supposed to but only when I am in certain spot hovering the arm and I need it to happen when any of the arm is being hovered.
Here is the second image where the arm is being hovered, and it is detecting the intersection and displaying that it is indeed the same arm, but since I am not hovering over a specific spot it is returning a duplicate mesh that has a different id and this is where the problem is.
Upvotes: 1
Views: 514
Reputation: 5016
My guess is that the duplicates are in your obj file. The raycaster returns every object hit by the ray, so if you're getting 8 hits, there are 8 copies of the geometries there.
Are you exporting from Blender? There may be other copies in another layer, or hidden?
edit: I downloaded your model and viewed it in blender. The geometry is duplicated Up to 6 times for some segments of the object. This is not an uncommon problem because as a modeller, you may not notice the duplicates because they are identical copies within the same mesh.
Mesh obj size went from like 2.5 megs, down to ~350 k :)
In blender, you can go into edit mode on an object, select a single vertex, then hit Ctrl-L (select linked vertices) and then move that chunk of geometry, and it reveals a duplicate left behind.
The good news is that once these dupes are stripped out, your model file is going to be much much smaller. :)
eidt:1.5 I found an easier way to clean this model up.. selecting all the parts, then space bar->split->Separate by loose parts.. that turns each duped mesh into a separate object that was easy to select and get rid of.
edit2: Here's the cleaned up OBJ file with dupes removed.
https://drive.google.com/open?id=1Oi-hA9biuZmYuQ6ehiISOUZqCJDxd_fi
Upvotes: 2