现在,当检测到卡时,我能够显示不同的SCNPlane.在显示SCNPlanes之后,用户触摸任何平面以显示新的SCNPlane.但是现在触摸工作正常,但新的SCNPlane没有显示.

这是我尝试过的代码:

var cake_1_PlaneNode : SCNNode? = nil

func renderer(_ renderer: SCNSceneRenderer,didAdd node: SCNNode,for anchor: aranchor) {

    guard let imageAnchor = anchor as? ARImageAnchor else { return }

    if let imageName  = imageAnchor.referenceImage.name {            
        print(imageName)

        if imageName == "menu" {

            // Check To See The Detected Size Of Our menu Card (Should By 5cm*3cm)
            let menuCardWidth = imageAnchor.referenceImage.physicalSize.width
            let menuCardHeight =  imageAnchor.referenceImage.physicalSize.height

            print(
                """
                We Have Detected menu Card With Name \(imageName)
                \(imageName)'s Width Is \(menuCardWidth)
                \(imageName)'s Height Is \(menuCardHeight)
                """)

            //raspBerry
            //cake 1

            let cake_1_Plane = SCNPlane(width: 0.045,height: 0.045)
            cake_1_Plane.firstMaterial?.diffuse.contents = UIImage(named: "france")
            cake_1_Plane.cornerRadius = 0.01

            let cake_1_PlaneNode = SCNNode(geometry: cake_1_Plane)
            self.cake_1_PlaneNode = cake_1_PlaneNode
            cake_1_PlaneNode.eulerAngles.x = -.pi/2
            cake_1_PlaneNode.runAction(SCNAction.moveBy(x: 0.15,y: 0,z: -0.125,duration: 0.75))

            node.addChildNode(cake_1_PlaneNode)
            self.sceneView.scene.rootNode.addChildNode(node)                
        }  
   }       

   override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) {

    let touch = touches.first as! UITouch
    if(touch.view == self.sceneView){
        //print("touch working")
        let viewTouchLocation:CGPoint = touch.location(in: sceneView)
        guard let result = sceneView.hitTest(viewTouchLocation,options: nil).first else {
            return
        }

        if let planeNode = cake_1_PlaneNode,cake_1_PlaneNode == result.node{
            print("match")
            cake_1() 
        }
    }
}

func cake_1() {

    let plane = SCNPlane(width: 0.15,height: 0.15)
    plane.firstMaterial?.diffuse.contents = UIColor.black.withAlphaComponent(0.75)

    let planeNodee = SCNNode(geometry: plane)
    planeNodee.eulerAngles.x = -.pi / 2
    planeNodee.runAction(SCNAction.moveBy(x: 0.21,z: 0,duration: 0))

} //cake_1

点击此链接:Detect touch on SCNNode in ARKit.

查看代码,我可以看到几个问题(更不用说变量和方法的命名约定).

首先,您正在创建一个您已声明的全局变量:

var cake_1_PlaneNode : SCNNode? = nil

但是,在yourDelegate回调中为cake_1_PlaneNode使用本地变量和全局变量:

let cake_1_PlaneNode = SCNNode(geometry: cake_1_Plane)
self.cake_1_PlaneNode = cake_1_PlaneNode

这应该只是这样读:

self.cake_1_PlaneNode = SCNNode(geometry: cake_1_Plane)

其次,您将cake_1_PlaneNode添加到ARSCNView的rootNode而不是您检测到的ARImageAnchor,这可能是您不想做的事情,因为当检测到aranchor时:

You can provide visual content for the anchor by attaching geometry
(or other SceneKit features) to this node or by adding child nodes.

因此,这种方法(除非你真的想这样做)是不必要的.

剩下的问题在于你的cake_1函数本身.

首先,您实际上并没有将planeNodee添加到sceneHierachy中.

由于您尚未指定是否应将新初始化的planeNode直接添加到ARSCNView或作为cake_1_planeNode的childNode,因此您的函数应包括以下内容之一:

self.sceneView.scene.rootNode.addChildNode(planeNodee)    
self.cake_1_planeNode.addChildNode(planeNodee)

此外,可能还没有必要旋转您的planeNodee,因为默认情况下SCNPlane是垂直渲染的.

由于您没有规定放置内容的位置,因此可能不需要使用-.pi / 2,因为这可能使其几乎看不见肉眼.

另一个问题也可能导致您在实际添加节点时没有看到您的节点是Z位置.

如果您在同一位置设置2个节点,您可能会遇到一个称为Z-fighting的问题(您可以阅读更多关于here的信息).因此,您可能应该在添加节点时稍微向前移动添加的节点,例如SCNVector3(0,0.001)来解释这一点.

基于所有这些要点,我在下面提供了一个完整的工作和评论示例:

import UIKit
import ARKit

//-------------------------
//MARK: - ARSCNViewDelegate
//-------------------------

extension ViewController: ARSCNViewDelegate {

    func renderer(_ renderer: SCNSceneRenderer,for anchor: aranchor) {

        //1. Check We Have An ARImageAnchor,Then Get It's Reference Image & Name
        guard let imageAnchor = anchor as? ARImageAnchor else { return }

        let detectedTarget = imageAnchor.referenceImage

        guard let detectedTargetName = detectedTarget.name  else { return }

        //2. If We Have Detected Our Virtual Menu Then Add The CakeOnePlane
        if detectedTargetName == "cakeMenu" {

            let cakeOnePlaneGeometry = SCNPlane(width: 0.045,height: 0.045)
            cakeOnePlaneGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
            cakeOnePlaneGeometry.cornerRadius = 0.01

            let cakeOnPlaneNode = SCNNode(geometry: cakeOnePlaneGeometry)
            cakeOnPlaneNode.eulerAngles.x = -.pi/2

            //3. To Allow Us To Easily Keep Track Our Our Currently Added Node We Will Assign It A Unique Name
            cakeOnPlaneNode.name = "StrawBerry Cake"

            node.addChildNode(cakeOnPlaneNode)
            cakeOnPlaneNode.runAction(SCNAction.moveBy(x: 0.15,duration: 0.75))


        }
    }
}

