在3D空间中旋转后计算顶点位置

时间:2017-11-22 17:53:39

标签: javascript math 3d rotation trigonometry

我想在javascript中旋转Y轴(在我自己的3D引擎中) 我尝试了这个功能:

function rotateY(amount) {
  for (var i = 0; i < points.length; i++) {
    points[i].z = Math.sin(amount) * points[i].x + Math.cos(amount) * points[i].z;
    points[i].x = Math.cos(amount) * points[i].x - Math.sin(amount) * points[i].z;
  }
}

它正在旋转,但每次旋转它都会改变它的x和z刻度,因此它变得更薄了。你能帮我解决一下如何旋转它吗?谢谢:))

1 个答案:

答案 0 :(得分:1)

假设i)旋转分别对应于全局原点而不是对象本身,以及ii)您想要应用增量(如果我们不能采用这些,请参见下文):

对于每一点:
1.找到该点相对于轴的距离 2.找到该点相对于轴的当前角度 3.使用基本的二维cos / sin polar projection,因为排除的轴是unit vector

function rotateY( points, deltaAngle ) {

    const _points = points;

    if ( ! Array.isArray( points ) ) points = [ points ];

    for ( let i = 0; i < points.length; i ++ ) {

        const newAngle = Math.atan2( points[ i ].z, points[ i ].x ) + deltaAngle;
        const distance = ( points[ i ].x ** 2 + points[ i ].z ** 2 ) ** ( 1 / 2 );

        points[ i ].x = distance * Math.cos( newAngle );
        points[ i ].z = distance * Math.sin( newAngle );

    }

    return _points;

}

对于X和Z旋转,算法是相同的,只要Math.atan2中使用的第一个轴与使用Math.sin的轴相同。

  

注意:我使用了exponentiation operator。除非您使用Babel /类似的东西或不关心IE /旧用户,否则我不会在制作中使用此功能。

如果不能采用假设ii),我们只想存储点的原始角度,并将newAngle定义为原始角度加上新角度。

如果不能采取假设i),那就变得复杂了。如果对象的轴只是偏移,您可以在newAngledistance中减去该偏移量,并在设置xz时将其添加回来。如果轴本身不是分别与全局轴平行,则您需要切换到使用quaternion以避免gimbal lock。我建议复制或至少查看three.js's implementation