iOS:如何在 SceneKit 中模拟默认相机控件?

6
下面的代码旨在模拟SceneKit中默认相机控件的缩放和旋转功能。
然而,该代码并不像默认控件那样平滑和多用途。
例如,如果您加载这两个模型,则默认缩放对两个模型都能正常工作。但是下面的代码只对模型1有效,并且对模型2进行缩放速度过快。
任何帮助将不胜感激。
模型1:https://poly.google.com/view/6mRHqTCZHxw 模型2:https://poly.google.com/view/cKryD9VnDEZ
    // Create camera
    let camera = SCNCamera()
    camera.automaticallyAdjustsZRange = true
    camera.xFov = 30 
    camera.yFov = 0

    // Compute distance to place camera
    let theta = GLKMathDegreesToRadians(Float(camera.xFov/2))
    let adjacentLength = oppositeLength / Float(tan(theta))

    // Add camera to <cameraNode>
    cameraNode.camera = camera
    cameraNode.position = SCNVector3(x: 0, y: 0, z: adjacentLength)

    // Add <cameraNode> to <orbitNode>
    orbitNode.addChildNode(cameraNode)

    // Add <orbitNode>
    scene.rootNode.addChildNode(orbitNode)

    // Handle pinches
    let pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(didSceneViewPinch))
    pinchRecognizer.delegate = self
    sceneView.addGestureRecognizer(pinchRecognizer)

    // Handle pans
    let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didSceneViewPanOneFinger))
    panRecognizer.minimumNumberOfTouches = 1
    panRecognizer.maximumNumberOfTouches = 1
    panRecognizer.delegate = self
    sceneView.addGestureRecognizer(panRecognizer)

func rotate(recognizer: UIPanGestureRecognizer) {
    // Set throttle value to slow down rotation
    let throttleFactor = Float(40)

    // Compute rotation
    let translation = recognizer.translation(in: recognizer.view!)
    let xRadians = GLKMathDegreesToRadians(Float(translation.x)) / throttleFactor
    let yRadians = GLKMathDegreesToRadians(Float(translation.y)) / throttleFactor

    // Orbit camera via <orbitNode>
    orbitNode.eulerAngles.x -= yRadians
    orbitNode.eulerAngles.y -= xRadians
}


func zoom(recognizer: UIPinchGestureRecognizer) {
    // Set zoom properties
    let minVelocity = CGFloat(0.10)
    let zoomDelta = 0.5

    // Only zoom when gesture changing and when velocity exceeds <minVelocity>
    if recognizer.state == .changed {
        // Ignore gesture on tiny movements
        if abs(recognizer.velocity) <= minVelocity {
            return
        }

        // If here, zoom in or out based on velocity
        let deltaFov = recognizer.velocity > 0 ? -zoomDelta : zoomDelta
        var newFov = cameraNode.camera!.xFov + deltaFov

        // Make sure FOV remains within min and max values
        if newFov <= minXFov {
            newFov = minXFov
        } else if newFov >= maxXFov {
            newFov = maxXFov
        }

        // Update FOV?
        if cameraNode.camera?.xFov != newFov {
            cameraNode.camera?.xFov = newFov
        }
    }
}

抱歉打扰你了,@mnuages。你能帮忙吗?或者知道谁可以帮忙吗? - Confused
这一行代码:var newFov = cameraNode.camera!.xFov + deltaFov 可能需要修改为非线性的形式。您希望小的fov更新速度比大的fov慢。也许可以尝试使用一个因子,例如 var newFov = cameraNode.camera!.xFov * (1 + deltaFov),并使用较小的缩放增量。 - Toyos
1
@Toyos,是的,经过更多测试后我们意识到了这一点,感谢您的建议! :) 有什么关于使旋转更平滑的建议吗?你们最终在手势结束状态使用动画吗?请向蒂姆·库克请求为你们的团队雇佣更多人! :) - Crashalot
他们让Chris Lattner以一个普通的苹果员工的身份存在,没有给予他像一位伟大程序员那样的股票期权和声望,也没有给予他足够吸引他保持对苹果及其方向感兴趣和热情的授权和决策权。这是由Tim Cook监督的。整个科技界都未能认可特殊人才,或者说未能认识到特殊人才需要得到授权才能成为特殊人才的必要性。@Toyos和SCNKit团队是另一个特殊人才被剥夺授权、资金不足并受制于无知管理的例子。BWWIK - Confused
苹果可以通过Scene Kit实现这一点,他们可以向制作SceneKit的团队提供一些支持,并花费一两年时间将其变得更加出色,大幅改进它,教授它并赋予用户权力,然后开源它。他们已经成功地在Swift上做到了这一点... - Confused
显示剩余2条评论
1个回答

2

我尝试按照默认相机控制器的方式重新创建SCNCamera旋转。但是与默认相机相比,它不够流畅。所以我添加了一个带有两个最小触摸的平移手势,并将函数保留为空,什么也不做。这仅利用了默认相机旋转属性,避免了默认相机以下两个属性的使用,如https://developer.apple.com/documentation/scenekit/scnview/1523171-allowscameracontrol所述:

1. 用两个手指在本地xy平面上平移相机 2. 用三个手指在垂直方向上平移相机,前后移动

//Pan Gesture
let gesture = UIPanGestureRecognizer(target: self, action: #selector(panDetected(sender:)))
gesture.maximumNumberOfTouches = 3
gesture.minimumNumberOfTouches = 2
self.sceneView.addGestureRecognizer(gesture);

//Doing nothing in pan gesture other than  printing
@objc func panDetected (sender: UIPanGestureRecognizer) {
    print("two pan detected")
}

接下来,将捏合手势添加到场景视图中,以便可以控制最小和最大缩放级别。


//pinch gesture
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(pinched(sender:)))
    

self.sceneView.addGestureRecognizer(pinchGesture);
@objc func pinched(sender:UIPinchGestureRecognizer){
    let pinchVelocity = Double.init(sender.velocity)
    //print("PinchVelocity \(pinchVelocity)")

    self.sceneView.pointOfView?.camera!.orthographicScale -= (pinchVelocity/pinchAttenuation)

    if (self.sceneView.pointOfView?.camera!.orthographicScale)! <= 0.5 {
        self.sceneView.pointOfView!.camera!.orthographicScale = 0.5
    }

    if self.sceneView.pointOfView!.camera!.orthographicScale >= 1 {
        self.sceneView.pointOfView?.camera!.orthographicScale = 1
    }
}

如果您想禁用或修改默认的相机旋转(使用两个手指旋转相机以在相机节点的z轴上旋转),请添加UIRotationGestureRecognizer。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接