代码之家  ›  专栏  ›  技术社区  ›  Jacob

在三维空间中旋转后计算顶点位置

  •  1
  • Jacob  · 技术社区  · 7 年前

    我试图在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 回复  |  直到 6 年前
        1
  •  2
  •   vox    7 年前

    假设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 定义为原始角度加上新角度。

    新角度 distance 并在设置时重新添加 x z . 如果轴本身不分别平行于全局轴,则需要切换到使用 quaternion 为了避免 gimbal lock . 我建议复制或至少看一看 three.js's implementation .