如何以编程方式撤消位置平移到枢轴点的问题?

时间:2019-01-03 05:58:30

标签: three.js

我认为这最终是一个非常简单的问题,但是很难描述,因此,我提供了一个有效的示例here (在示例中按“ z”以查看带有不需要的平移和“ x”键的旋转)以补偿性重新定位旋转)。

基本上,我正在尝试绕着通过gltf(oculus rift触摸控制器的模型)加载的复杂模型的z轴旋转对象(指图)。绕x轴旋转90度很容易。垂直于x轴。关于z轴,这比较困难,因为指杆所连接的平面成30度角。我意识到,如果指尖使用局部坐标,这不会有问题,但是'thumb.rotation.z'似乎并没有使用局部坐标,而是围绕模型(整体)旋转,甚至场景的全局y和z(?)。无论如何,经过一堆混乱之后,我可以通过执行以下操作使事情正常进行:

// occulus plane is angle at 30 deg, which corresponds to
// 5 units forward to 3 units down.
var axis = new THREE.Vector3(0, 5, -3).normalize();
factory.thumbstick.geometry.center();
var dir = (evt.key === 'x' ? 1 : -1);
thumb.rotateOnAxis(axis, factory.ONE_DEG * 5.0 * dir);  

基本上,我绕“倾斜”轴旋转,然后调用“中心”以使指点图以枢轴点为中心,因此它绕枢轴点 而不是旋转>围绕枢轴点(例如绕太阳旋转的地球)。

唯一的问题是,当您调用“ geometry.center()”然后调用“ rotateOnAxis”时,它会将指尖平移到枢轴点:

enter image description here

注意:在调用之前和之后,图钉对象上的位置是(0,0,0)。

根据经验,我确定在翻译后是否像这样改变了指尖的位置:

   // magic numbers compensating position
    var zDisp = 0.0475;
    var yDisp = zDisp / 6.0
    thumb.position.x = 0.001;
    thumb.position.y = -yDisp;
    thumb.position.z = zDisp;

然后(几乎)返回到其原始位置:

enter image description here

问题是这些数字只是通过交互并反复尝试重新定位指尖(即凭经验)来确定的。我根本无法找到一种编程的,分析的,api的方式来恢复原始位置。注意:保存原始位置不起作用,因为在转换前后该位置为零。我尝试过的一些事情是利用全局对象和指图对象的边界球之间的差异,试图在一个距离上得出一些“ sin x-cos x”关系,但没有任何效果。

我的问题是,由于调用'geometry.center()'和rotateOnAxis(转换为枢轴点),我该如何通过编程逆向偏移,而不必求助于经过破解的,经验性的“魔术”数,如果gltf模型发生变化,则可以想象会发生变化。

当然,如果有人还能想出一种更好的方法来实现这种轮换,那也很好。

让我感到震惊的是gltf模型本身的复杂性。这很令人困惑,因为我很难理解它的各个部分:我真的不确定“中心”在哪里,并且在某些情况下,它与“ THREE.AxesHelper”一起出现,我附上它所显示的内容因为'y'实际上是'z',有时'up'实际上是'down'等,并且它很快变得令人困惑。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

对此我的突破是重新构造问题,因为我如何更改指尖的枢轴点,而不是如何将指尖移至(默认和现有的)枢轴点。简而言之,肯尼迪·肯尼迪(JFK):“不要问您如何向枢轴移动,而要问枢轴如何向您移动”:-)

改变攻角后,我很快找到了aforementioned link,这产生了我的解决方案。

我发布了一个更新的故障here,因此现在按z可以正常工作。这是相关的代码部分:

  factory.onModelLoaded = function(evt) {
    console.log(`onModelLoaded: entered`);

    factory.thumbstick = this.scene.children[1].children[2]
    let thumb = factory.thumbstick;
    // make the thumb red so it's easier to see
    thumb.material = (new THREE.MeshBasicMaterial({color: 0xFF7777}));

    // use method from https://stackoverflow.com/questions/28848863/threejs-how-to-rotate-around-objects-own-center-instead-of-world-center/28860849#28860849
    // to translate the pivot point of the thumbstick to the the thumbstick center
    factory.thumbParent = thumb.parent;
    let thumbParent = factory.thumbParent;
    thumbParent.remove(thumb);

    var box = new THREE.Box3().setFromObject( thumb );
    box.getCenter( thumb.position ); // this basically yields my prev. "magic numbers"
    // thumb.position.multiplyScalar( - 1 );
    var pivot = new THREE.Group();
    thumbParent.add( pivot );
    pivot.add( thumb );

    thumb.geometry.center();

    // add axeshelp after centering, otherwise the axes help, as a child of thumb,
    // will increase the bounding box of thumb, and positioning will be wrong.
    axesHelper = new THREE.AxesHelper();
    thumb.add(axesHelper);
  }

哪些允许我的“ z”处理程序旋转而无需执行翻译:

  case 'z':
  case 'Z':
    var axis = new THREE.Vector3(0, 5, -3).normalize();
    var dir = (evt.key === 'z' ? 1 : -1);
    thumb.rotateOnAxis(axis, factory.ONE_DEG * 5.0 * dir);
  break;

有趣的是,对box.getCenter()的调用生成的数字非常接近我的“魔术数字”:

box.getCenter()
Vector3 {x: 0.001487499801442027, y: -0.007357006114165027, z: 0.04779449797522323}

我的经验猜测是{x: 0.001, y: -0.00791666666, z: 0.0475},即%error {x: 32.7%, y: 7.6%, z: 0.61%},所以我的看法非常接近。在z分量上,但仍不是box.getCenter()的“完美”数字。