前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ARKit示例 - 第3部分:添加几何和物理乐趣

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

作者头像
iOSDevLog
发布2018-09-19 13:52:16
9560
发布2018-09-19 13:52:16
举报
文章被收录于专栏:iOSDevLogiOSDevLog

上一篇文章中,我们使用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光线并返回结果:

代码语言:javascript
复制
- (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,我们可以获得光线/平面交叉发生的世界坐标,并在该位置放置一些虚拟内容。对于本文,我们将只插入一个简单的立方体,稍后我们将使对象看起来更逼真:

代码语言:javascript
复制
- (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属性并重新运行会话。默认情况下,会话将保持相同的坐标系和找到的任何锚点:

代码语言:javascript
复制
// 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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.08.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 命中测试
  • 添加一些物理
  • 停止飞机检测
  • 下一个
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档