Ios 在三维世界ARKit中创建UIBezierPath形状

Ios 在三维世界ARKit中创建UIBezierPath形状,ios,swift,geometry,uibezierpath,arkit,Ios,Swift,Geometry,Uibezierpath,Arkit,我正在制作一个应用程序,用户可以通过ARKit在3D空间中定位一些点来创建一些平面形状,但我使用这些点创建UIBezierPath的部分似乎有问题 在我的应用程序中,用户首先通过按下按钮将AR中的虚拟透明墙放置在其设备所在的同一位置: guard let currentFrame = sceneView.session.currentFrame else { return } let imagePlane = SCNPlane(width: sceneV

我正在制作一个应用程序,用户可以通过ARKit在3D空间中定位一些点来创建一些平面形状,但我使用这些点创建UIBezierPath的部分似乎有问题

在我的应用程序中,用户首先通过按下按钮将AR中的虚拟透明墙放置在其设备所在的同一位置:

    guard let currentFrame = sceneView.session.currentFrame else {
        return
    }

    let imagePlane = SCNPlane(width: sceneView.bounds.width, height: sceneView.bounds.height)
    imagePlane.firstMaterial?.diffuse.contents = UIColor.black
    imagePlane.firstMaterial?.lightingModel = .constant

    var windowNode = SCNNode()
    windowNode.geometry = imagePlane
    sceneView.scene.rootNode.addChildNode(windowNode)

    windowNode.simdTransform = currentFrame.camera.transform
    windowNode.opacity = 0.1
然后,用户在墙上放置一些点(一些球体节点),通过按下按钮确定要创建的平面对象的形状。如果用户指向创建的第一个球体节点,我将关闭该形状,创建其节点并将其放置在与墙相同的位置:

    let hitTestResult = sceneView.hitTest(self.view.center, options: nil)

    if let firstHit = hitTestResult.first {
        if firstHit.node == windowNode {
            let x = Double(firstHit.worldCoordinates.x)
            let y = Double(firstHit.worldCoordinates.y)
            let pointCoordinates = CGPoint(x: x , y: y)

            let sphere = SCNSphere(radius: 0.02)
            sphere.firstMaterial?.diffuse.contents = UIColor.white
            sphere.firstMaterial?.lightingModel = .constant

            let sphereNode = SCNNode(geometry: sphere)
            sceneView.scene.rootNode.addChildNode(sphereNode)
            sphereNode.worldPosition = firstHit.worldCoordinates

            if points.isEmpty {
                windowPath.move(to: pointCoordinates)
            } else {
                windowPath.addLine(to: pointCoordinates)
            }

            points.append(sphereNode)

            if undoButton.alpha == 0 {
                undoButton.alpha = 1
            }
        } else if firstHit.node == points.first {
            windowPath.close()
            let windowShape = SCNShape(path: windowPath, extrusionDepth: 0)
            windowShape.firstMaterial?.diffuse.contents = UIColor.white
            windowShape.firstMaterial?.lightingModel = .constant
            let tintedWindow = SCNNode(geometry: windowShape)

            let worldPosition = windowNode.worldPosition

            tintedWindow.worldPosition = worldPosition
            sceneView.scene.rootNode.addChildNode(tintedWindow)

            //removing all the sphere nodes from points and reinitializing the UIBezierPath windowPath
            removeAllPoints()
        }
    }
当我创建第一面看不见的墙和第一个形状时,该代码起作用,但当我创建第二面墙时,当我完成绘制形状时,该形状似乎变形,不在正确的位置,就像根本不在正确的位置一样。所以我想我的UIBezierPath点的坐标遗漏了一些东西,但是什么呢

编辑

好的,在几次测试之后,它似乎取决于AR会话启动时设备的方向。当设备在启动时面向用户将创建的第一面墙时,将创建形状并按预期放置。但是,如果用户启动应用程序时将设备指向一个方向,然后自己旋转90度,放置第一面墙并创建其形状,则形状将变形且不在正确的位置


看来这是一个3D坐标的问题,但我还是没弄明白。

好的,我刚刚发现了问题!我只是用错了向量和坐标。。。我从来都不是数学/几何专业的人哈哈

因此,与其使用:

let x = Double(firstHit.worldCoordinates.x)   
let y = Double(firstHit.worldCoordinates.y)
let worldPosition = windowNode.worldPosition
我现在使用:

let x = Double(firstHit.localCoordinates.x)  
let y = Double(firstHit.localCoordinates.y)
let worldPosition = windowNode.transform
而不是使用:

let x = Double(firstHit.worldCoordinates.x)   
let y = Double(firstHit.worldCoordinates.y)
let worldPosition = windowNode.worldPosition
我现在使用:

let x = Double(firstHit.localCoordinates.x)  
let y = Double(firstHit.localCoordinates.y)
let worldPosition = windowNode.transform
这就是为什么我的形状节点的位置取决于AR会话的初始化,我正在使用世界坐标,现在对我来说似乎很明显