【问题标题】:Rotate SCNVector3 around an axis绕轴旋转 SCNVector3
【发布时间】:2017-08-30 17:23:44
【问题描述】:

这可能更像是一个线性代数问题,但假设我有一个 SCNVector,我想要一个新的 SCNVector,它与围绕 y 轴(或任何轴)的原始 SCNVector 成一定角度。所以理想情况下:

extension SCNVector3 {  
    // assume dot, cross, length, +, - functions are available.
    enum Axis {
        case x, y, z
    }
    func rotatedVector(aroundAxis: Axis, angle: Float) -> SCNVector3 {
        // code from smart person goes here
    }
}

例如(0,0,-1).rotatedVector(aroundAxis: y, angle: pi/2) = (1,0,0)

谢谢!

【问题讨论】:

    标签: ios linear-algebra scenekit trigonometry


    【解决方案1】:

    尝试使用四元数https://developer.apple.com/documentation/accelerate/working_with_quaternions

    extension SCNVector3 {
        enum Axis {
            case x, y, z
            
            func getAxisVector() -> simd_float3 {
                switch self {
                case .x:
                    return simd_float3(1,0,0)
                case .y:
                    return simd_float3(0,1,0)
                case .z:
                    return simd_float3(0,0,1)
                }
            }
        }
    
        func rotatedVector(aroundAxis: Axis, angle: Float) -> SCNVector3 {
            /// create quaternion with angle in radians and your axis
            let q = simd_quatf(angle: angle, axis: aroundAxis.getAxisVector())
            
            /// use ACT method of quaternion
            let simdVector = q.act(simd_float3(self))
            
            return SCNVector3(simdVector)
        }
    }
    

    用途:

    let a = SCNVector3(5,0,0)
    
    let b = a.rotatedVector(aroundAxis: SCNVector3.Axis.y, angle: -.pi/2)
    
    // SCNVector3(x: 0.0, y: 0.0, z: 5.0)
    

    你也可以围绕任何矢量旋转:

    let simdVector = q.act(simd_normalize(simd_float3(x: 0.75, y: 0.75, z: -0.2)))
    

    【讨论】:

      【解决方案2】:

      一般情况下使用Rodrigues' rotation formula

      Rodrigues 的旋转公式是一种有效的旋转算法 空间中的向量,给定轴和旋转角度

      对于初始向量v,旋转轴单位向量k和角度theta结果为

      vrot = v * cos(theta) + (k x v强>) * sin(theta) + k * (k.dot.v) * (1 - cos(theta))

      【讨论】:

      • 是右手还是左手单位空间?
      • Emm... 我总是用右手处理旋转角 theta - CCW 逆轴方向。似乎对于包含向量积的第二项来说,方便性在这里很重要。但它也包含正弦函数,所以我不能说——方便性是否会影响结果——它取决于角度方向的约定。
      【解决方案3】:

      感谢comment on gamedev.net 我想我有我需要的东西。它不适用于任意角度,但事实证明我只需要 90°,所以这对我有用。这是解决方案:

      extension SCNVector3 {
          enum Axis { case x, y, z }
          enum Direction { case clockwise, counterClockwise }
          func orthogonalVector(around axis: Axis, direction: Direction) -> SCNVector3 {
              switch axis {
              case .x: return direction == .clockwise ? SCNVector3(self.x, -self.z, self.y) : SCNVector3(self.x, self.z, -self.y)
              case .y: return direction == .clockwise ? SCNVector3(-self.z, self.y, self.x) : SCNVector3(self.z, self.y, -self.x)
              case .z: return direction == .clockwise ? SCNVector3(self.y, -self.x, self.z) : SCNVector3(-self.y, self.x, self.z)
              }
          }
      }
      

      【讨论】:

      • 这个怎么用
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-12
      • 2016-12-11
      • 2013-09-15
      • 2016-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多