class ViewController: UIViewController {

    @IBOutlet var augmentedRealityView: ARSCNView!
    let augmentedRealitySession = ARSession()
    let configuration = ARWorldTrackingConfiguration()

    //------------------
    //MARK: - Life Cycle
    //------------------

    override func viewDidLoad() {
        super.viewDidLoad()

        setupARSession()
    }


    //-----------------
    //MARK: - ARSession
    //-----------------

    /// Runs The ARSession
    func setupARSession(){

        //1. Load Our Detection Images
        guard let detectionImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources",bundle: nil) else { return }

        //2. Configure & Run Our ARSession
        augmentedRealityView.session = augmentedRealitySession
        augmentedRealityView.delegate = self
        configuration.detectionImages = detectionImages
        augmentedRealitySession.run(configuration,options: [.resetTracking,.removeExistingAnchors])

    }

    //--------------------
    //MARK: - Interaction
    //--------------------

    override func touchesBegan(_ touches: Set<UITouch>,with event: UIEvent?) {

        //1. Get The Current Touch Location & Perform An ARSCNHitTest To Check For Any Hit SCNNode's
        guard let currentTouchLocation = touches.first?.location(in: self.augmentedRealityView),let hitTestNode = self.augmentedRealityView.hitTest(currentTouchLocation,options: nil).first?.node else { return }

        //2. If We Have Hit Our StrawBerry Cake Then We Call Our makeCakeOnNode Function
        if let cakeID = hitTestNode.name,cakeID == "StrawBerry Cake"{

            makeCakeOnNode(hitTestNode)

        }
    }


    /// Adds An SCNPlane To A Detected Cake Target
    ///
    /// - Parameter node: SCNNode
    func makeCakeOnNode(_ node: SCNNode){

        let planeGeometry = SCNPlane(width: 0.15,height: 0.15)
        planeGeometry.firstMaterial?.diffuse.contents = UIColor.black.withAlphaComponent(0.75)

        let planeNode = SCNNode(geometry: planeGeometry)
        planeNode.position = SCNVector3(0,0.001)
        planeNode.runAction(SCNAction.moveBy(x: 0.21,duration: 0))
        node.addChildNode(planeNode)

    }
}

这在我的设备上产生以下内容:

对于您的信息,这似乎表明您放置内容的计算是关闭的(除非当然这是期望的结果).

正如您所看到的,所有内容都正确呈现,但是这些内容的间距非常大,因此您可能需要稍微平移设备,以便在进一步测试和开发时看到它们.

希望能帮助到你…

swift – 如何使用ARKit检测触摸并显示新的SCNPlane?的更多相关文章

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. js中‘!.’是什么意思

  3. InnoDB 和 MyISAM 引擎恢复数据库,使用 .frm、.ibd文件恢复数据库

  4. Error: Cannot find module ‘node:util‘问题解决

    控制台 安装 Vue-Cli 最后一步出现 Error: Cannot find module 'node:util' 问题解决方案1.问题C:\Windows\System32>cnpm install -g @vue/cli@4.0.3internal/modules/cjs/loader.js:638 throw err; &nbs

  5. yarn的安装和使用(全网最详细)

    一、yarn的简介:Yarn是facebook发布的一款取代npm的包管理工具。二、yarn的特点:速度超快。Yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快。超级安全。在执行代码之前,Yarn 会通过算法校验每个安装包的完整性。超级可靠。使用详细、简洁的锁文件格式和明确的安装算法,Yarn 能够保证在不同系统上无差异的工作。三、y

  6. 前端环境 本机可切换node多版本 问题源头是node使用的高版本

    前言投降投降 重头再来 重装环境 也就分分钟的事 偏要折腾 这下好了1天了 还没折腾出来问题的源头是node 使用的高版本 方案那就用 本机可切换多版本最终问题是因为nodejs的版本太高,导致的node-sass不兼容问题,我的node是v16.14.0的版本,项目中用了"node-sass": "^4.7.2"版本,无法匹配当前的node版本根据文章的提

  7. 宝塔Linux的FTP连接不上的解决方法

    宝塔Linux的FTP连接不上的解决方法常见的几个可能,建议先排查。1.注意内网IP和外网IP2.检查ftp服务是否启动 (面板首页即可看到)3.检查防火墙20端口 ftp 21端口及被动端口39000 - 40000是否放行 (如是腾讯云/阿里云等还需检查安全组)4.是否主动/被动模式都不能连接5.新建一个用户看是否能连接6.修改ftp配置文件 将ForcePassiveIP前面的#去掉 将19

  8. 扩展element-ui el-upload组件,实现复制粘贴上传图片文件,带图片预览功能

  9. 微信小程序canvas实现水平、垂直居中效果

    这篇文章主要介绍了小程序中canvas实现水平、垂直居中效果,本文图文实例代码相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

  10. 使用HTML5做的导航条详细步骤

    这篇文章主要介绍了用HTML5做的导航条详细步骤,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部