Swift SCNNode 3D立方体旋转到立方体上的一点

Swift SCNNode 3D cube rotate to a point on cube

问题:尝试将立方体旋转到立方体本身上的一点。该点是随机创建的,它应该出现在屏幕中央。

尝试使用 lookAtConstraint 并在 func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) 中分配了随机点。但是没有用(评论)

 cube = SCNNode(geometry: sphereGeometry)
        cube.position = SCNVector3Make(0.0, 0.0, 0.0)
        gamescn.rootNode.addChildNode(cube)

        cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 40)
        gamescn.rootNode.addChildNode(cameraNode)

        lookAtConstraint

//        lookAtConstraint = SCNLookAtConstraint(target: cube)
//        lookAtConstraint.isGimbalLockEnabled = true
//        cameraNode.constraints = [lookAtConstraint]

还尝试获取偏差第一个中心点(最初是 [0,0,distance from center])——然后是 cube.eulerAngles = deviationfunc renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)。但是立方体随机旋转。

我想出了一个简单的 3D 几何解决方案。可能还有其他优雅的解决方案。 这是我如何实现的 -

制作了两个效用函数来获取两点之间角度的 asin 和 acos 分量 -

func angleBetweenVectorsCos(_ vectorB:SCNVector3) -> SCNFloat {
        let cosineAngle = (dot(vector: vectorB) / (magnitude * vectorB.magnitude))
        return SCNFloat(acos(cosineAngle))
}

func angleBetweenVectorsSin(_ vectorB:SCNVector3) -> SCNFloat {
        let cosineAngle = angleBetweenVectorsCos(vectorB)
        let sinangle = sqrt(1-cosineAngle*cosineAngle)
        return SCNFloat(acos(sinangle))
 }

然后 - 在 func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) 函数中,我指定计算的角度

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        if time > rotationTimer{


            let angleCos = lastposition.angleBetweenVectorsCos(movingTarget.position)
            let angleSin = lastposition.angleBetweenVectorsSin(movingTarget.position)
            SCNTransaction.begin()
            SCNTransaction.animationDuration = 0.5
            xDegree += angleSin
            yDegree += angleCos
            zDegree += 0

            if vMove {
                cube.eulerAngles.x =  xDegree
            }
            if hMove {
                cube.eulerAngles.y =  -yDegree
            }


            SCNTransaction.commit()
            lastposition = movingTarget.position
            .......    
            rotationTimer = time + 0.2
        }

    }

如何获得vMove(垂直运动)和hMove(水平运动) - 只是通过检测到原点的距离来计算移动物体在哪个表面上。

我为此做了一个完整的 github 回购。 See this and suggest some improvements