【问题标题】:Is there a Metal library function to create a simd rotation matrix?是否有金属库函数来创建 simd 旋转矩阵?
【发布时间】:2018-04-01 19:44:04
【问题描述】:

Apple 系统中似乎至少有六个矩阵库。其中之一是 simd 库,其类型在 CPU 和 GPU 代码中的工作方式相同。

import simd
let mat = float3x3(...)
let vec = float3(...)
mat * vec

我无法找到它的文档。与大多数东西不同,它不会出现在 Xcode 的文档浏览器中。我知道另一个库 (GLKit) 具有具有构建旋转矩阵功能的矩阵类型。例如,

GLKMatrix3MakeXRotation(radians)
GLKMatrix3RotateY(mat, radians)

simd 矩阵类型有类似的功能吗?

【问题讨论】:

    标签: metal


    【解决方案1】:

    你可以通过simd_quat。四元数对角轴表示具有simple connection。 SIMD库可以从角度轴构造一个四元数,还有一个函数可以从一个四元数构造一个float3x3。 (这是 C++,但同样的想法应该适用于 Swift)。

    inline float3x3 MakeRotation(float radians, float x, float y, float z) {
      simd_quatf quat = simd_quaternion(radians, (simd_float3){x, y, z});
      return simd_matrix3x3(quat);
    }
    

    【讨论】:

      【解决方案2】:

      目前在 simd.framework、Metal 或 MetalKit 中没有用于创建此类矩阵的实用程序函数。但是,您可以使用 GLKit 的矩阵函数并将生成的 GLKMatrix4s 转换为 float4x4s,然后再将它们复制到 Metal 缓冲区中以便在着色器中使用。

      GLKMatrix4 只是一个包含 16 个浮点数组的联合,存储在 column-major order 中。

      因此,我们可以在float4x4 上编写一个扩展,允许使用 GLKit 矩阵初始化一个 simd 矩阵:

      extension float4x4 {
          init(matrix: GLKMatrix4) {
              self.init(columns: (float4(x: matrix.m00, y: matrix.m01, z: matrix.m02, w: matrix.m03),
                                  float4(x: matrix.m10, y: matrix.m11, z: matrix.m12, w: matrix.m13),
                                  float4(x: matrix.m20, y: matrix.m21, z: matrix.m22, w: matrix.m23),
                                  float4(x: matrix.m30, y: matrix.m31, z: matrix.m32, w: matrix.m33)))
          }
      }
      

      我通过创建一个表示围绕 +Z 轴逆时针旋转 45 度的 GLKit 矩阵来验证生成的矩阵符合我的期望,并确保它确实将单位向量 <1, 0, 0> 旋转到单位上矢量<sqrt(2)/2, sqrt(2)/2, 0>:

      let rotation = GLKMatrix4MakeZRotation(.pi / 4)
      let simdRotation = float4x4(matrix: rotation)
      let v = float4(1, 0, 0, 0)
      let vp = simdRotation * v
      print("\(vp)")
      
      
      > float4(0.707107, 0.707107, 0.0, 0.0)
      

      请注意,我在这里遵守惯例,即矩阵-矢量乘法将矢量视为列矢量并将矩阵放在左侧,这是当前使用中最常见的惯例。

      关于 GLKit 和 Metal 的剪辑空间,您应该注意一个警告。您可以阅读有关该问题以及如何纠正它的信息,here

      【讨论】:

      • 谢谢!听起来GLKMatrix4(或 3)与float4x4(或 3x3)具有相同的内存布局,因此如果需要,您可以将内存重新解释为其中之一。 ?我看到由于 Swift 允许我定义像 * 和 + 这样的运算符,GLK 矩阵变得和 simd 矩阵一样方便。
      • 对。我提供了初始化程序作为如何“安全地”将一个转换为另一个的示例,但由于它们具有相同的布局,您可以轻松地将GLKMatrix4 的内容重新解释为float4x4GLKMatrix3 不是这样,它有 9 个打包的浮点成员,而 float3x3 有一个由三个 float3 组成的数组,每个数组的步幅为 16 字节,而不是 12 字节用于 simd 对齐原因。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-09
      • 2016-12-13
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多