SceneKitでカメラ操作の中心がずれてしまうのはなぜか?
環境:Mac/High Sierra 10.13.6/swift4.2/xcode 10.0
現在SceneKitを勉強中で、色々試していました。
カメラコントロールをtrueにして、画面表示のアングルや拡大縮小などをできるようにしました。
そこで、1本指でパンした時にアングル回転の中心がずれてしまう事象が発生しました。
調べても今の自分のレベルでは原因がわかりませんでした。
原因と対処法が知りたいです。
1.
現状(x,y,z) = (0,0,0)を中心に回転していると思うのですが、間違いでしょうか?
2.
SCNCameraの回転の中心をずらすことは可能でしょうか?(現状タップしたオブジェクトを原点に持ってくるように全てのオブジェクトを平行移動するという操作を実装しています。本当はカメラの視点をそのオブジェクトに合わせたいです。)
3.
下記のソースコードにおいて、カメラの操作方法の指定をしていますが、
scnView.defaultCameraController.interactionMode = .orbitCenteredArcball
.orbitArcball
.orbitCenterArcball
の違いを明確に知りたいです。
以下がソースコードの一部です。
下記のソースコードでscene.rootNode.addChildNode(obj.bodyNode)としていますが、
実態はgeometoryがSCNSphereのノードです。
import UIKit
import QuartzCore
import SceneKit
class GameViewController: UIViewController {
var objList:[Object]!
var selectedNode:SCNNode!
var cameraNode:SCNNode!
var displayLink:CADisplayLink!
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene()
//カメラ設置
// create and add a camera to the scene
cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .ambient
lightNode.position = SCNVector3(x: 0, y: 0, z: 10)
scene.rootNode.addChildNode(lightNode)
// retrieve the SCNView
let scnView = self.view as! SCNView
// set the scene to the view
scnView.scene = scene
// allows the user to manipulate the camera
scnView.allowsCameraControl = true
scnView.defaultCameraController.interactionMode = .orbitCenteredArcball
scnView.defaultCameraController.inertiaEnabled = true
scnView.defaultCameraController.automaticTarget = true
// configure the view
scnView.backgroundColor = UIColor.black
objList = Util().convinienceInitialCondition()
for obj in objList{
obj.updatePosition()
scene.rootNode.addChildNode(obj.bodyNode)
scene.rootNode.addChildNode(obj.bodyNodeForTap)
if let _ = obj.ringNode{
scene.rootNode.addChildNode(obj.ringNode!)
}
}
//loop設定
// CADisplayLink設定
displayLink = CADisplayLink(target: self, selector: #selector(self.update(_:))) //#selector部分については後述
displayLink.preferredFramesPerSecond = 30 // FPS設定
displayLink.add(to: RunLoop.current, forMode: .common) //forModeについては後述
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.objTap(_:)))
scnView.addGestureRecognizer(tapGesture)
}
let law = LawOfUniversalGravitation(G: 1)
@objc func update(_ displayLink: CADisplayLink) {
law.nextStepByRungeKuttaMethod(objList: objList, dt: 0.0005)
if let node = self.selectedNode{
Util().objectSetOrigin(objects: objList, objectNode: node)
}
//print("camera:x:"+String(self.cameraNode.position.x)+",y:"+String(self.cameraNode.position.y)+",z:"+String(self.cameraNode.position.z))
//print("body1:x:"+String(objList[0].bodyNode.position.x)+",y:"+String(objList[0].bodyNode.position.x)+",z:"+String(objList[0].bodyNode.position.x))
}
@objc
func objTap(_ gestureRecognize: UIGestureRecognizer){
self.displayLink.invalidate()
let scnView = self.view as! SCNView
let p = gestureRecognize.location(in: scnView)
let hitResults = scnView.hitTest(p, options: [:])
if hitResults.count > 0 {
let result = hitResults[0]
self.selectedNode = result.node
}
if let node = self.selectedNode{
Util().objectSetOrigin(objects: objList, objectNode: node)
}
print(self.selectedNode.position)
print(self.cameraNode.position)
displayLink = CADisplayLink(target: self, selector: #selector(self.update(_:)))
displayLink.preferredFramesPerSecond = 30
self.displayLink.add(to: .current, forMode: .common)
}
}