简体   繁体   English

旋转后努力使节点沿其轴移动(Swift | ARKit | SceneKit)

[英]Struggling to move node along its axis after rotation (Swift | ARKit | SceneKit)

As the title states, after I rotate my ship node, I would like the "go" button to cause the ship to travel in the direction it is now facing after the rotation. 如标题所示,旋转我的船节点后,我想使用“ go”按钮使船沿旋转后现在面向的方向行驶。 Currently, pressing the "go" button causes the ship to continue moving along the world's z-axis instead of the direction the ship is facing (obviously because I don't have any code in there telling it otherwise). 当前,按下“开始”按钮会使船继续沿世界的z轴而不是船所面对的方向移动(显然是因为我那里没有任何代码可以告诉它)。

I have tried using worldTransform and convertPosition:toNode: with no luck currently. 我已经尝试使用worldTransformconvertPosition:toNode:当前没有运气。

In ViewController: 在ViewController中:

let ship = SpaceShip();
    let SHIP_SPEED: Float = 3.00;
    let scene = SCNScene();


    var timer = Timer();

    var upPressed = false;
    var rightPressed = false;
    var downPressed = false;
    var leftPressed = false;
    var goPressed = false;
    var stopPressed = false;
    var firePressed = false;

    //initial angles for rotating ship
    //if ship is flipping upside down, it is because of these
   /* var xAngle: SCNMatrix4?
    var yAngle: SCNMatrix4?
    var zAngle: SCNMatrix4? */

    @IBOutlet weak var sceneView: ARSCNView!

    @IBAction func upBtnDown(_ sender: Any) {
        upPressed = true;
    }
    @IBAction func upBtnUp(_ sender: Any) {
        upPressed = false;
        ship.rotateShip(ship.getNode(), x: 180, y: 0, z: 180);
    }

    @IBAction func rightBtnDown(_ sender: Any) {
        rightPressed = true;

    }

    @IBAction func rightBtnUp(_ sender: Any) {
        rightPressed = false;
        ship.rotateShip(ship.getNode(), x: 180, y: 0, z: 180);
    }

    @IBAction func downBtnDown(_ sender: Any) {
        downPressed = true;
    }

    @IBAction func downBtnUp(_ sender: Any) {
        downPressed = false;
        ship.rotateShip(ship.getNode(), x: 180, y: 0, z: 180);
    }

    @IBAction func leftBtnDown(_ sender: Any) {
        leftPressed = true;

    }

    @IBAction func leftBtnUp(_ sender: Any) {
        leftPressed = false;
        //ship.rotateShip(ship.getNode(), x: 180, y: 0, z: 180);
    }

    @IBAction func goBtnDown(_ sender: Any) {

        goPressed = true;
    }

    @IBAction func goBtnUp(_ sender: Any) {
        goPressed = false;
    }

    @IBAction func stopBtnDown(_ sender: Any) {
        stopPressed = true;
    }

    @IBAction func stopBtnUp(_ sender: Any) {
        stopPressed = false;
    }


    @IBAction func fireBtnDown(_ sender: Any) {
        firePressed = true;
    }

    @IBAction func fireBtnUp(_ sender: Any) {
        firePressed = false;
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        //set scene from storyboard to scene variable
        sceneView.scene = scene;
        sceneView.scene.physicsWorld.contactDelegate = self;
        sceneView.delegate = self;

    }

    override func viewWillAppear(_ animated: Bool) {

        super.viewWillAppear(animated);

        let configuration = ARWorldTrackingSessionConfiguration();

        sceneView.session.run(configuration);

        addShip();

    }

    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {

        ship.physicsBody?.velocity = SCNVector3(0,0,0);

        if(upPressed == true) {
            ship.physicsBody?.velocity.y = SHIP_SPEED;
            ship.rotateShip(ship.getNode(), x: 170, y: 0, z: 180);
        } else if (rightPressed == true) {
            ship.physicsBody?.velocity.x = SHIP_SPEED;
            ship.rotateShip(ship.getNode(), x: 180, y: 0, z: 170);
        } else if (downPressed == true) {
            ship.physicsBody?.velocity.y = -SHIP_SPEED;
            ship.rotateShip(ship.getNode(), x: 190, y: 0, z: 180);
        } else if (leftPressed == true) {
            //ship.physicsBody?.velocity.x = -SHIP_SPEED;
           ship.rotateShip(ship.getNode(), x: 180, y: 15, z: 190);
            print(ship.getNode().rotation);

        } else if (goPressed == true) {
            ship.physicsBody?.velocity.z = -SHIP_SPEED;
        } else if (stopPressed == true) {
            ship.physicsBody?.velocity.z = SHIP_SPEED;
        }

    }

    func getZForwards(node: SCNNode) -> SCNVector3{
        return SCNVector3(node.worldTransform.m31, node.worldTransform.m32, node.worldTransform.m33);
    }

    func addShip() {
        ship.loadModel();

        ship.position = SCNVector3(0, 0, -2);

        sceneView.scene.rootNode.addChildNode(ship);
    }

    func degToRad(deg: Float) -> Float{
        return deg / 180 * Float(M_PI)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

In SpaceShip(): 在SpaceShip()中:

class SpaceShip: SCNNode {

    var node = SCNNode();

    func loadModel() {
        guard let virtualObjectScene = SCNScene(named: "art.scnassets/ship.scn") else {return};

        let wrapperNode = SCNNode();

        for child in virtualObjectScene.rootNode.childNodes {
            wrapperNode.addChildNode(child);
        }

        node = wrapperNode.childNodes[0];
        let shape = SCNPhysicsShape(node: node, options: nil);
        self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape);
        self.physicsBody?.isAffectedByGravity = false;

        rotateShip(node, x: 180, y: 0, z: 180);

        self.addChildNode(wrapperNode);
    }

    func getNode() -> SCNNode {
        return node;
    }

    func rotateShip(_ node: SCNNode, x: Float, y: Float, z: Float){
        //original angles
        let xAngle = SCNMatrix4MakeRotation(degToRad(deg: x), 1, 0, 0);
        let yAngle = SCNMatrix4MakeRotation(degToRad(deg: y), 0, 1, 0);
        let zAngle = SCNMatrix4MakeRotation(degToRad(deg: z), 0, 0, 1);


        let rotationMatrix = SCNMatrix4Mult(SCNMatrix4Mult(xAngle, yAngle), zAngle);

        node.pivot = SCNMatrix4Mult(rotationMatrix, node.transform);
    }

    func degToRad(deg: Float) -> Float{
        return deg / 180 * Float(M_PI)
    }

}

Thank you 谢谢

transfomPosition does not work because it transforms a position, but you don't want that, you want to transform a direction . transfomPosition不起作用,因为它可以转换位置,但是您不希望那样,您想要转换方向 This also is a SCNVector3 but entirely different, because you only want the rotation applied, not the translation . 这也是一个SCNVector3但完全不同,因为您只想应用旋转 ,而不是平移

Either use transformVector or use worldFront directly, which are new in iOS 11. 使用transformVector或直接使用worldFront ,这是iOS 11中的新增功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM