热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何以编程方式移动ARAnchor?

如何解决《如何以编程方式移动ARAnchor?》经验,为你挑选了1个好方法。

我正在尝试新的ARKit来取代我的另一个类似的解决方案.真是太棒了!但我似乎无法弄清楚如何以编程方式移动ARAnchor.我想慢慢将锚点移动到用户的左侧.

将锚点创建在用户面前2米处:

        var translation = matrix_identity_float4x4
        translation.columns.3.z = -2.0
        let transform = simd_mul(currentFrame.camera.transform, translation)

        let anchor = ARAnchor(transform: transform)
        sceneView.session.add(anchor: anchor)

之后,将对象移动到用户的左/右(x轴)...

anchor.transform.columns.3.x = anchor.transform.columns.3.x + 0.1

每50毫秒(或其他)重复一次.

上述方法不起作用,因为transform是一个get-only属性.

我需要一种方法来改变空间中AR对象相对于用户的位置,以保持AR体验不变 - 这意味着,如果移动设备,AR对象将会移动但也不会被卡住"就像它只是画上相机一样,但移动就像你在走路时会看到一个人移动 - 它们正在移动,你正在移动它看起来很自然.

请注意,此问题的范围仅涉及如何在空间中移动与用户相关的对象(ARAnchor),而不是与平面(ARPlaneAnchor)或另一个检测到的表面(ARHitTestResult)相关.

谢谢!



1> rickster..:

您不需要移动锚点.(手波)这不是你要找的API ......

ARAnchor对象添加到会话实际上是"标记"真实世界空间中的一个点,以便您以后可以参考它.点(1,1,1)(例如)总是重点(1,1,1)- 你不能把它移到其他地方,因为那时它不再是重点(1,1,1)了.

进行2D类比:锚点是参考点,类似于视图的边界.系统(或代码的另一部分)告诉视图它的边界在哪里,并且视图相对于这些边界绘制其内容.AR中的锚点为您提供了可用于在3D中绘制内容的参考点.

你要问的是关于在两点之间移动(和动画化)虚拟内容的动作.而ARKit本身并不是关于显示或动画虚拟内容 - 那里有很多很棒的图形引擎,所以ARKit不需要重新发明那个轮子.ARKit所做的是为您提供真实的参考框架,您可以使用SceneKit或SpriteKit(或Unity或Unreal,或使用Metal或GL构建的自定义引擎)等现有图形技术来显示或动画内容.


既然你提到过用SpriteKit做这个...小心,它会变得混乱.SpriteKit是一个2D引擎,虽然ARSKView它提供了一些方法来制作第三维,但这些方法都有其局限性.

ARSKView自动更新xScale,yScale以及zRotation与相关联的每个精灵的ARAnchor,提供3D立体的错觉.但这仅适用于附加到锚点的节点,如上所述,锚点是静态的.

但是,您可以将其他节点添加到场景中,并使用这些相同的属性使这些节点与ARSKView受管节点匹配.这里有一些代码可以在ARKit/SpriteKit Xcode模板项目中添加/替换.我们将从一些基本逻辑开始,在第三次点击时运行一个弹跳动画(在使用前两个点击来放置锚点之后).

var anchors: [ARAnchor] = []
override func touchesBegan(_ touches: Set, with event: UIEvent?) {

    // Start bouncing on touch after placing 2 anchors (don't allow more)
    if anchors.count > 1 {
        startBouncing(time: 1)
        return
    }
    // Create anchor using the camera's current position
    guard let sceneView = self.view as? ARSKView else { return }
    if let currentFrame = sceneView.session.currentFrame {

        // Create a transform with a translation of 30 cm in front of the camera
        var translation = matrix_identity_float4x4
        translation.columns.3.z = -0.3
        let transform = simd_mul(currentFrame.camera.transform, translation)

        // Add a new anchor to the session
        let anchor = ARAnchor(transform: transform)
        sceneView.session.add(anchor: anchor)
        anchors.append(anchor)
    }
}

然后,一些SpriteKit可以让这个动画发生:

var ballNode: SKLabelNode = {
    let labelNode  = SKLabelNode(text: "")
    labelNode.horizOntalAlignmentMode= .center
    labelNode.verticalAlignmentMode = .center
    return labelNode
}()
func startBouncing(time: TimeInterval) {
    guard
        let sceneView = self.view as? ARSKView,
        let first = anchors.first, let start = sceneView.node(for: first),
        let last = anchors.last, let end = sceneView.node(for: last)
        else { return }

    if ballNode.parent == nil {
        addChild(ballNode)
    }
    ballNode.setScale(start.xScale)
    ballNode.zRotation = start.zRotation
    ballNode.position = start.position

    let scale = SKAction.scale(to: end.xScale, duration: time)
    let rotate = SKAction.rotate(toAngle: end.zRotation, duration: time)
    let move = SKAction.move(to: end.position, duration: time)

    let scaleBack = SKAction.scale(to: start.xScale, duration: time)
    let rotateBack = SKAction.rotate(toAngle: start.zRotation, duration: time)
    let moveBack = SKAction.move(to: start.position, duration: time)

    let action = SKAction.repeatForever(.sequence([
        .group([scale, rotate, move]),
        .group([scaleBack, rotateBack, moveBack])
        ]))
    ballNode.removeAllActions()
    ballNode.run(action)
}

