swift – 获取节点scenekit中顶点的位置

swift – 获取节点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, 我有一个以编程方式创建的平面,我想获得该平面所具有的一个顶点的坐标.像这样的东西: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,SCNVector3Make(  0,0.1,]        let indices :[UInt16] = [            0,1,2,3,]        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)

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

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

SceneKit将存储用于以原始比例/基础生成节点的几何体的坐标.创建对象后,这些不会更改.对于像SCNPlane或SCNBox这样的原语,这些几何在场景中共享.因此,如果您有一堆不同的平面或框,所有处于不同的位置,旋转和缩放,当您查询SCNGeometrySource时,您将获得相同的顶点.这里有一个很好的讨论检索:Extracting vertices from scenekit.但是这种方法不会给你本地坐标空间的角落.

我们有两个适用于SCNNode和SCNGeometry的函数:boundingBox和boundingSphere(它们在协议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: -1.0)SCNVector3(x: 0.300000011920929,z: -1.0)custom 2SCNVector3(x: 0.300000011920929,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: -2.0)SCNVector3(x: 0.5,z: -2.0)plain plane 2SCNVector3(x: 0.5,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 playimport Cocoaimport SceneKitimport PlaygroundSupportlet positions = [SCNVector3Make(  0,]let indices :[UInt16] = [    0,]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,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,-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,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,-2)plainPlane1.name = "plain plane 1"scene.rootNode.addChildNode(plainPlane1)let plainPlane2 = SCNNode(geometry: plainPlaneGeometry)plainPlane2.position = SCNVector3Make(0,-2)plainPlane2.rotation = SCNVector4Make(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,plainPlane2] {    print(node.name!)    print(node.boundingBox.max)    print(node.boundingBox.min)//  print(node.transform)    print(node.convertposition(node.boundingBox.min,to: scene.rootNode))}

你提到了转换矩阵.有一个很好的解释它看起来是什么样的,它是如何在Need better and simpler understanding of CATransform3D工作的(引用了两篇优秀的维基百科文章),以及一个易于理解的概述于http://sketchytech.blogspot.com/2014/12/explaining-catransform3d-matrix.html.

总结

以上是内存溢出为你收集整理的swift – 获取节点scenekit中顶点的位置全部内容,希望文章能够帮你解决swift – 获取节点scenekit中顶点的位置所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1006231.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存