2017-01-14 47 views
2

我有一個以編程方式創建的平面,我想獲取平面所具有的一個頂點的座標。事情是這樣的:print(Plane.vertices[1].position),它可能打印出類似這樣:(X:1 Y:1),和print(Plane.vertices[2].position)打印(X - 1,Y:1)獲取節點scenekit中頂點的位置

enter image description here 我這是怎麼形成的平面:

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<CInt>.size * indices.count) 


     let newElement = SCNGeometryElement(data: NSData(bytes: indices, length: indices.count * MemoryLayout<Int16>.size) as Data, primitiveType: .triangles , primitiveCount: 2, bytesPerIndex: MemoryLayout<Int16>.size) 

     let geometry = SCNGeometry(sources: [vertexSource], elements: [newElement]) 
     custom = SCNNode(geometry: geometry) 
     scene.rootNode.addChildNode(custom!) 
     custom?.position = SCNVector3Make(0, 0, 0) 

我認爲這可以通過變換完成,但是自定義的變換有很多奇怪的東西,比如m11,m12,m13,這些我都不明白。

+0

我把這個問題搜索了一遍,看了很多堆棧溢出的問題,但他們沒有解釋scnmatrix是什麼意思。這篇文章可能聽起來像我還沒有讀過關於scenekit的任何內容,因爲英語不是我的第一語言,很難用英語來形容一些東西。 – Asphys

+1

從這個問題和另一個關於飛機頂點的問題,我仍然不明白你想看到什麼效果。你能畫一張粗略的鉛筆素描並上傳嗎? –

+0

@HalMueller我認爲他是在創建他的平面物體的每個頂點的場景座標之後。 – Confused

回答

4

這是一個比乍看起來更復雜的問題。

SceneKit將以原始比例/基礎存儲用於生成節點的幾何體座標。這些對象一旦創建就不會改變。對於像SCNPlaneSCNBox這樣的圖元,這些幾何圖形將在場景中共享。所以如果你有一堆不同的平面或者盒子,都在不同的位置,旋轉和縮放,當你查詢SCNGeometrySource時,你會得到相同的頂點。這裏有一個很好的討論:Extracting vertices from scenekit。但是,這種方法不會給你在你的本地座標空間的角落。

我們有上SCNNodeSCNGeometry工作兩個功能:boundingBoxboundingSphere(他們在協議SCNBoundingVolume定義)。 boundingBox給你兩點,最小值和最大值。從立方體的兩個相對角落,您可以計算出您飛機的角落頂點。不過,還有另一個複雜因素。這兩個函數都以局部座標(節點本身使用的座標系)返回答案。所以我們仍然堅持:我的每一架飛機或箱子都會有相同的邊界框。

我想出的答案是使用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) 

對於這樣的情景: enter image description here

這裏是下面的完整MacOS的遊樂場:

 
//: 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)) 
} 

你提到的變換矩陣。在Need better and simpler understanding of CATransform3D(引用了兩篇很好的維基百科文章)以及在http://sketchytech.blogspot.com/2014/12/explaining-catransform3d-matrix.html上易於摘要概述的文章中,有一個很好的解釋。