了解 ARKit 中的 3D 对象变换 属性
Understanding 3D object transform property in ARKit
假设我在 ViewDidLoad
中将狗等 3D 模型作为子节点添加到场景的根节点。我打印出狗节点的 transform
和 worldTransform
属性,它们都是 4x4 单位矩阵。
旋转缩放定位后,我重新打印了transform
和worldTransform
属性。我无法理解如何阅读它们。哪一列是指位置、大小或方向?
在任何变换下,我如何计算出 1) 狗的正面朝向哪个方向,假设在 viewDidLoad
中正面朝向 (0,0,-1)
方向,以及 2) 高度和狗的宽度?
变换矩阵的完整介绍是 a) 超出了简单 SO 答案的范围和 b) 3D 图形编程中的基本主题,您可以找到无数或两本关于该主题的书籍、教程和资源.这里有两篇不错的文章:
- Linear Algebra for Graphics Programming 在 metalbyexample.com
- Transformations 在 learnopengl.com
不过,由于您在 SceneKit 中使用 ARKit,因此有许多方便的实用程序可用于处理变换,因此您通常不需要深入研究数学。
which direction the front of the dog is facing?
节点在其局部坐标 space 中始终 "facing" 朝向 (0,0,-1)
。 (请注意,这是 SceneKit 的内在概念 "facing",它可能映射也可能不映射任何自定义资产的设计方式。如果您导入了 OBJ、DAE 或任何在 3D 创作工具中构建的文件,并且在那个工具狗的鼻子指向 (0,0,-1)
,你的狗面向 "right" 方向。)
你可以从 SCNNode.simdLocalFront
得到这个方向——注意它是一个 static/class 属性,因为在局部 space 中,所有节点的前面总是相同的方向。
您可能更感兴趣的是节点自己对其 "front" 的想法如何转换为世界 space — 也就是说,狗相对于其余部分面向哪个方向场景。这里有两种方法:
Convert simdLocalFront
到世界 space,你可以用任何其他向量的方式:node.convert(node.simdLocalFront, to: nil)
。 (请注意,如果您将 to
参数保留为零,您将转换为世界 space。)
使用 simdWorldFront
属性,它会为您进行转换。
the height and width of the dog?
高度和宽度与变换无关。转换(主要)告诉您某物在哪里以及它面向哪个方向。
假设你没有缩放你的节点,不过,它在本地 space 中的边界框描述了它在世界中的尺寸 space:
let (min, max) = node.boundingBox
let height = abs(max.y - min.y)
let width = abs(max.x - min.x)
let depthiness = abs(max.z - min.z)
(但请注意,这是固有高度:例如,如果您有一个站立的人物模型,然后旋转它使他们躺下,这个高度仍然是从头到脚。)
假设我在 ViewDidLoad
中将狗等 3D 模型作为子节点添加到场景的根节点。我打印出狗节点的 transform
和 worldTransform
属性,它们都是 4x4 单位矩阵。
旋转缩放定位后,我重新打印了transform
和worldTransform
属性。我无法理解如何阅读它们。哪一列是指位置、大小或方向?
在任何变换下,我如何计算出 1) 狗的正面朝向哪个方向,假设在 viewDidLoad
中正面朝向 (0,0,-1)
方向,以及 2) 高度和狗的宽度?
变换矩阵的完整介绍是 a) 超出了简单 SO 答案的范围和 b) 3D 图形编程中的基本主题,您可以找到无数或两本关于该主题的书籍、教程和资源.这里有两篇不错的文章:
- Linear Algebra for Graphics Programming 在 metalbyexample.com
- Transformations 在 learnopengl.com
不过,由于您在 SceneKit 中使用 ARKit,因此有许多方便的实用程序可用于处理变换,因此您通常不需要深入研究数学。
which direction the front of the dog is facing?
节点在其局部坐标 space 中始终 "facing" 朝向 (0,0,-1)
。 (请注意,这是 SceneKit 的内在概念 "facing",它可能映射也可能不映射任何自定义资产的设计方式。如果您导入了 OBJ、DAE 或任何在 3D 创作工具中构建的文件,并且在那个工具狗的鼻子指向 (0,0,-1)
,你的狗面向 "right" 方向。)
你可以从 SCNNode.simdLocalFront
得到这个方向——注意它是一个 static/class 属性,因为在局部 space 中,所有节点的前面总是相同的方向。
您可能更感兴趣的是节点自己对其 "front" 的想法如何转换为世界 space — 也就是说,狗相对于其余部分面向哪个方向场景。这里有两种方法:
Convert
simdLocalFront
到世界 space,你可以用任何其他向量的方式:node.convert(node.simdLocalFront, to: nil)
。 (请注意,如果您将to
参数保留为零,您将转换为世界 space。)使用
simdWorldFront
属性,它会为您进行转换。
the height and width of the dog?
高度和宽度与变换无关。转换(主要)告诉您某物在哪里以及它面向哪个方向。
假设你没有缩放你的节点,不过,它在本地 space 中的边界框描述了它在世界中的尺寸 space:
let (min, max) = node.boundingBox
let height = abs(max.y - min.y)
let width = abs(max.x - min.x)
let depthiness = abs(max.z - min.z)
(但请注意,这是固有高度:例如,如果您有一个站立的人物模型,然后旋转它使他们躺下,这个高度仍然是从头到脚。)