ARKit —几何,材质,节点,手势哦,我的天哪!
本章是我的《 iOS开发者的ARKit》一书的一部分。 立即获取该书,并开始构建出色的增强现实应用程序。
在上一章中,您了解了创建默认ARKit应用程序所涉及的组件。 您还亲眼目睹了一只漂浮在您面前的太空船。 希望您已将其失踪的太空船告知了NASA!
在本章中,您将学习如何创建具有不同几何形状的虚拟对象,使用材质进行装饰,最后将它们作为SceneKit节点对象添加到现实世界中。 您还将学习如何使用手势和命中测试与虚拟对象进行交互。 让我们学习一些毕达哥拉斯定理。
几何:
几何表示与形状相对应的对象的线框。 SceneKit框架开箱即用地支持许多几何,此处显示了其中的一些。
SCNPlane :指定宽度和高度的矩形单边几何
SCNSphere :球形(或球形或球形)几何
SCNBox :六面多面体几何,其面均为矩形,可以选择带有圆角和圆角
SCNPyramid :直角金字塔几何
SCNTube :管的几何形状。 右圆柱体,其中心轴上有一个圆孔
每个类别代表一个特定的几何形状,可以一起使用以创建更复杂的形状。
材料:
默认情况下,几何图形只是线框。 您可以将几何体视为人类的骨骼。 材质就是您用肉装饰骨架的方式。 素材可以是颜色,图像甚至视频。 在阅读本节内容时,请确保您没有靠近食人族,否则他们可能会有错误的主意。
节点:
节点代表可以添加到场景中的对象。 只要未明确隐藏,添加到场景中的任何内容都可以被用户看到。 您可以将节点视为屏幕上的单个元素。 如果您要构建赛车游戏,那么一个节点可以代表一辆汽车。 如果要构建太空飞船游戏,则该节点可以是太空飞船,而一个单独的节点可以代表导弹。 节点也可以是复合节点,这意味着它们可以包含其他节点。 您可以想到一个代表大型卡车的节点,以及一个代表拖车,轮胎,货物等的子节点。
为真实世界添加形状:
首先,我们向增强现实世界添加一些形状。 在Xcode 9中创建一个新的Augmented Reality项目,并将清单1中的代码添加到viewDidLoad函数。
覆盖func viewDidLoad(){
super.viewDidLoad()
//设置视图的委托
sceneView.delegate =自我
//创建一个新场景
让场景= SCNScene()
let box = SCNBox(宽度:0.2,高度:0.2,长度:0.2,倒角半径:0)
让boxNode = SCNNode(geometry:box)
boxNode.position = SCNVector3(0,0,-0.5)
scene.rootNode.addChildNode(boxNode)
//将场景设置为视图
sceneView.scene =场景
}
清单1:在场景中添加一个盒子
我们首先创建一个SCNBox几何体,该几何体表示我们正在构建的立方体形状。 我们指定了盒子的宽度,高度,长度和chamferRadius。 倒角半径表示盒子的拐角半径,我们将其设置为0表示我们不需要拐角半径。
注意 :使用SceneKit时的度量单位为米。 这意味着您将要设置的尺寸和位置将以米为单位进行计算。
接下来,我们创建一个SCNNode对象,该对象使用几何作为参数。 这意味着,当我们将节点添加到场景中时,由于已将框指定为几何体,因此它将像框一样。 我们将z轴的值设置为-0.5米,这表示物体将被放置在离我们较远的位置 。 最后,我们将boxNode作为子级添加到场景的rootNode中。 这使该节点在屏幕上可见。 图1显示了实际显示的框。
图1:向场景添加盒子
惊人而简单的权利!
本章是我的《 iOS开发者的ARKit》一书的一部分。 立即获取书籍,并开始为iOS构建出色的增强现实应用程序
目前,我们的盒子没有使用任何材料,这就是为什么它看起来是白色的原因。 为了改变盒子的外观,我们需要用一种材料装饰它。 清单2显示了使用SCNMaterial类创建材料并将其应用于框的所有侧面的实现。
覆盖func viewDidLoad(){
super.viewDidLoad()
//设置视图的委托
sceneView.delegate =自我
//创建一个新场景
让场景= SCNScene()
let box = SCNBox(宽度:0.2,高度:0.2,长度:0.2,倒角半径:0)
让材质= SCNMaterial()
material.diffuse.contents = UIColor.red
box.materials = [材料]
让boxNode = SCNNode(geometry:box)
boxNode.position = SCNVector3(0,0,-0.5)
scene.rootNode.addChildNode(boxNode)
//将场景设置为视图
sceneView.scene =场景
}
清单2:将材料应用于包装盒
材质对象的漫反射属性控制阴影将如何受到光的影响。
图2:设置几何材质
这很棒! 但是通常在增强现实应用程序中,您希望使虚拟物品看起来更像真实物品,以便它们可以轻松融入现实世界。 红色很棒,但是如果我们可以用真实世界的纹理代替它,那就更好了。
以下代码段显示了如何将图像用作材料而不是颜色。
material.diffuse.contents = UIImage(名称:“ brick.png”)
而不是指定颜色,我们指定的图像将用作盒子的材料。 图3显示了使用图像作为素材的结果。
图3:将图像设置为几何材质
将图像用作纹理时,请确保该纹理与环境完美融合,从而使人幻想它是真实世界的一部分。
添加触摸事件:
在本节中,我们将学习如何向SCNSphere形状添加纹理,并允许用户在触摸球体时循环浏览纹理列表。
与前面讨论的盒子示例类似,我们将从几何开始。 这次,我们将使用SCNSphere类,该类将允许我们使用球体几何来创建虚拟对象。 清单3显示了创建球体节点并将其添加到场景的实现。
设Sphere = SCNSphere(半径0.3)
让sphereNode = SCNNode(geometry:sphere)
sphereNode.position = SCNVector3(0,0,-0.5)
清单3:创建一个球体
我们以米为单位指定球体的半径,然后将其添加到球体节点。 最后,将SphereNode对象添加到场景中。 因为我们没有设置球节点的材质,所以它以白色物体的形式出现。 我们将使用代表我们美丽的星球“地球”的纹理来装饰我们的球体。 清单4显示了如何使用用作材料的图像来装饰球体。
设Sphere = SCNSphere(半径0.3)
让材质= SCNMaterial()
material.diffuse.contents = UIImage(名称:“ earth.jpg”)
sphere.materials = [material]
让sphereNode = SCNNode(geometry:sphere)
sphereNode.position = SCNVector3(0,0,-0.5)
清单4:使用地球材料创建球体几何
继续运行该应用程序,一定会感到惊讶!
图4:设置球体几何的纹理
接下来,我们将为我们的星球添加触摸手势。 这将使我们能够在不同的纹理之间循环并更新球体以反映新的星球。 我们这样做的唯一原因是让我们的邻居开心,以免他们入侵我们美丽的星球。
第一步是为场景视图注册轻击手势。 这可以通过使用清单5所示的UITapGestureRecognizer类来完成。
私人功能寄存器GestureRecognizers(){
让tapGestureRecognizer = UITapGestureRecognizer(目标:自我,行动:#选择器(点击))
self.sceneView.addGestureRecognizer(tapGestureRecognizer)
}
清单5:为场景视图注册轻敲手势
从viewDidLoad函数内部调用registerGestureRecognizer函数,该函数将确保在加载视图时注册手势。 对于每个轻击事件,将调用轻击功能。 利用点击功能,我们将在其中编写代码以检查用户是否点击了虚拟对象。
清单6中的实现显示了如何检测场景视图中的节点是否拦截了用户的触摸。
@objc func点击(识别器:UITapGestureRecognizer){
让sceneView = ogniser.view为! ARSCN查看
让touchLocation = Recognitor.location(in:sceneView)
让hitResults = sceneView.hitTest(touchLocation,选项:[:])
如果!hitResults.isEmpty {
//这表示该节点已被触摸
}
}
清单6:命中测试检测
我们首先获得2D空间中的触摸位置。 这可以通过identifier.location函数来完成,该函数将视图作为参数并返回CGPoint结构作为触摸位置。 接下来,我们使用ARSCNView的类特殊方法hitTest,该方法可以将触摸的位置作为CGPoint,并返回表示沿点线段找到的对象的结果。
接下来,我们需要访问与线段相交的节点。 这很容易,因为SCNHitTestResult实例由称为节点的属性组成,该属性引用相交的节点。 有了节点,我们就可以简单地更改其使用的材料类型并完成吊臂。 清单7显示了tapped函数的更新实现。
@objc func点击(识别器:UITapGestureRecognizer){
让sceneView = ogniser.view为! ARSCN查看
让touchLocation = Recognitor.location(in:sceneView)
让hitResults = sceneView.hitTest(touchLocation,选项:[:])
如果!hitResults.isEmpty {
如果index == self.textures.count {
索引= 0
}
警卫让hitResult = hitResults.first else {
返回
}
让节点= hitResult.node
node.geometry?.firstMaterial?.diffuse.contents = UIImage(名称:textures [index])
指数+ = 1
}
}
清单7:在触摸手势上更改虚拟对象的材质
继续运行该应用程序! 该应用程序将从显示现实世界中美丽的地球开始。 如果触摸行星,您会注意到它将改变材质以反映纹理数组中的下一个行星。 确保您不要触摸金星,因为高温会烫伤您的手。
结论:
在本章中,我们学习了如何使用几何来创建不同的形状。 我们用材料装饰了以几何图形表示的线框,使其更具逼真的感觉。 最后,我们使用手势和命中测试与现实世界中的虚拟对象进行交互。