iOS の SceneKit で SCNNode の位置や大きさをだいたい把握するために boundingBox
プロパティを参照することが多いと思いますが、このプロパティの指す値は公式ドキュメント(下記)にあるとおり、そのノードのローカル座標系における値となるため注意が必要です。
SCNBoundingVolume - boundingBox
Scene Kit defines a bounding box in the local coordinate space using two points identifying its corners, which implicitly determine six axis-aligned planes marking its limits.
これについてボックス形状の SCNBox をジオメトリとした SCNNode を例に整理していきます
まず、各辺が 1 の立方体の SCNNode boxNode
を定義してシーンに追加します。
let scene = SCNScene()
let box = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
let boxNode = SCNNode(geometry: box)
scene.rootNode.addChildNode(boxNode)
print(boxNode.boundingBox)
この時、boxNode
の boundingBox
は次のようになっています。
(min: __C.SCNVector3(x: -0.5, y: -0.5, z: -0.5), max: __C.SCNVector3(x: 0.5, y: 0.5, z: 0.5))
原点を中心に配置されていることがわかります。それではこの boxNode
の位置やスケールを変更してみます。
boxNode.position.x = 1
boxNode.scale.y = 2
print(boxNode.boundingBox)
X軸方向に +1 移動し、Y軸方向に倍に伸びた形状になりました。ここでboundingBox
の値はどうなっているかというと...
(min: __C.SCNVector3(x: -0.5, y: -0.5, z: -0.5), max: __C.SCNVector3(x: 0.5, y: 0.5, z: 0.5))
はい、変更する前と同じです。
最初に述べた通り、boundingBox
はその SCNNode のローカル座標系のものだからです。SCNNode の position
, scale
といったプロパティを変更すると、その親のノードの座標系での位置やスケールが変化していることになります(position
プロパティの公式ドキュメントには次のように書かれています)。
The node’s position locates it within the coordinate system of its parent,
次に、boxNode
の親となる空の SCNNode parentNode
をつくり boxNode
のみを子として追加して boundingBox
を見てみましょう。
let parentNode = SCNNode()
parentNode.addChildNode(boxNode)
scene.rootNode.addChildNode(parentNode)
print(parentNode.boundingBox)
(min: __C.SCNVector3(x: 0.49999997, y: -0.99999994, z: -0.49999997), max: __C.SCNVector3(x: 1.4999999, y: 0.99999994, z: 0.49999997))
計算の誤差のようなものは出ていますが、実際のカメラからの見た目上の位置と大きさに相当する値になりました。この値は SCNNode の各プロパティや convert~
系のメソッドで求めることはできると思いますが、一つ空の親ノードをかませてあげることで簡単に求めることができました。