【问题标题】:threejs how to rotate around object's own center,instead of world centerthreejs如何围绕对象自己的中心旋转,而不是世界中心
【发布时间】:2015-05-05 02:40:09
【问题描述】:

场景中的两个对象。 立方体旋转轴应该是立方体的中心,这是我的期望。

但鞋子模型的旋转轴是世界的 y 轴。

我原来的代码是。

cube.rotation.y += 0.01;
shoe.rotation.y += 0.01;

我在stackoverflow中找到了一个解决方案,像这样:

cube.rotation.y += 0.01;
var pivot = new THREE.Object3D();
pivot.add(shoe);
pivot.rotation.y += 0.01;

但它不起作用。 然后,我改变鞋子的位置。

cube.rotation.y += 0.01;
var pivot = new THREE.Object3D();
shoe.position.set(-5,0,0);
pivot.add(shoe);
pivot.rotation.y += 0.01;

现在效果更好了,但还不够完美。而且由于鞋子的型号很多,我无法确定每个鞋子型号的不同位置。

【问题讨论】:

  • 您是否能够在不将鞋子对象移动到原点的情况下完成这项工作?谢谢。

标签: rotation three.js


【解决方案1】:

pivot 解决方案对我不起作用。

使用 OBJLoader.js(用于加载 .obj 对象),您需要获取对象的边界框,获取其中心,将标量乘以 -1,然后使用它来转换每个孩子的几何体的几何体。然后,如果您想将其用于某个目的,则需要重新更新边界框。

这是一个加载 obj 并“规范化”其几何顶点的函数,给定 OBJ 和 MTL(纹理)文件的目录和名称(例如,如果 OBJ 和 MTL 文件是 dir1/myObject.obj 和dir1/myObject.mtl,然后调用 loadObj('dir1','myObject'))。

function loadObj(dir, objName) {
  var onProgress = function (xhr) {
    if (xhr.lengthComputable) {
      var percentComplete = (xhr.loaded / xhr.total) * 100;
      console.log(Math.round(percentComplete, 2) + "% downloaded");
    }
  };

  var onError = function (xhr) {};

  // Manager
  var manager = new THREE.LoadingManager();
  manager.onProgress = function (item, loaded, total) {
    console.log(
      "Started loading file: " +
        item +
        ".\nLoaded " +
        loaded +
        " of " +
        total +
        " files."
    );
  };

  var mtlLoader = new THREE.MTLLoader();
  mtlLoader.setPath(dir);
  mtlLoader.load(objName + ".mtl", function (materials) {
    materials.preload();

    // Model
    var loader = new THREE.OBJLoader(manager);
    loader.setMaterials(materials);
    loader.setPath(dir);
    loader.load(
      objName + ".obj",
      function (object) {
        var objBbox = new THREE.Box3().setFromObject(object);

        // Geometry vertices centering to world axis
        var bboxCenter = objBbox.getCenter().clone();
        bboxCenter.multiplyScalar(-1);

        object.traverse(function (child) {
          if (child instanceof THREE.Mesh) {
            child.geometry.translate(bboxCenter.x, bboxCenter.y, bboxCenter.z);
          }
        });

        objBbox.setFromObject(object); // Update the bounding box

        scene.add(object);
      },
      onProgress,
      onError
    );
  });
}

【讨论】:

  • 谢谢!到处搜索这个。
【解决方案2】:

如果有多个网格(这是最常见的),设置父节点在场景图中的位置,以达到使模型居中的目的。如果场景图是这样的 gltfObject -> childObject ->.. -> 网格数组

const bbox = new THREE.Box3().setFromObject( gltfObject );
const offset = new THREE.Vector3();
bbox.getCenter(offset).negate();
childObject.position.set(offset.x, offset.y, offset.z);

【讨论】:

    【解决方案3】:

    如果您的网格没有围绕其中心旋转,那是因为几何顶点偏离原点。

    您可以通过使用边界框定义合理的中心来自动重新定位,然后像这样偏移网格的位置:

    var box = new THREE.Box3().setFromObject( mesh );
    box.center( mesh.position ); // this re-sets the mesh position
    mesh.position.multiplyScalar( - 1 );
    

    然后将网格添加到枢轴对象:

    var pivot = new THREE.Group();
    scene.add( pivot );
    pivot.add( mesh );
    

    在您的动画循环中,旋转枢轴;

    pivot.rotation.y += 0.01;
    

    编辑:A different solution 用于平移几何顶点,使几何以原点为中心或靠近原点:

    geometry.translate( distX, distY, distZ );
    

    或者,您也可以直接调用:

    geometry.center();
    

    根据几何体的边界框为您将几何体的顶点居中。

    three.js r.97

    【讨论】:

    • 如果可以的话,我们如何获得自定义glTF模型的geometry,一旦加载模型,我们所做的就是通过glTF.scene访问它并将其添加到我们的场景中。不知道从哪里获得模态的几何图形以使其居中:(。我相信我们可以遍历对象并获取每个节点上的几何图形,但我相信应该有一个更快的解决方案
    • @semuzaboi 使用第一种方法,但不要使用mesh,而是使用glTF.scene
    • @WestLangley 该位置已设置为box.center(mesh.position) 中边界框的中心。将 -1 乘以正数有什么影响?
    • @Ajay 如果边界框以 (100, 0, 0) 为中心,那么我们通过将网格位置设置为 (- 100, 0, 0) 来进行补偿。
    • 是否可以在不移动将对象平移到原点的情况下实现这一点?
    【解决方案4】:

    这就是我如何在 r86 上工作的方法

    // Store original position
    let box = new THREE.Box3().setFromObject(this.mesh);
    let offset = box.getCenter();
    
    // Center geometry faces
    this.geometry.center();
    
    // Add to pivot group
    this.group = new THREE.Object3D();
    this.group.add(this.mesh);
    
    // Offset pivot group by original position
    this.group.position.set(offset.x, offset.y, offset.z);
    

    【讨论】:

      【解决方案5】:

      使用 THREE.Geometry.prototype.center 如下:

      myGeometry.center();
      

      这就像使用带有自动居中 (x,y,z) 的 myGeometery.translate(x,y,z)。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-10
      • 1970-01-01
      • 1970-01-01
      • 2019-10-22
      • 2017-10-13
      • 2014-03-05
      • 2015-07-23
      相关资源
      最近更新 更多