如何使用平移手势在场景中旋转物体 - SceneKit

6

我正在尝试使用Scene Kit创建一个解决魔方的应用程序。我有自己的魔方dae文件。 这是我的viewDidLoad中的设置代码

    let myscene = SCNScene(named: "Rubik1.scnassets/Rubiks_Cube.dae")
    scene.rootNode.addChildNode((myscene?.rootNode)!)

    // retrieve the SCNView
    let scnView = self.view as! SCNView

    // set the scene to the view
    scnView.scene = scene

    geometryNode = (scnView.scene?.rootNode.childNodeWithName("Cube",recursively: true))!

    let panRecognizer = UIPanGestureRecognizer(target: self, action: "panGesture:")
    scnView.addGestureRecognizer(panRecognizer)

在识别到手势旋转立方体时

func panGesture(gestureRecognize: UIPanGestureRecognizer){

    let translation = gestureRecognize.translationInView(gestureRecognize.view!)

    let x = Float(translation.x)
    let y = Float(-translation.y)

    let anglePan = sqrt(pow(x,2)+pow(y,2))*(Float)(M_PI)/180.0

    var rotationVector = SCNVector4()
    rotationVector.x = -y
    rotationVector.y = x
    rotationVector.z = 0
    rotationVector.w = anglePan

    geometryNode.rotation = rotationVector

    //geometryNode.transform = SCNMatrix4MakeRotation(anglePan, -y, x, 0)

    if(gestureRecognize.state == UIGestureRecognizerState.Ended) {
        //
    }
}

以上代码不能保留之前的平移手势。我该如何使用“旋转向量”或者

SCNMatrix4MakeRotation(anglePan, -y, x, 0)

旋转立方体
2个回答

7
问题已经解决。
if(gestureRecognize.state == UIGestureRecognizerState.Ended) {

    let currentPivot = geometryNode.pivot
    let changePivot = SCNMatrix4Invert( geometryNode.transform)

    geometryNode.pivot = SCNMatrix4Mult(changePivot, currentPivot)

    geometryNode.transform = SCNMatrix4Identity
}

只有当原始对象的变换位置为(0,0,0)时才有效。 - Yann Bouschet
在应用程序的整个生命周期中,该对象将位于0,0,0处。这解决了我的需求,目前来说已经足够了。 - Nishanth Vemula

7

如果你的物体原始位置不是(0,0,0),那么这个解决方案就可行。

    if(gestureRecognize.state == UIGestureRecognizerState.Ended) {
       let currentPivot = geometryNode.pivot
       let currentPosition = geometryNode.position
       let changePivot = SCNMatrix4Invert(SCNMatrix4MakeRotation(geometryNode.rotation.w, geometryNode.rotation.x, geometryNode.rotation.y, geometryNode.rotation.z))

       geometryNode.pivot = SCNMatrix4Mult(changePivot, currentPivot)
       geometryNode.transform = SCNMatrix4Identity
       geometryNode.position = currentPosition
    }

但是我不明白为什么我们要把transform或rotation的倒数值分配给changePivot。这样做是正确的吗?我们试图将旋转中心旋转到当前的旋转值,并通过将.transform属性设置为单位矩阵将节点重置为旋转中心的值。我们没有看到任何变化,因为此时旋转中心已经具有与节点相同的值。 但是为什么我们要使用倒数值呢?通常您会使用这种方法将某物旋转回其原点。有人能告诉我,我想错了吗?


这个问题已经得到了回答,你的回答没有带来任何新的内容。 - Maciej Jureczko
2
答案仅在原始对象的位置为(0,0,0)时有效。我的答案只是一个加法,即使原始位置例如为(0,0,-1),它也可以正常工作。我试图发表评论,但没有足够的积分... - Emanuel Huser
对象在使用此逻辑时进行了一些平移。旋转效果很好,但是平移是一个问题。可能是因为我的初始变换矩阵不是单位矩阵。平移发生在第一次手势结束时,之后不再发生。有什么想法吗? - Manganese
@Manganese 我期望输入是一次手指滑动操作,而且是瞬间/短暂的滑动。因此,我的意图是在手势结束时旋转并停止,以便用户可以选择旋转另一侧或同一侧。 - Nishanth Vemula

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