当前位置:  开发笔记 > 前端 > 正文

获取节点scenekit中顶点的位置

如何解决《获取节点scenekit中顶点的位置》经验,为你挑选了1个好方法。

我有一个以编程方式创建的平面,我想获得该平面所具有的一个顶点的坐标.像这样的东西:print(Plane.vertices[1].position)它可能会打印如下:(x:1,y:1),并print(Plane.vertices[2].position)打印(x - 1,y:1)

在此输入图像描述 这就是我创造飞机的方式:

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 geometry = SCNGeometry(sources: [vertexSource], elements: [newElement])
        custom = SCNNode(geometry: geometry)
        scene.rootNode.addChildNode(custom!)
        custom?.position = SCNVector3Make(0, 0, 0)

我认为这可以通过变换完成,但是自定义变换有很多奇怪的东西,比如m11,m12,m13,我不明白.



1> Hal Mueller..:

这是一个比初看起来更复杂的问题.

SceneKit将存储用于以原始比例/基础生成节点的几何体的坐标.创建对象后,这些不会更改.对于像SCNPlane或的基元SCNBox,这些几何在场景中共享.因此,如果您有一堆不同的平面或方框,所有位于不同的位置,旋转和缩放,当您查询时,您将获得相同的顶点SCNGeometrySource.这里有一个很好的讨论:从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)

对于这个场景: 在此输入图像描述

这是下面的完整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))
}

你提到了转换矩阵.有一个很好的解释,它看起来是什么样的,它是如何工作的,需要更好,更简单地理解CATransform3D(引用两篇优秀的维基百科文章),以及一个易于理解的概述,请访问http://sketchytech.blogspot.com/2014/ 12/explain-catransform3d-matrix.html.

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有