SceneKit 相机节点在捏合手势时重置

Posted

技术标签:

【中文标题】SceneKit 相机节点在捏合手势时重置【英文标题】:SceneKit camera node resets on pinch gesture 【发布时间】:2016-07-26 21:00:28 【问题描述】:

我试图在捏合手势上实现缩放,但是每次我第二次捏合时,模型都会自行重置。

func zoom(scale: Double)

    self.cameraNode.camera!.xFov = scale
    self.cameraNode.camera!.yFov = scale



func handlePinch(gestureRecognize: UIPinchGestureRecognizer) 

    if gestureRecognize.numberOfTouches() == 2 

                let zoom = gestureRecognize.scale
                if (gestureRecognize.state == UIGestureRecognizerState.Began)
                    startScale = lastScale
                    bimScene.zoom(startScale)
                
                if (gestureRecognize.state == UIGestureRecognizerState.Changed)
                    startScale = Double(100/zoom)
                    bimScene.zoom(startScale)
                
                if (gestureRecognize.state == UIGestureRecognizerState.Ended)
                    lastScale = startScale
                

    

我还是 Scenekit 的新手,所以我觉得这很奇怪。有人可以解释一下原因吗?

【问题讨论】:

什么是 bimScene 和 SNScene?节点? 【参考方案1】:

你已经接近了,逻辑有点不对。

开始的情况很好,您需要“记住”开始捏合的比例,这可能是您上次缩放时设置的比例。

您更改后的案例有两个问题。

您计算的比例startScale = Double(100/zoom) 仅基于手势识别器比例,此比例仅适用于当前捏合(因此每次捏合都会重置)。这需要基于 GR 比例,以及在紧要关头开始时“记住”的比例。 您还将startScale 在更改后的大小写中重置为您的新值。这给出了“指数”类型的缩放效果;你不想要这个。

结束的案例只需要设置比例值,这样我们就可以记住下一个捏从什么开始。在这种情况下,它可能有点多余,您可能会使用startScale = startScale * zoom 而在开始的情况下什么都没有。

尚未测试以下内容,但希望它能给您一些想法。您传递给zoom 函数的值实际上是一个视野角度,所以我重命名了它以将其与各种比例区分开来。 FOV 将在 30-60 度左右,而比例更倾向于在 0.1 - 10 范围内(非常粗略)。

func handlePinch(gestureRecognize: UIPinchGestureRecognizer) 

    if gestureRecognize.numberOfTouches() == 2 

        let zoom = gestureRecognize.scale
        if (gestureRecognize.state == UIGestureRecognizerState.Began)
            startScale = lastScale
         else if (gestureRecognize.state == UIGestureRecognizerState.Changed)
            let fov = Double(100/(startScale * zoom))
            bimScene.zoom(fov)
         else 
            lastScale = startScale * zoom
        
    

【讨论】:

【参考方案2】:

这是处理特定节点的缩放进出的另一种方法,如果需要在不改变相机视角的情况下实现这一点。

-(void)handlePinch:(UIPinchGestureRecognizer*)gestureRecognizer 
    if (gestureRecognizer.numberOfTouches == 2) 
        CGFloat zoom = gestureRecognizer.scale;
        if (gestureRecognizer.state == UIGestureRecognizerStateBegan) 
            lastScale = yourNode.scale.x;
         else if (gestureRecognizer.state == UIGestureRecognizerStateChanged) 
            double final = lastScale * zoom;
            yourNode.scale = SCNVector3Make(final, final, final);
        
    

【讨论】:

只是想说这是用于基本相机控制的钻石。非常感谢您提供了一个紧凑的、非常简单的块,它直接将手势识别器的放大率与节点的比例因子相关联。例如,我将其应用于我的相机节点,并且能够完美地复制放大/缩小变换。

以上是关于SceneKit 相机节点在捏合手势时重置的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SceneKit 中将 allowCameraControl 与相机节点一起使用

在 Scenekit 中移动相机

平移手势(按住/拖动)缩放相机,如 Snapchat

Scenekit - 将子节点(平面节点)添加到相机前面的父节点(球体节点)

SceneKit:关于定位相机节点的数学问题

在 SceneKit 节点周围添加边框