2016-07-22 4 views
0

SceneKit에서 카메라 관리 코드를 다시 코딩하려고합니다. 이를 위해 UIPanGestureRecognizer를 사용하여 객체 주위의 카메라 회전을 처리합니다 (이 경우 장면 중앙 부근).SceneKit 상위 노드 회전 중에 하위 노드 위치가 변경되지 않습니다.

다음은 카메라가 부착 된 가상 구의 축 (X, Y, Z)에 추가 할 각도 (코드의 경우 cameraOrbit)를 결정하기 위해 다른 비율 또는 길이를 얻습니다.

내 문제는 필자가 구의 각도를 결정할 때 카메라의 위치를 ​​사용한다는 것입니다. 그러나 그 위치는 일정합니다. 구 회전을 변경하면 하위 노드 카메라의 위치가 절대 업데이트되지 않습니다. 그러면 각도가 변하지 않습니다.

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

누구나 아이디어가 있다면? 감사

+0

"self.rootNode.childNodeWithName'에서"cameranode "를 참조하는 것으로 나타났습니다. 그런 다음'self.camearOrbit.addChildNode (self.cameranode)'를 호출하십시오. 카메라 노드를 cameraOrbit에 추가하기 전에'self.cameranode.removeFromParentNode'라고 부르지 않습니까? –

+0

나는 부모/자식 속성에 대해 작업하고 다시 생각해 보려고합니다. – Ynamy

답변

1

부모 노드의 변환 (위치, 회전, 크기 조절)을 업데이트하면 하위 노드의 변환은 로컬 좌표 (부모를 기준으로 함)에서 변경되지 않고 변경되며 월드 좌표 만 변경됩니다.

주어진 노드에 대해 월드 변환에 액세스하려면 worldTransform 속성을 사용하십시오.

+0

예. 그렇습니다. 그러나 "self.camera.position"으로 위치를 검색 할 때 나는 세계 위치를 얻었습니까? 구의 중심은 0,0,0입니다. 그럼 내가 어떻게 세계의 위치를 ​​잡을 수 있을까? – Ynamy