これは、最初の一見よりも複雑な質問です。
SceneKitは、ノードを生成するために使用されたジオメトリの座標を元の縮尺/基準で保存します。オブジェクトが作成されてもそれらは変更されません。 SCNPlane
またはSCNBox
のようなプリミティブの場合、これらのジオメトリはシーン内で共有されます。したがって、異なる位置、回転、および拡大率で異なるプレーンまたはボックスの束がある場合は、SCNGeometrySource
を照会するときに同じ頂点を取得します。ここでの検索についての良い議論があります:Extracting vertices from scenekit。しかし、そのアプローチは、あなたのローカル座標空間のコーナーを与えることはありません。
我々はSCNNode
とSCNGeometry
に取り組む二つの機能を持っている:boundingBox
とboundingSphere
(彼らはプロトコルSCNBoundingVolume
で定義されています)。 boundingBox
では、最小値と最大値の2つのポイントが得られます。立方体の2つの反対側の角から、平面の頂点を見つけることができます。しかし、もう一つの合併症があります。これらの関数はいずれもローカル座標(ノード自体が使用する座標系)で応答を返します。だから私たちはまだ立ち往生しています:私の飛行機や箱のすべてが同じバウンディングボックスを持っています。
私が思いついた答えは、SCNNodeのconvertPosition(_, to: node)
を使ってシーンのルートノードを渡すことでした。それは最終的に私にルートノードの座標空間にバウンディングボックスを与えます。
for node in [custom1, custom2, plainPlane1, plainPlane2] {
print(node.name!)
print(node.boundingBox.max)
print(node.boundingBox.min)
print(node.convertPosition(node.boundingBox.min, to: scene.rootNode))
print(node.convertPosition(node.boundingBox.max, to: scene.rootNode))
}
このシーンのため
custom 1
SCNVector3(x: 0.300000011920929, y: 0.100000001490116, z: 0.0)
SCNVector3(x: 0.0, y: -0.100000001490116, z: 0.0)
SCNVector3(x: 0.0, y: -0.100000001490116, z: -1.0)
SCNVector3(x: 0.300000011920929, y: 0.100000001490116, z: -1.0)
custom 2
SCNVector3(x: 0.300000011920929, y: 0.100000001490116, z: 0.0)
SCNVector3(x: 0.0, y: -0.100000001490116, z: 0.0)
SCNVector3(x: 0.200000002980232, y: 0.429289322037836, z: -1.07071067796216)
SCNVector3(x: 0.500000014901161, y: 0.570710677962164, z: -0.929289322037836)
plain plane 1
SCNVector3(x: 0.5, y: 1.0, z: 0.0)
SCNVector3(x: -0.5, y: -1.0, z: 0.0)
SCNVector3(x: -0.5, y: -1.0, z: -2.0)
SCNVector3(x: 0.5, y: 1.0, z: -2.0)
plain plane 2
SCNVector3(x: 0.5, y: 1.0, z: 0.0)
SCNVector3(x: -0.5, y: -1.0, z: 0.0)
SCNVector3(x: -9.18485139438876e-18, y: -0.300000011920929, z: -1.84999999403954)
SCNVector3(x: 9.18485139438876e-18, y: 0.300000011920929, z: -2.15000000596046)
を生産する:あなたは、変換行列を述べた
//: Playground - noun: a place where people can play
import Cocoa
import SceneKit
import PlaygroundSupport
let positions = [SCNVector3Make( 0, -0.1, 0),
SCNVector3Make( 0.3, -0.1, 0),
SCNVector3Make( 0, 0.1, 0),
SCNVector3Make( 0.3, 0.1, 0),
]
let indices :[UInt16] = [
0, 1, 2,
1, 3, 2,
]
let vertexSource = SCNGeometrySource(vertices: positions, count: 4)
let indexData = NSData(bytes: indices, length: MemoryLayout.size * indices.count)
let newElement = SCNGeometryElement(data: NSData(bytes: indices,
length: indices.count * MemoryLayout.size) as Data,
primitiveType: .triangles ,
primitiveCount: 2,
bytesPerIndex: MemoryLayout.size)
let sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 600, height: 400))
sceneView.allowsCameraControl = true
sceneView.autoenablesDefaultLighting = true
sceneView.backgroundColor = NSColor.darkGray
sceneView.showsStatistics = true
PlaygroundPage.current.liveView = sceneView
let scene = SCNScene()
sceneView.scene = scene
let geometry = SCNGeometry(sources: [vertexSource], elements: [newElement])
geometry.firstMaterial?.diffuse.contents = NSColor.red
geometry.firstMaterial?.isDoubleSided = true
let custom1 = SCNNode(geometry: geometry)
custom1.position = SCNVector3Make(0, 0, -1)
custom1.name = "custom 1"
scene.rootNode.addChildNode(custom1)
let custom2 = SCNNode(geometry: geometry)
custom2.position = SCNVector3Make(0.2, 0.5, -1)
custom2.rotation = SCNVector4Make(1, 0, 0, CGFloat(M_PI_4))
custom2.name = "custom 2"
scene.rootNode.addChildNode(custom2)
let plainPlaneGeometry = SCNPlane(width: 1, height: 2)
plainPlaneGeometry.firstMaterial?.diffuse.contents = NSColor.yellow
plainPlaneGeometry.firstMaterial?.isDoubleSided = true
let plainPlane1 = SCNNode(geometry: plainPlaneGeometry)
plainPlane1.position = SCNVector3Make(0, 0, -2)
plainPlane1.name = "plain plane 1"
scene.rootNode.addChildNode(plainPlane1)
let plainPlane2 = SCNNode(geometry: plainPlaneGeometry)
plainPlane2.position = SCNVector3Make(0, 0, -2)
plainPlane2.rotation = SCNVector4Make(0, 1, 0, CGFloat(M_PI_2))
plainPlane2.scale = SCNVector3Make(0.3, 0.3, 0.3)
plainPlane2.name = "plain plane 2"
scene.rootNode.addChildNode(plainPlane2)
for node in [custom1, custom2, plainPlane1, plainPlane2] {
print(node.name!)
print(node.boundingBox.max)
print(node.boundingBox.min)
// print(node.transform)
print(node.convertPosition(node.boundingBox.min, to: scene.rootNode))
print(node.convertPosition(node.boundingBox.max, to: scene.rootNode))
}
:
ここでは、以下のフルMacOSの遊び場です。 Need better and simpler understanding of CATransform3D(2つの優れたWikipediaの記事を引用しています)、そして簡単に概要をダイジェストするのは、http://sketchytech.blogspot.com/2014/12/explaining-catransform3d-matrix.htmlです。
私は問題を探って、変換に関する多くのスタックオーバーフローに関する質問を見ましたが、scnmatrix mのものの意味を説明しません。この記事は、英語が私の母国語ではなく、英語でいくつかのことを記述するのが難しいため、私はシーンキットについて何も読んでいないように思えるかもしれません – Asphys
この質問と飛行機の頂点に関するあなたのもう一つの質問から、私はまだ理解しませんあなたが見たいと思う効果。あなたは私達に荒い鉛筆のスケッチを描いてそれをアップロードできますか? –
@HalMueller私は彼が彼の飛行機オブジェクトを構築するために作成した各頂点のシーン座標の後ろだと思います。 – Confused