专栏首页iOSDevLogARKit示例 - 第3部分:添加几何和物理乐趣

ARKit示例 - 第3部分:添加几何和物理乐趣

上一篇文章中,我们使用ARKit来检测现实世界中的水平平面,然后将这些平面可视化。在本文中,我们现在将开始为我们的AR体验添加虚拟内容,并开始与检测到的平面进行交互。

到本文结束时,我们将能够将立方体放入世界,将真实物理应用于立方体,以便它们相互作用并产生微型冲击波,使立方体飞得很快。

这是一个显示应用程序运行的视频,您可以看到我们首先如何捕获水平平面,然后我们添加一些3D立方体与场景交互,然后最终导致一些小型爆炸使立方体跳转:

youtube

与往常一样,您可以按照以下代码进行操作:https://github.com/markdaws/arkit-by-example/tree/part3

命中测试

正如您在第一个教程中看到的,我们可以在任何X,Y,Z位置插入虚拟3D内容,它将在现实世界中渲染和跟踪。现在我们有平面检测,我们想要添加与这些平面交互的内容。这将使应用程序看起来像桌子,椅子,地板等顶部有物体。

在这个应用程序中,当用户单击屏幕时,我们执行命中测试,这涉及获取2D屏幕坐标并通过2D屏幕点(在投影平面上具有3D位置)从相机原点发射Ray并进入现场。如果光线与任何平面相交,我们得到命中结果,然后我们获取光线和平面相交的3D坐标,并将我们的内容放置在该3D位置。

这个代码非常简单,ARSCNView包含一个hitTest方法,你传递屏幕坐标,它负责通过相机原点从那个点投射3D光线并返回结果:

- (void)handleTapFrom: (UITapGestureRecognizer *)recognizer {
  // Take the screen space tap coordinates and pass them to the
  // hitTest method on the ARSCNView instance
  CGPoint tapPoint = [recognizer locationInView:self.sceneView];
  NSArray<ARHitTestResult *> *result = [self.sceneView   hitTest:tapPoint types:ARHitTestResultTypeExistingPlaneUsingExtent];
  // If the intersection ray passes through any plane geometry they
  // will be returned, with the planes ordered by distance 
  // from the camera
  if (result.count == 0) {
    return;
  }
  // If there are multiple hits, just pick the closest plane
  ARHitTestResult * hitResult = [result firstObject];
  [self insertGeometry:hitResult];
}

给定ARHitTestResult,我们可以获得光线/平面交叉发生的世界坐标,并在该位置放置一些虚拟内容。对于本文,我们将只插入一个简单的立方体,稍后我们将使对象看起来更逼真:

- (void)insertGeometry:(ARHitTestResult *)hitResult {
float dimension = 0.1;
SCNBox *cube = [SCNBox boxWithWidth:dimension 
                             height:dimension 
                             length:dimension 
                      chamferRadius:0];
SCNNode *node = [SCNNode nodeWithGeometry:cube];
// The physicsBody tells SceneKit this geometry should be
// manipulated by the physics engine
node.physicsBody = [SCNPhysicsBody         
                     bodyWithType:SCNPhysicsBodyTypeDynamic 
                            shape:nil];
node.physicsBody.mass = 2.0;
node.physicsBody.categoryBitMask = CollisionCategoryCube;
// We insert the geometry slightly above the point the user tapped
// so that it drops onto the plane using the physics engine
float insertionYOffset = 0.5;
node.position = SCNVector3Make(
  hitResult.worldTransform.columns[3].x,
  hitResult.worldTransform.columns[3].y + insertionYOffset,
  hitResult.worldTransform.columns[3].z
);
// Add the cube to the scene
[self.sceneView.scene.rootNode addChildNode:node];
// Add the cube to an internal list for book-keeping
[self.boxes addObject:node];
}

添加一些物理

AR假设是为了增强现实世界,所以为了使我们的物体感觉更逼真,我们将添加一些物理来给予一种重量感。

正如您在上面的代码中所看到的,我们为每个立方体提供了一个physicsBody,它指示了SceneKit物理引擎,这个几何应该由物理引擎控制。然后我们还给每个ARKit检测到物理体的平面,以便立方体可以与平面交互(有关更多确切的细节,请参阅github 仓库中的Plane.m类)。

停止飞机检测

一旦我们绘制了世界并拥有多个平面,我们就不希望ARKit继续为我们提供新的平面并可能更新现有的平面,因为这可能会影响我们已经添加到世界的几何体。

在这个应用程序中,如果用户按住两个手指一秒钟,那么我们隐藏所有平面并关闭平面检测。为此,您需要更新ARSession配置的planeDetection属性并重新运行会话。默认情况下,会话将保持相同的坐标系和找到的任何锚点:

// Get our existing session configuration
ARWorldTrackingSessionConfiguration *configuration = (ARWorldTrackingSessionConfiguration *)self.sceneView.session.configuration;
// Turn off future plane detection and updating
configuration.planeDetection = ARPlaneDetectionNone;
// Re-run the session for the changes to take effect
[self.sceneView.session runWithConfiguration:configuration];

下一个

在下一篇文章中,我们将向后退一小步,看看我们已编写的一些代码是否有用,添加了一些用于启用/禁用功能的UI控件。我们还将使用光照和纹理来使插入的几何图形看起来更逼真。

原文:https://blog.markdaws.net/arkit-by-example-part-3-adding-geometry-and-physics-fun-8dd2b90037f2 作者:Mark Dawson

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python机器学习:Scikit-Learn教程

    一个易于理解的scikit-learn教程,可以帮助您开始使用Python机器学习。

    iOSDevLog
  • Ubuntu安装Weblate

    This is the recommended method if you don’t want to concern yourself with furthe...

    iOSDevLog
  • Ubuntu 16.04, Python 2.7 安装 TensorFlow CPUUbuntu 16.04, Python 2.7 安装 TensorFlow CPUInstalling Tenso

    iOSDevLog
  • 如果大数据是任何东西……If Big Data Is Anything at All, This Is It

    除了我们几个人是第一次听说过“大数据”这个词,我们是在信息技术厂商开着的营销活动以宣传自己的产品和服务的背景下听到它的。正是这种营销活动使得“大数据”这个词取得...

    小莹莹
  • 聊聊Spring Data Auditable接口的变化

    spring-data-commons-1.12.8.RELEASE-sources.jar!/org/springframework/data/domain/...

    codecraft
  • Angular应用里的Template Reference变量

    Angular应用里的Template Reference Variable,模板引用变量,用于创建一个对模板里DOM元素或者Angular指令的引用。

    Jerry Wang
  • Tomcat生成的session持久化到MySQL

    The default Tomcat default session storage mechanism uses temporary files. To sa...

    用户3148308
  • Ext JS 4预览:更快、更简单、更稳定

    Ext JS 4预览版:更快、更简单、更稳定 上周在SanFrancisco看,在哪里,我们很激动来自全球的500多Sencha开发者(放到以前应该叫ExtJ...

    用户1183026
  • [教程] 系列报道——PyOpenCL介绍

    OpenCL一直被软件工程师诟病说很难学习,但我觉得这是不公平的。OpenCL API的通用性,导致了它比较繁琐。一旦你写了一些OpenCL代码,你就会意识到很...

    GPUS Lady
  • Spark Streaming性能优化: 如何在生产环境下动态应对流数据峰值

    默认情况下,Spark Streaming通过Receiver以生产者生产数据的速率接收数据,计算过程中会出现batch processing time > b...

    大数据技术与架构

扫码关注云+社区

领取腾讯云代金券