首页 文章

Scenekit 形状介于 4 点之间

提问于
浏览
2

鉴于我在上一个问题中采用的路线:

ARKit - 在 Swift 3 中的平面上的 2 个矢量点之间放置一个 SCNPlane

...seems 有缺陷,我正在寻找其他选择。我可以在两个节点之间绘制一条线,然后我可以在那些节点之上创建节点,有效地在一个正方形中,但即使我在它们之间画线,我也不能将它变成一个形状。在 Scenekit 中是否可以绘制一个形状(正方形),其中每个角都连接到一个节点。

我可以创建一个平面,将它放在一个节点上,转换枢轴然后旋转,但它并不总是有效,但 SCNGeometry 线可以。

谢谢

1 回答

  • 5

    所以答案,至少我的解决方案是使用 SCNGeometry 三角形。我想要一个正方形(而不是立方体)作为增强现实中的墙,所以我只使用映射墙的 4 个角的 4 个节点构建了 2 个三角形。

    构建三角形的类:

    extension SCNGeometry {
    
        class func triangleFrom(vector1: SCNVector3, vector2: SCNVector3, vector3: SCNVector3) -> SCNGeometry {
    
            let indices: [Int32] = [0, 1, 2]
    
            let source = SCNGeometrySource(vertices: [vector1, vector2, vector3])
    
            let element = SCNGeometryElement(indices: indices, primitiveType: .triangles)
    
            return SCNGeometry(sources: [source], elements: [element])
        }
    }
    

    使用以下内容调用 2 个三角形的点[3]和[4]:

    let thirdPoint = firstPoint.clone()
    thirdPoint.position = SCNVector3Make(thirdPoint.position.x, 
    thirdPoint.position.y + Float(1.5), thirdPoint.position.z)
    sceneView.scene.rootNode.addChildNode(thirdPoint)
    
    let fourthPoint = secondPoint.clone()
    fourthPoint.position = SCNVector3Make(fourthPoint.position.x, 
    fourthPoint.position.y + Float(1.5), fourthPoint.position.z)
    sceneView.scene.rootNode.addChildNode(fourthPoint)
    
    let triangle = SCNGeometry.triangleFrom(vector1: firstPoint.position, vector2: secondPoint.position, vector3: fourthPoint.position)
    let triangleNode = SCNNode(geometry: triangle)
    triangleNode.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
    triangleNode.geometry?.firstMaterial?.isDoubleSided = true
    sceneView.scene.rootNode.addChildNode(triangleNode)
    
    let triangle2 = SCNGeometry.triangleFrom(vector1: firstPoint.position, vector2: thirdPoint.position, vector3: fourthPoint.position)
    let triangle2Node = SCNNode(geometry: triangle2)
    triangle2Node.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
    triangle2Node.geometry?.firstMaterial?.isDoubleSided = true
    sceneView.scene.rootNode.addChildNode(triangle2Node)
    

    这都是基于通过在 ARKit 中选择墙的底部 2 个点来创建 2 个初始节点。

    希望对其他寻找类似答案的人有意义。

    编辑:添加材料

    这是一个稍微不同的扩展和添加材料的代码,墙的最终结果保持不变:

    extension SCNGeometry {
    
        class func Quad() -> SCNGeometry {
    
            let verticesPosition = [
                SCNVector3(x: -0.242548823, y: -0.188490361, z: -0.0887458622),
                SCNVector3(x: -0.129298389, y: -0.188490361, z: -0.0820985138),
                SCNVector3(x: -0.129298389, y: 0.2, z: -0.0820985138),
                SCNVector3(x: -0.242548823, y: 0.2, z: -0.0887458622)
            ]
    
            let textureCord = [
                CGPoint(x: 1, y: 1),
                CGPoint(x: 0, y: 1),
                CGPoint(x: 0, y: 0),
                CGPoint(x: 1, y: 0),
            ]
    
            let indices: [CInt] = [
                0, 2, 3,
                0, 1, 2
            ]
    
            let vertexSource = SCNGeometrySource(vertices: verticesPosition)
            let srcTex = SCNGeometrySource(textureCoordinates: textureCord)
            let date = NSData(bytes: indices, length: MemoryLayout<CInt>.size * indices.count)
    
            let scngeometry = SCNGeometryElement(data: date as Data, 
    primitiveType: SCNGeometryPrimitiveType.triangles, primitiveCount: 2, 
    bytesPerIndex: MemoryLayout<CInt>.size)
    
            let geometry = SCNGeometry(sources: [vertexSource,srcTex], 
    elements: [scngeometry])
    
            return geometry
    
        }
    
    }
    

    然后只需在 viewDidLoad()中调用它并应用材质

    let scene = SCNScene()
    
    let quad = SCNGeometry.Quad()
    
    let (min, max) = quad.boundingBox
    
    let width = CGFloat(max.x - min.x)
    let height = CGFloat(max.y - min.y)
    
    quad.firstMaterial?.diffuse.contents = UIImage(named: "wallpaper.jpg")
    quad.firstMaterial?.diffuse.contentsTransform = SCNMatrix4MakeScale(Float(width), Float(height), 1)
    quad.firstMaterial?.diffuse.wrapS = SCNWrapMode.repeat
    quad.firstMaterial?.diffuse.wrapT = SCNWrapMode.repeat
    
    let node = SCNNode()
    node.geometry = quad
    scene.rootNode.addChildNode(node)
    
    sceneView.scene = scene
    

相关问题