【问题标题】:THREE.ObjLoader generating duplicate meshes from .obj file三.ObjLoader 从 .obj 文件生成重复网格
【发布时间】:2018-08-03 18:35:18
【问题描述】:

我正在加载一个构建人体模型的 .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'
      });
    }
  }

我正在展示什么网格是相交的,它会按预期变成红色,但只有当我在某个位置悬停手臂并且我需要它在任何手臂悬停时发生。

这是手臂悬停的第二张图像,它正在检测交叉点并显示它确实是同一只手臂,但是由于我没有将鼠标悬停在特定位置上,因此它返回了一个重复的网格,该网格具有不同的id,这就是问题所在。

【问题讨论】:

    标签: three.js .obj


    【解决方案1】:

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

    您是从 Blender 导出吗?可能在另一层有其他副本,或者隐藏?

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

    Mesh obj 大小从 2.5 兆,下降到 ~350 k :)

    在搅拌器中,您可以进入对象的编辑模式,选择单个顶点,然后按 Ctrl-L(选择链接的顶点),然后移动该几何体块,它会显示一个重复的左侧。

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

    eidt:1.5 我找到了一种更简单的方法来清理这个模型..选择所有部分,然后空格键->拆分->用松散的部分分隔..将每个被复制的网格变成一个单独的对象,很容易选择并摆脱。

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

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

    【讨论】:

    • 这是我最初的想法,我相信模型是从 Maya 导出的,基于我从哪里得到的:turbosquid.com/FullPreview/Index.cfm/ID/662719。我运行了一个基本的 powershell 脚本来检查文件中是否存在重复的行,结果结果是错误的,所以我认为这不是问题所在。要我发布 .obj 文件吗?
    • 是的,请,寻找行重复可能不够
    • 我发现了你的问题。
    • 非常感谢。我刚看到这个,应该早点回复说 .obj 文件有重复。再次感谢您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 2019-01-28
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多