Threejs如何绕物体自身中心旋转,而不是世界中心

问题描述 投票:0回答:5

enter image description here

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

但是鞋子模型的旋转轴是世界的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
5个回答
69
投票

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

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

var box = new THREE.Box3().setFromObject( mesh );
box.getCenter( 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;

编辑:一个不同的解决方案是平移几何顶点,使几何图形以原点为中心或附近:

geometry.translate( distX, distY, distZ );

或者,您也可以致电:

geometry.center();

它根据几何图形的边界框将几何图形的顶点居中。

三.js r153


29
投票

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

myGeometry.center();

这就像使用 myGeometery.translate(x,y,z) 和自动居中 (x,y,z) 一样。


12
投票

枢轴解决方案对我不起作用。

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

这里是一个加载 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
    );
  });
}


3
投票

如果有多个网格(这是最常见的),设置父节点在场景图中的位置,以达到模型居中的目的。如果场景图是这样的 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);

2
投票

这就是我如何在 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);
© www.soinside.com 2019 - 2024. All rights reserved.