这是一个视频,因此您可以看到此代码的实际效果.你会注意到,只要你不移动相机,幻觉就会起作用 - 对AR来说不是那么好.使用时SKAction,我们无法在动画时调整动画的开始/结束状态,因此球会在其原始(屏幕空间)位置/旋转/比例之间来回反复弹跳.

你可以通过直接制作动画来做得更好,但这需要做很多工作.您需要在每个帧(或每个view(_:didUpdate:for:)委托回调)上:

    在动画的每一端保存基于锚点的节点的更新位置,旋转和缩放值.每次didUpdate回调都需要执行两次,因为每个节点都会有一个回调.

    通过基于当前时间在两个端点值之间进行插值,计算出要设置动画的节点的位置,旋转和缩放值.

    在节点上设置新属性.(或者可能会在很短的时间内将它设置为那些属性,因此它在一帧中不会跳得太多?)

将伪造的3D幻觉装入2D图形工具包中需要付出很多努力 - 因此我对SpriteKit的评论并不是进入ARKit的第一步.


如果您想要AR叠加的3D定位和动画,那么使用3D图形工具包会容易得多.这是前一个示例的重复,但改为使用SceneKit.从ARKit/SceneKit Xcode模板开始,取出宇宙飞船,并将touchesBegan上面的相同功能粘贴到ViewController.(也将as ARSKView演员表更改为as ARSCNView.)

然后,一些用于放置2D广告牌精灵的快速代码,通过SceneKit匹配ARKit/SpriteKit模板的行为:

// in global scope
func makeBillboardNode(image: UIImage) -> SCNNode {
    let plane = SCNPlane(width: 0.1, height: 0.1)
    plane.firstMaterial!.diffuse.cOntents= image
    let node = SCNNode(geometry: plane)
    node.cOnstraints= [SCNBillboardConstraint()]
    return node
}

// inside ViewController
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    // emoji to image based on /sf/ask/17360801/
    let billboard = makeBillboardNode(image: "??".image())
    node.addChildNode(billboard)
}

最后,添加弹跳球的动画:

let ballNode = makeBillboardNode(image: "".image())
func startBouncing(time: TimeInterval) {
    guard
        let sceneView = self.view as? ARSCNView,
        let first = anchors.first, let start = sceneView.node(for: first),
        let last = anchors.last, let end = sceneView.node(for: last)
        else { return }

    if ballNode.parent == nil {
        sceneView.scene.rootNode.addChildNode(ballNode)
    }

    let animation = CABasicAnimation(keyPath: #keyPath(SCNNode.transform))
    animation.fromValue = start.transform
    animation.toValue = end.transform
    animation.duration = time
    animation.autoreverses = true
    animation.repeatCount = .infinity
    ballNode.removeAllAnimations()
    ballNode.addAnimation(animation, forKey: nil)
}

这次动画代码比SpriteKit版本短很多. 这是它在行动中的表现.

因为我们开始使用3D,我们实际上是在两个3D位置之间制作动画 - 与SpriteKit版本不同,动画保持原样.(并且没有额外的工作来直接插值和动画属性.)


推荐阅读
  • Asp.net Mvc Framework 七 (Filter及其执行顺序) 的应用示例
    本文介绍了在Asp.net Mvc中应用Filter功能进行登录判断、用户权限控制、输出缓存、防盗链、防蜘蛛、本地化设置等操作的示例,并解释了Filter的执行顺序。通过示例代码,详细说明了如何使用Filter来实现这些功能。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • 指示|厂家_UDS协议
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了UDS协议相关的知识,希望对你有一定的参考价值。UDS的第二类诊断服务,数据传输 ... [详细]
  • Introduction(简介)Forbeingapowerfulobject-orientedprogramminglanguage,Cisuseda ... [详细]
  • 本博文基于《Amalgamationofproteinsequence,structureandtextualinformationforimprovingprote ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • JSP内置对象之application的作用范围和获取方式
    本文介绍了JSP内置对象之application的作用时间范围、可以在不同浏览器获取的特点,以及获取application对象的方法。通过示例代码展示了在JSP中设置和在servlet中获取application对象的步骤。对于学习JSP内置对象的读者来说,本文具有一定的参考价值。摘要长度为163字。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 如何在php文件中添加图片?
    本文详细解答了如何在php文件中添加图片的问题,包括插入图片的代码、使用PHPword在载入模板中插入图片的方法,以及使用gd库生成不同类型的图像文件的示例。同时还介绍了如何生成一个正方形文件的步骤。希望对大家有所帮助。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • 本文介绍了如何使用n3-charts绘制以日期为x轴的数据,并提供了相应的代码示例。通过设置x轴的类型为日期,可以实现对日期数据的正确显示和处理。同时,还介绍了如何设置y轴的类型和其他相关参数。通过本文的学习,读者可以掌握使用n3-charts绘制日期数据的方法。 ... [详细]
  • 我创建了一个新的AWSSSO(使用内部IDP作为身份源,因此不使用ActiveDirectory)。我能够登录AWSCLI、AWSGUI,但 ... [详细]
author-avatar
shurui26jx_882
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有