gpt4 book ai didi

swift - 获取节点场景包中顶点的位置

转载 作者:搜寻专家 更新时间:2023-10-31 08:22:20 25 4
gpt4 key购买 nike

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

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。

最佳答案

这是一个比乍看起来更复杂的问题。

SceneKit 将存储用于在原始比例/基础中生成节点的几何体的坐标。一旦对象被创建,这些就不会改变。对于像 SCNPlaneSCNBox 这样的基元,这些几何图形在场景中共享。因此,如果您有一堆不同的平面或盒子,它们都处于不同的位置、旋转和缩放比例,那么当您查询 SCNGeometrySource 时,您将得到相同的顶点。此处对该检索进行了很好的讨论:Extracting vertices from scenekit .但这种方法不会为您提供局部坐标空间中的角点。

我们有两个作用于 SCNNodeSCNGeometry 的函数:boundingBoxboundingSphere(它们被定义在协议(protocol) 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 1SCNVector3(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 2SCNVector3(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 1SCNVector3(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 2SCNVector3(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 :

//: Playground - noun: a place where people can playimport Cocoaimport SceneKitimport PlaygroundSupportlet 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 = truesceneView.autoenablesDefaultLighting = truesceneView.backgroundColor = NSColor.darkGraysceneView.showsStatistics = truePlaygroundPage.current.liveView = sceneViewlet scene = SCNScene()sceneView.scene = scenelet geometry = SCNGeometry(sources: [vertexSource], elements: [newElement])geometry.firstMaterial?.diffuse.contents = NSColor.redgeometry.firstMaterial?.isDoubleSided = truelet 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.yellowplainPlaneGeometry.firstMaterial?.isDoubleSided = truelet 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 .

关于swift - 获取节点场景包中顶点的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41652158/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com