THREE.ObjLoader从.obj文件生成重复的网格

时间:2018-08-03 18:35:19

标签: three.js .obj

我正在加载构建人类假人的.obj文件,并且在.obj文件中有几行显示了网格在哪里分割E.G. “ g“ body_part”,后跟顶点和面。当我加载对象时,它工作得很好,并且我可以控制台记录该对象并查看子对象,它们是构成对象的所有不同网格。问题是当我我正在使用raycaster来更改所徘徊的网格的颜色,它将仅在特定的部分上起作用。经过进一步的调查,我发现当对象被加载时,它会生成同一网格的重复项。有人对此有解释吗?是复制重复的网格物体还是对此的解决方案?

悬停在网格上时,使光线投射正常工作的技巧是选择交集返回的数组的最后一个索引,但这是一种技巧,不能解决复制问题。我仍在调查中。

// store reference to closest object as current intersection object
this.INTERSECTED = intersects[intersects.length - 1].object;

此外,如果我记录了相交,它会返回正确的相交网格,但也会返回所有重复的网格。例如,当我将鼠标悬停在手上时,它将返回相同对象的数组,但它们具有不同的uid:

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

加载对象:

  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);
      });
  }

射线广播功能

  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'
      });
    }
  }

我正在显示相交的网格,它会按照预期的方式变为红色,但是仅当我在某个位置悬停手臂并且需要悬停手臂时才需要发生。 enter image description here

enter image description here

这是悬停手臂的第二个图像,它正在检测相交并显示它确实是同一手臂,但是由于我没有悬停在特定点上,因此它返回了一个具有不同的ID,这就是问题所在。

1 个答案:

答案 0 :(得分:1)

我的猜测是重复项在您的obj文件中。光线投射器会返回光线所击中的每个对象,因此,如果您要命中8次,则那里有8个几何体副本。

您要从Blender导出吗?在另一层中可能还有其他副本,还是隐藏了?

编辑:我下载了您的模型并在Blender中进行了查看。对于对象的某些部分,几何图形最多重复6次。这不是一个罕见的问题,因为作为建模者,您可能不会注意到重复项,因为它们是同一网格中的相同副本。

Here's a screenshot of the parts ive separated so far...

Mesh obj的大小从2.5兆减小到了约350 k:)

在Blender中,您可以进入对象的编辑模式,选择一个顶点,然后按Ctrl-L(选择链接的顶点),然后移动那部分几何图形,然后显示出一个重复项。

好消息是,一旦删除了这些重复项,您的模型文件就会小得多。 :)

eidt:1.5我找到了一种清理模型的简便方法。选择所有零件,然后按空格键->拆分->用松散的零件分开。.这样就可以将每个重复的网格物体变成一个易于分离的对象。选择并摆脱。

edit2:这是清除了重复项的清理后的OBJ文件。

https://drive.google.com/open?id=1Oi-hA9biuZmYuQ6ehiISOUZqCJDxd_fi