ios - 如何指向和定位 arkit 文本

标签 ios swift text position arkit

下面的代码只是将文本随机放置在 View 中。我希望用户能够按照他们选择的方式指向并定位文本。 enter image description here

最佳答案

鉴于您还不完全清楚您想要做什么,我将根据我对您问题的解释提供答案,我认为这是在询问用户如何将 SCNNode 与用户指定位置的 SCNTextGeometry,例如(点击的位置),然后对其进行定位或与之交互。

下面的代码是一个非常粗略的示例,它允许用户在 tapLocation 处放置一个带有 SCNTextGeometrySCNNode

然后用户可以使用 UIPinchGestureRecognizer 缩放它或使用 UIRotationGestureRecognizer 旋转它。

您需要在 tapGestureRecognizer 中设置 currentNode,但它应该会为您指明正确的方向。

所有代码都有完整的注释,因此应该非常有意义:

class ViewController: UIViewController {

    //1. Create A Reference To Our ARSCNView In Our Storyboard Which Displays The Camera Feed
    @IBOutlet weak var augmentedRealityView: ARSCNView!

    //2. Create Our ARWorld Tracking Configuration
    let configuration = ARWorldTrackingConfiguration()

    //3. Create Our Session
    let augmentedRealitySession = ARSession()

    //4. Create A Variable To Store The Current Nodes Rotation Around It's Y-Axis
    var currentAngleY: Float = 0.0
    var isRotating = false
    var currentNode: SCNNode?

    //--------------------
    //MARK: View LifeCycle
    //--------------------

    override func viewDidLoad() {
        super.viewDidLoad()

        //1. Run The ARSession
        augmentedRealityView.session = augmentedRealitySession
        augmentedRealitySession.run(configuration, options: [.resetTracking, .removeExistingAnchors])

        //2. Add A UIPinchGestureRecognizer So We Can Scale Our TextNode
        let scaleGesture = UIPinchGestureRecognizer(target: self, action: #selector(scaleCurrentNode(_:)))
        self.view.addGestureRecognizer(scaleGesture)

        //3. Add A Tap Gesture Recogizer So We Can Place Our TextNode
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(placeOrAssignNode(_:)))
        self.view.addGestureRecognizer(tapGesture)

        //4. Add A Rotation Gesture Recogizer So We Can Rotate Our TextNode
        let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotateNode(_:)))
        self.view.addGestureRecognizer(rotateGesture)
    }

    override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }

    //-----------------------
    //MARK: Touch Interaction
    //-----------------------

    /// Performs An ARHitTest Or SCNHitTest So We Can Place Or Assign Our TextNode
    ///
    /// - Parameter gesture: UITapGestureRecognizer
    @objc func placeOrAssignNode(_ gesture: UITapGestureRecognizer){

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

        //2. If We Hit An SCNNode Set It As The Current Node So We Can Interact With It
        if let nodeHitTest = self.augmentedRealityView.hitTest(currentTouchLocation, options: nil).first?.node{

            currentNode = nodeHitTest
            return
        }

        //3. Do An ARHitTest For Features Points So We Can Place An SCNNode
        if let hitTest = self.augmentedRealityView.hitTest(currentTouchLocation, types: .featurePoint).first {

            //4. Get The World Transform
            let hitTestPosition = hitTest.worldTransform.columns.3

            //5. Add The TestNode At The Desired Position
            createTextFromPosition(SCNVector3(hitTestPosition.x, hitTestPosition.y, hitTestPosition.z))
            return

        }

    }

    //-------------------
    //MARK: Node Creation
    //-------------------

    /// Creates An SCNNode With An SCNTextGeometry
    ///
    /// - Parameter position: SCNVector3
    func createTextFromPosition(_ position: SCNVector3){

        let textNode = SCNNode()

        //1. Create The Text Geometry With String & Depth Parameters
        let textGeometry = SCNText(string: "StackOverFlow" , extrusionDepth: 1)

        //2. Set The Font With Our Set Font & Size
        textGeometry.font = UIFont(name: "Helvatica", size: 1)

        //3. Set The Flatness To Zero (This Makes The Text Look Smoother)
        textGeometry.flatness = 0

        //4. Set The Colour Of The Text
        textGeometry.firstMaterial?.diffuse.contents = UIColor.white

        //5. Set The Text's Material
        textNode.geometry = textGeometry

        //6. Set The Pivot At The Center
        let min = textNode.boundingBox.min
        let max = textNode.boundingBox.max

        textNode.pivot = SCNMatrix4MakeTranslation(
            min.x + (max.x - min.x)/2,
            min.y + (max.y - min.y)/2,
            min.z + (max.z - min.z)/2
        )

        //7. Scale The Text So We Can Actually See It!
        textNode.scale = SCNVector3(0.005, 0.005 , 0.005)

        //8. Add It To The Hierachy & Position It
        self.augmentedRealityView.scene.rootNode.addChildNode(textNode)
        textNode.position = position

        //9. Set It As The Current Node
        currentNode = textNode
    }


    //-------------
    //MARK: Scaling
    //-------------

    /// Scales The Currently Selected Node
    ///
    /// - Parameter gesture: UIPinchGestureRecognizer
    @objc func scaleCurrentNode(_ gesture: UIPinchGestureRecognizer) {

        if !isRotating, let selectedNode = currentNode{

            if gesture.state == .changed {

                let pinchScaleX: CGFloat = gesture.scale * CGFloat((selectedNode.scale.x))
                let pinchScaleY: CGFloat = gesture.scale * CGFloat((selectedNode.scale.y))
                let pinchScaleZ: CGFloat = gesture.scale * CGFloat((selectedNode.scale.z))
                selectedNode.scale = SCNVector3Make(Float(pinchScaleX), Float(pinchScaleY), Float(pinchScaleZ))
                gesture.scale = 1

            }

            if gesture.state == .ended {}
        }
    }

    //----------------
    //MARK: Rotation
    //----------------

    /// Rotates The Currently Selected Node Around It's YAxis
    ///
    /// - Parameter gesture: UIRotationGestureRecognizer
    @objc func rotateNode(_ gesture: UIRotationGestureRecognizer){

        if let selectedNode = currentNode{

            //1. Get The Current Rotation From The Gesture
            let rotation = Float(gesture.rotation)

            //2. If The Gesture State Has Changed Set The Nodes EulerAngles.y
            if gesture.state == .changed{
                isRotating = true
                selectedNode.eulerAngles.y = currentAngleY + rotation
            }

            //3. If The Gesture Has Ended Store The Last Angle Of The CurrentNode
            if(gesture.state == .ended) {
                currentAngleY = selectedNode.eulerAngles.y
                isRotating = false
            }
        }

    }
}

希望对你有帮助

关于ios - 如何指向和定位 arkit 文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50591866/

相关文章:

swift - 通过分段控制更改 map 类型(混合、卫星)

ios - 使用 RxSwift 和 Parse-Server 进行轮询

java - Android:我如何在文本字段中实现警告

ios - CAAnimationGroup 的最大持续时间值 (CFTimeInterval) 是多少?

ios - 开发应用程序仅用于应用程序内购买?

ios - EXC_BAD_ACCESS 使用 gmaps sdk 1.9.0,Xcode 6.4,在 8.3 设备上运行

ios - 添加 Google Conversion Tracking SDK iOS-3.0.0 时应用程序崩溃

ios - 如何修复 'Locale' 没有成员 'objectForKey' ?让小数分隔符在我的代码中工作

html - 竖排文字方向

python - 如何在 Tkinter 文本小部件绑定(bind)后在 Tkinter 文本小部件中绑定(bind)自身事件?