Three JS旋转中心点

19

我想实现的是围绕枢轴点旋转几何图形,并将其作为几何图形的新定义。我不想保留对rotationZ的编辑,而是希望当前的rotationZ成为新的rotationZ 0。

这样,当我创建一个新的旋转任务时,它将从新给定的枢轴点和新给定的弧度开始。

我尝试过的方法会使旋转点移动:

// Add cube to do calculations
var box = new THREE.Box3().setFromObject( o );
var size = box.getSize();
var offsetZ = size.z / 2;

o.geometry.translate(0, -offsetZ, 0)

// Do ratation
o.rotateZ(CalcUtils.degreeToRad(degree));

o.geometry.translate(0, offsetZ, 0)

我也尝试添加一个组并旋转该组,然后删除该组。但我需要保持旋转而没有所有额外的对象。我创建的代码

var box = new THREE.Box3().setFromObject( o );
    var size = box.size();

    var geometry = new THREE.BoxGeometry( 20, 20, 20 );
    var material = new THREE.MeshBasicMaterial( { color: 0xcc0000 } );

    var cube = new THREE.Mesh( geometry, material );

    cube.position.x = o.position.x;
    cube.position.y = 0; // Height / 2
    cube.position.z = -size.z / 2;

    o.position.x = 0;
    o.position.y = 0;
    o.position.z = size.z / 2;

    cube.add(o);

    scene.add(cube);

    // Do ratation
    cube.rotateY(CalcUtils.degreeToRad(degree));

    // Remove cube, and go back to single object
    var position = o.getWorldPosition();

    scene.add(o)
    scene.remove(cube);
    console.log(o);

    o.position.x = position.x;
    o.position.y = position.y;
    o.position.z = position.z;

我的问题是如何将当前旋转保存为新的0旋转点。使旋转最终生效。

编辑 我添加了一张图片来说明我的意思。这个对象是绿色的。世界的0点是黑色的,对象的0点是红色的,旋转点是蓝色的。

如何让对象围绕蓝点旋转?

图片描述


只是想澄清一下:您是想将旋转应用于对象还是对象的顶点?换句话说,您是想通过更新顶点来保持旋转,而不仅仅是保留变换矩阵吗? - TheJim01
是的,就是这样。我希望旋转是持久的。 - Niels
1
@Niels 你需要将几何图形翻译,使得所需旋转点映射到世界原点。然后应用旋转。最后应用反向平移。 - WestLangley
@WestLangley 谢谢,我使用了TheJim1的答案进行旋转,但在使用pointInWorld时,将本地点作为值。 - Niels
2个回答

32

我不建议更新顶点,因为你会遇到法向量的问题(除非你也保持它们的最新状态)。基本上,这样做会带来很多麻烦,而这正是转换矩阵旨在解决的问题。

你已经很接近正确的方法了,通过平移、旋转和反平移。还有一些内置方法可以帮助你轻松完成这个过程。

// obj - your object (THREE.Object3D or derived)
// point - the point of rotation (THREE.Vector3)
// axis - the axis of rotation (normalized THREE.Vector3)
// theta - radian value of rotation
// pointIsWorld - boolean indicating the point is in world coordinates (default = false)
function rotateAboutPoint(obj, point, axis, theta, pointIsWorld){
    pointIsWorld = (pointIsWorld === undefined)? false : pointIsWorld;

    if(pointIsWorld){
        obj.parent.localToWorld(obj.position); // compensate for world coordinate
    }

    obj.position.sub(point); // remove the offset
    obj.position.applyAxisAngle(axis, theta); // rotate the POSITION
    obj.position.add(point); // re-add the offset

    if(pointIsWorld){
        obj.parent.worldToLocal(obj.position); // undo world coordinates compensation
    }

    obj.rotateOnAxis(axis, theta); // rotate the OBJECT
}

这个方法执行后,旋转/位置 将被保留。下一次调用该方法时,它将把对象从其当前状态转换到您的输入定义的任何位置。

还要注意使用世界坐标进行补偿。这使您可以通过将对象的position向量转换为正确的坐标系来在世界坐标或本地空间中使用点。无论何时您的点和对象位于不同的坐标系统中,最好以这种方式使用它,但您的观察可能会有所不同。


谢谢您的回答,我差不多让它工作了,但是我该如何获得规范化的Vector3呢?目前我的做法是:rotateAboutPoint(mesh, new THREE.Vector3(0, 0, -355 / 2), new THREE.Vector3(0, 1, 0), THREE.Math.degToRad(30))。目前它也会移动物体的当前位置。 - Niels
在问题中添加了更详细的解释。 - Niels
4
在我看来,这应该包括在Three.js中。 - frankenapps
我该如何使它不持久化? - Ood
我不明白为什么你要同时旋转“位置”和“对象”。旋转对象不就等同于旋转它的位置吗? - bennlich
显示剩余2条评论

13
作为一个快速更改物体中心点的简单解决方案,我建议创建一个组,并将网格添加到该组中,然后围绕该组进行旋转。
完整示例
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube)

enter image description here

现在,它只会围绕其中心旋转

cube.rotation.z = Math.PI / 4

enter image description here

创建一个新的组并添加立方体。
const group = new THREE.Group();
group.add(cube)
scene.add(group)

enter image description here

此时,我们回到了起点。现在移动网格:

cube.position.set(0.5,0.5,0)

enter image description here

然后移动该组。
group.position.set(-0.5, -0.5, 0)

enter image description here

现在使用你的 group 来旋转对象:
group.rotation.z = Math.PI / 4

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接