SceneKit 子节点位置在父节点旋转期间未更改 [英] SceneKit Child node position not changed during Parent node rotation

查看:47
本文介绍了SceneKit 子节点位置在父节点旋转期间未更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试重新编码 SceneKit 中的相机管理.为此,我使用 UIPanGestureRecognizer 使相机围绕对象(在本例中围绕场景中心)旋转.

I'm trying to recode the camera management in SceneKit. For that, I use UIPanGestureRecognizer for the rotation of camera around an object (In this case around the centre of scene).

接下来,我得到不同的比率或长度来确定在连接相机的假想球体的轴(X、Y、Z)上添加的角度(代码中的cameraOrbit).

Next I get the different ratio or length to determinate the angle to add at axes (X, Y, Z) of imaginary sphere where camera is attached (cameraOrbit in code).

我的问题是我使用相机的位置来确定添加到球体的角度.但位置是不变的.当我改变球体旋转时,子节点相机的位置永远不会更新.那么角度永远不会改变.

My problem is that I use the position of camera to determinate the angle to add at sphere. But the position is constant. When I change the sphere rotation, the position of child node camera are never updated. Then angle never change.

import SceneKit
import UIKit

class SceneManager
{
    private let scene: SCNScene
    private let view: SCNView
    private let camera: SCNNode
    private let cameraOrbit: SCNNode
    private let cameraRadius: Float

    init(view: SCNView, assetFolder: String, sceneName: String, cameraName: String, backgroundColor: UIColor) {
        self.view = view
        self.scene = SCNScene(named: (assetFolder + "/" + sceneName))!
        if (self.scene.rootNode.childNodeWithName(cameraName, recursively: true) == nil) {
            print("Fatal error: Cannot find camera in scene with name :\"", cameraName, "\"")
            exit(1)
        }
        self.camera = self.scene.rootNode.childNodeWithName(cameraName, recursively: true)! // Retrieve cameraNode created in scene file
        self.cameraOrbit = SCNNode()
        self.cameraOrbit.addChildNode(self.camera)
        self.cameraRadius = sqrt(pow((self.camera.position.x), 2) + pow(self.camera.position.y, 2)) // CameraOrbit radius for rotation camera in panHandler
        self.scene.rootNode.addChildNode(self.cameraOrbit)
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panHandler(_:)))
        panGesture.maximumNumberOfTouches = 1
        self.view.addGestureRecognizer(panGesture)
        self.view.backgroundColor = backgroundColor
        self.view.pointOfView = self.camera
        self.view.scene = self.scene
    }

    @objc private func panHandler(sender: UIPanGestureRecognizer) {
        let alpha = cos(self.camera.position.z / self.cameraRadius) // Get angle of camera

        // --
        print(self.camera.position) // <-------- (X, Y, Z) The axes position are always the same
        // --

        var ratioX = 1 - ((CGFloat)(alpha) / (CGFloat)(M_PI)) // Get the radio with angle for apply to Z and X axes rotation
        var ratioZ = ((CGFloat)(alpha) / (CGFloat)(M_PI))
        // Change direction of rotation depending camera's position in trigonometric circle
        if (self.camera.position.z > 0 && self.camera.position.x < 0) {
            ratioZ *= -1
        } else if (self.camera.position.z < 0 && self.camera.position.x < 0) {
            ratioX *= -1
            ratioZ *= -1
        } else if (self.camera.position.z > 0 && self.camera.position.x > 0) {
            ratioX *= -1
        }
        // Set the angle rotation to add at imaginary sphere (cameraOrbit)
        let xAngleToAdd = (sender.velocityInView(sender.view!).y / 10000) * ratioX
        let yAngleToAdd = (sender.velocityInView(sender.view!).x / 10000) * (-1)
        let zAngleToAdd = (sender.velocityInView(sender.view!).y / 10000) * ratioZ
        let rotation = SCNAction.rotateByX(xAngleToAdd, y: yAngleToAdd, z: zAngleToAdd, duration: 0.5)
        self.cameraOrbit.runAction(rotation)
    }
}

如果有人有想法?谢谢

推荐答案

当你更新父节点的变换(位置、旋转、缩放)时,子节点的变换在局部坐标(相对于父节点)保持不变,它只有世界坐标的变化.

When you update the parent node's transform (position, rotation, scale), the child nodes' transform remains unchanged in local coordinates (relative to the parent), it only changes in world coordinates.

如果要访问给定节点的世界变换,请使用 worldTransform 属性.

If you want to access the world transform for a given node, use the worldTransform property.

这篇关于SceneKit 子节点位置在父节点旋转期间未更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