如何 3d 旋转 arkit 文本 (Swift4)

how to 3d rotate arkit text (Swift4)

我下面的代码获取文本并将 3d 文本放置在参数现实中。问题是我无法旋转文本。我可以在二维方向上移动它。我想移动和旋转文本。我不知道该怎么做。我还没有看到任何关于这个问题的在线教程。目前这是一个 swift 4 问题。

    import UIKit
import SceneKit
import ARKit
class TextNode: SCNNode{
var textGeometry: SCNText!
init(text: String, depth: CGFloat = 1, font: String = "Helvatica", textSize: CGFloat = 3, colour: UIColor) {

    super.init()
    textGeometry = SCNText(string: text , extrusionDepth: depth)
    textGeometry.font = UIFont(name: font, size: textSize)
    textGeometry.flatness = 0
    textGeometry.firstMaterial?.diffuse.contents = colour
    self.geometry = textGeometry
    self.scale = SCNVector3(0.01, 0.01 , 0.01)
}

required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }

}
extension ViewController: UITextFieldDelegate{

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        if let textEntered = textField.text,
            let textRange = Range(range, in: textEntered) {

            let updatedText = textEntered.replacingCharacters(in: textRange, with: string)
            print("User Has Entered \(updatedText)")

            DispatchQueue.main.async {
                self.textNode.textGeometry.string = updatedText
            }
        }

        return true
    }


}


class ViewController: UIViewController {


    /////
var name: String?
@IBOutlet var theBar: UITextField!

@IBOutlet 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?


    /////
var textNode: TextNode!

fileprivate func judo() {
    augmentedRealityView.scene.rootNode.addChildNode(textNode)
    textNode.position = SCNVector3(0, 0, -1.5)
}



override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    augmentedRealityView.session.pause()
}

@IBAction func changeTextColour(){
    let snapShot = self.augmentedRealityView.snapshot()



    UIImageWriteToSavedPhotosAlbum(snapShot, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

@objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    if let error = error {
        print("Error Saving ARKit Scene \(error)")
    } else {
        print("ARKit Scene Successfully Saved")
    }}


    @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 {}
        }
    }

    @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
            }
        }

    }



    override func viewDidLoad() {
        super.viewDidLoad()
        augmentedRealityView.automaticallyUpdatesLighting = true
        theBar.delegate = self as? UITextFieldDelegate
        textNode = TextNode(text: theBar.text!, colour: .white)
        augmentedRealityView.scene.rootNode.addChildNode(textNode)
        textNode.position = SCNVector3(0, 0, -1.5)
           augmentedRealityView.automaticallyUpdatesLighting = true
        //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)
    }

    @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

        }

    }
    func createTextFromPosition(_ position: SCNVector3){

        let textNode = SCNNode()

        //1. Create The Text Geometry With String & Depth Parameters
        let textGeometry = SCNText(string: theBar.text! , 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
    }
    func changeColour(_ value: Int){
        if value == 0{
            textNode.textGeometry.firstMaterial?.diffuse.contents = UIColor.lightGray
        }
    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if let name = UserDefaults.standard.value(forKey: "name") as? String{
            theBar.text = name
        }
        theBar.delegate = self as? UITextFieldDelegate
        if name == String(1) {
            textNode = TextNode(text: theBar.text!, colour: .red)
            augmentedRealityView.scene.rootNode.addChildNode(textNode)
            textNode.position = SCNVector3(0, 0, -1.5)
        }

        let configuration = ARWorldTrackingConfiguration()
        configuration.planeDetection = .horizontal
        augmentedRealityView.session.run(configuration)




    }
}
//////////////////////////////////////

SCNNode 对象有一个旋转 属性 您可以利用。我没看到你在代码中的什么地方设置它。

https://developer.apple.com/documentation/scenekit/scnnode/1408034-rotation

// Sample code: Rotates node to the `heading`
public func nodeRotation(heading: Double) -> SCNVector4 {
    return SCNVector4(0, 1, 0, Double.pi - ((heading * (Double.pi/180)) - Double.pi))
}

textNode.rotation = nodeRotation(heading: 45.0)