Борьба за перемещение узла вдоль его оси после вращения (Swift | ARKit | SceneKit) - ios


1

Как указано в заголовке, после того, как я вращаю свой узел корабля, я хотел бы, чтобы кнопка "go" заставила корабль двигаться в том направлении, в котором оно теперь обращено после вращения. В настоящее время нажатие кнопки "идти" приводит к тому, что корабль продолжает двигаться по оси z мира, а не в направлении, с которым сталкивается корабль (очевидно, потому, что у меня нет никакого кода, говорящего иначе).

Я пробовал использовать worldTransform и convertPosition:toNode: без везения в настоящее время.

В 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.
    }


}

В 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)
    }

}

Спасибо

Источник
  •  23
  •  1
  • 9 мар 2020 2020-03-09 08:47:18

1 ответ

0

transfomPosition не работает, потому что он преобразует позицию, но вы этого не хотите, вы хотите преобразовать направление. Это также SCNVector3 но совершенно другое, потому что вам нужно только применить поворот, а не перевод.

Либо используйте transformVector либо используйте worldFront напрямую, которые являются новыми в iOS 11.