ARKIT - 如何粘贴两个物体

时间:2018-04-02 09:25:50

标签: swift swift4 arkit

我有两个对象(两个立方体)。首先,我将第一个立方体添加到场景中。然后我想添加第二个,我希望它粘在第一个的一侧,在第一个的一侧 - 我将通过点击选择哪一侧(如下图所示)。是否可以单击第一个立方体的一个面和第二个立方体的面自动出现在场景中并坚持第一个立方体?我无法想象如何做到这一点。

Photo

1 个答案:

答案 0 :(得分:0)

创建SCNBoxGeometry时:

  

SCNBox类自动创建SCNGeometryElement对象   需要处理材料的数量。

因此,为了访问这些元素,您需要为Box的每个面创建一个SCNMaterial。然后,您可以执行SCNHitTest来检测已检测到的脸部:

  

当您执行命中测试搜索时,SceneKit会查找SCNGeometry   沿指定光线的对象。对于每个交叉点   ray和几何,SceneKit创建一个命中测试结果来提供   有关包含几何体的SCNNode对象的信息   几何体表面上交点的位置。

那我们怎么做呢?

让我们假设您已创建了名为SCNNodes:

var cubeOne = SCNNode()
var cubeTwo = SCNNode()

这些都分配了6个不同的SCNMaterials(每个面一个),如下所示:

override func viewDidLoad() {
    super.viewDidLoad()

    cubeOne.geometry = cubeGeometry()
    cubeOne.position = SCNVector3(0, -0.5, -1.5)
    cubeOne.name = "Cube One"

    cubeTwo.geometry = cubeGeometry2()
    cubeTwo.position = SCNVector3(30, 0, -1.5)
    cubeTwo.name = "Cube Two"

    self.augmentedRealityView.scene.rootNode.addChildNode(cubeOne)
    self.augmentedRealityView.scene.rootNode.addChildNode(cubeTwo)

}

/// Returns The 6 Faces Of An SCNBox
///
/// - Returns: SCNGeometry
func cubeGeometry() -> SCNGeometry{

    var colours: [UIColor] = [.red, .green, .cyan, .yellow, .purple, .blue]
    var faces = [SCNMaterial] ()
    let cubeGeometry = SCNBox(width: 0.2, height: 0.2, length: 0.2, chamferRadius: 0)

    for faceIndex in 0..<5{

        let material = SCNMaterial()
        material.diffuse.contents = colours[faceIndex]
        faces.append(material)

    }

    cubeGeometry.materials = faces

    return cubeGeometry
}

现在您已为面部分配了6种材质,您将拥有6个几何元素,这些元素对应于SCNBox的每一面。

现在这样做可以快速创建一个与面部顺序相对应的枚举:

enum BoxFaces: Int{

    case Front, Right, Back, Left, Top, Botton
}

现在,当我们执行hitTest时,我们可以记录命中的位置,例如:

/// Detects Which Cube Was Detected & Logs The Geometry Index
///
/// - Parameter gesture: UITapGestureRecognizer
@IBAction func cubeTapped(_ gesture: UITapGestureRecognizer){

    //1. Get The Current Touch Location
    let currentTouchLocation = gesture.location(in: self.augmentedRealityView)

    //2. Perform An SCNHitTest
    guard let hitTest = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).first else { return }

    //3. If The Node In Cube One Then Get The Index Of The Touched Material
    if let namedNode = hitTest.node.name{

        if namedNode == "Cube One"{

            //4. Get The Geometry Index
            if let faceIndex = BoxFaces(rawValue:  hitTest.geometryIndex){
                print("User Has Hit \(faceIndex)")

                //5. Position The Second Cube
                positionStickyNode(faceIndex)
            }

        }

    }
}

在第5部分中,您将注意到函数positionStickyNode的调用,该函数将secondCube放置在第1个多维数据集的相应位置:

/// Position The Second Cube Based On The Face Tapped
///
/// - Parameter index: BoxFaces
func positionStickyNode(_ index: BoxFaces){

    let (min, max) = cubeTwo.boundingBox

    let cubeTwoWidth = max.x - min.x
    let cubeTwoHeight = max.y - min.y

    switch index {

    case .Front:
        cubeTwo.simdPosition = float3(cubeOne.position.x, cubeOne.position.y, cubeOne.position.z + cubeTwoWidth)
    case .Right:
        cubeTwo.simdPosition = float3(cubeOne.position.x + cubeTwoWidth, cubeOne.position.y, cubeOne.position.z)
    case .Back:
        cubeTwo.simdPosition = float3(cubeOne.position.x, cubeOne.position.y, cubeOne.position.z - cubeTwoWidth)
    case .Left:
        cubeTwo.simdPosition = float3(cubeOne.position.x - cubeTwoWidth, cubeOne.position.y, cubeOne.position.z)
    case .Top:
        cubeTwo.simdPosition = float3(cubeOne.position.x, cubeOne.position.y + cubeTwoHeight, cubeOne.position.z)
    case .Botton:
        cubeTwo.simdPosition = float3(cubeOne.position.x, cubeOne.position.y - cubeTwoHeight, cubeOne.position.z)
    }

这是一个非常粗略的例子,当你的立方体大小相同时它们会起作用......但是你已经绰绰有余了,现在想出这对于不同尺寸等是如何工作的。

希望它有所帮助...