【问题标题】:SceneKit. Place nodes in one "surface"场景套件。将节点放置在一个“表面”中
【发布时间】:2021-07-12 00:31:59
【问题描述】:

用户在绘图视图上画一条线,然后我需要将这些点转换为 3d 世界,但将这些点放在一个“表面”中。为此,我将点数组映射为向量(我将 hitTest 与 .featurePoint 一起使用),然后过滤该数组以获取下一个

func didEndDrawing(with points: [CGPoint]) {

    guard let transform = sceneView.pointOfView?.transform else { return }
    let cameraVectror = SCNVector3(transform.m31, transform.m32, transform.m33)

    let farthestVector = points
        .reduce((vector: SCNVector3(0, 0, 0), distance: CGFloat.zero)) { result, point in
                    
        guard let vector = getVector(for: point) else { return result }
        let distance: CGFloat = cameraVectror.distance(to: vector)
        return  distance > result.distance ? (vector, distance) : result
    }
        .vector
}
let parentNode = SCNNode()
parentNode.position = farthestVector

如何调整坐标(我猜是 z 位置)以使所有子节点与视点的距离相同? 该应用的理念是在 AR 中进行手绘。

更新

在 Voltan 的帮助下,我能够解决它


points.forEach { point in
    let scenePoint = sceneView.unprojectPoint(SCNVector3(point.x, point.y, CGFloat(projectedPoint.z)))
    let sphere = SCNSphere(radius: 0.01)
    let material = SCNMaterial()
    material.diffuse.contents = UIColor.green
    sphere.materials = [material]
    let node = SCNNode(geometry: sphere)
    node.position = scenePoint
    sceneView.scene.rootNode.addChildNode(node)
}

【问题讨论】:

    标签: ios swift augmented-reality scenekit arkit


    【解决方案1】:

    如果我的理解正确,您需要某种点击/拖动组合 - 从 2D 世界中获取点并转换为 3D 世界。这是导弹命令类型游戏的一些游戏代码,也许它会帮助你处理 unprojectPoint 的东西。有一些计时器没有包括在内,但希望你能明白。

    @objc func handleTap(recognizer: UITapGestureRecognizer)
        {
            if(data.gameState == .endGame)
            {
                endGameAnimates.stop()
                let _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: false, block: { _ in self.dismiss(animated: false, completion: nil) })
                
                return
            }
            
            if(gameControl.isWaveComplete == true || gNodes.gameNodes.isPaused == true) { return }
            
            currentLocation = recognizer.location(in: gameScene)
            let projectedPoint = gameScene.projectPoint(SCNVector3(0, 0, 0))
            let scenePoint = gameScene.unprojectPoint(SCNVector3(currentLocation.x, currentLocation.y, CGFloat(projectedPoint.z)))
            
            if(data.gameState == .endGame) // Allow animations to finish, otherwise they will show up next round
            {
                DispatchQueue.main.async { self.endGameAnimates.stop() }
                let _ = Timer.scheduledTimer(withTimeInterval: 1, repeats: false, block: { _ in self.dismiss(animated: false, completion: nil) })
                return
            }
            
            if(data.missilesAvailable <= 0)
            {
                sound.playSoundType(vSoundType: .defenseFails)
                hudControl.notify()
            }
            else
            {
                gameControl.defenseMissileShoot(vPosition: scenePoint, soundType: 0)
                sound.playSoundType(vSoundType: .defenseFires)
            }
        }
        //**************************************************************************
        @objc func handlePan(recognizer: UIPanGestureRecognizer)
        {
            currentLocation = recognizer.location(in: gameScene)
            let projectedPoint = gameScene.projectPoint(SCNVector3(0, 0, 0))
            let scenePoint = gameScene.unprojectPoint(SCNVector3(currentLocation.x, currentLocation.y, CGFloat(projectedPoint.z)))
            
            if(gameControl.isWaveComplete == true || gNodes.gameNodes.isPaused == true) { return }
            
            switch recognizer.state
            {
            case UIGestureRecognizer.State.began:
                gameControl.defenseMissileShoot(vPosition: scenePoint, soundType: 1)
                SNDdefenseSoundCount = 0
                if(data.missilesAvailable <= 0) { sound.playSoundType(vSoundType: .defenseFails); hudControl.notify() }
                beginLocation.x = currentLocation.x
                break
            case UIGestureRecognizer.State.changed:
                if(currentLocation.x > beginLocation.x + dragDistance) 
                {
                    beginLocation.x = currentLocation.x
                    if(data.missilesAvailable > 0) { gameControl.defenseMissileShoot(vPosition: scenePoint, soundType: 2) }
                    SNDdefenseSoundCount += 1
                }
                if(currentLocation.x < beginLocation.x - dragDistance)
                {
                    beginLocation.x = currentLocation.x
                    if(data.missilesAvailable > 0) { gameControl.defenseMissileShoot(vPosition: scenePoint, soundType: 2) }
                    SNDdefenseSoundCount += 1
                }
                break
            case UIGestureRecognizer.State.ended:
                if(data.missilesAvailable > 0)
                {
                    if(SNDdefenseSoundCount < 2) { sound.playSoundType(vSoundType: .defenseFires) }
                    else                         { sound.playSoundType(vSoundType: .defensePans)  }
                }
                break
            default:
                break
            }
    

    【讨论】:

    • 太好了,正是我需要的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-31
    • 2018-06-03
    • 1970-01-01
    相关资源
    最近更新 更多