【问题标题】:Three JS Pivot point三个 JS 支点
【发布时间】:2017-08-06 08:59:59
【问题描述】:

我想要实现的是几何围绕枢轴点的旋转,并使其成为几何的新定义。我不想继续编辑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 点的对象(红色)。我有旋转点(蓝色)。

如何围绕蓝点旋转对象?

【问题讨论】:

  • 只是为了澄清:您是要对对象应用旋转,还是对对象的顶点应用旋转?换句话说,您是否试图通过更新顶点来保持旋转,而不是简单地保持一个变换矩阵?
  • 是的。确切地说。我希望轮换保持不变。
  • @Niels 您需要转换几何体,以便所需的旋转点映射到世界原点。然后应用旋转。然后应用反向翻译。
  • @WestLangley 谢谢,我使用 TheJim1 答案旋转,但是当我使用世界作为 pointInWorld 时使用本地点作为值

标签: javascript three.js


【解决方案1】:

我不建议更新顶点,因为你会遇到法线问题(除非你也让它们保持最新)。基本上,执行转换矩阵所针对的操作非常麻烦。

您通过翻译、旋转和取消翻译非常接近,因此您走在了正确的轨道上。有一些内置方法可以帮助您轻松完成此操作。

// 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
}

此方法完成后,旋转/位置IS持续存在。下次您调用该方法时,它会将对象从其当前状态转换为您接下来定义的输入。

还要注意使用世界坐标的补偿。这允许您通过将对象的position 向量转换为正确的坐标系来使用世界坐标本地空间中的一个点。当您的点和对象位于不同的坐标系时,最好使用这种方式,尽管您的观察结果可能会有所不同。

【讨论】:

  • 感谢您的回答,几乎可以工作了,如何获得标准化的 Vector3?我目前做的是:rotateAboutPoint(mesh, new THREE.Vector3(0, 0, -355 / 2), new THREE.Vector3(0, 1, 0), THREE.Math.degToRad(30))目前它还移动了对象的当前位置。
  • 在问题中添加了更详细的解释。
  • 这似乎也在另一个轴上旋转了一点(z:试图在 y 上旋转),你知道是什么原因造成的吗?
  • @WarpDriveEnterprise 不,抱歉。如果您看到奇怪的行为,请尝试自己复制它。如果一切正常,请在 three.js 讨论页面上发帖,看看他们是否认为值得将其报告为错误。 (我对我的代码错误持开放态度,但我的例子是高度概括的......)
  • 我认为这应该包含在 Three.js 中。
猜你喜欢
  • 1970-01-01
  • 2014-08-23
  • 2013-07-12
  • 2018-01-14
  • 2021-08-16
  • 2015-07-12
  • 1970-01-01
  • 2023-01-18
  • 1970-01-01
相关资源
最近更新 更多