美文网首页
ARkit 实战教程(Xcode开发)

ARkit 实战教程(Xcode开发)

作者: 零度_不结冰 | 来源:发表于2017-08-23 17:56 被阅读372次

    ARkit 实战教程(Xcode开发)

    ARKit 最近在开发圈实在是火,ios 开发者可以快速的进行增强现实的开发,简化了许多步骤,之前了,我们AR酱也出了相应的ARKit 系列教程,今天了算是ARKit 的实战教程番外篇,我们实现一些网上比较流行的一些AR功能。

    ps:代码地址:http://www.arparticles.com/portal.php?mod=view&aid=107

    基础:现实模型

    基础效果演示:

    打开Xcode,新建一个AR项目

    这次我们用SceneKit 来渲染3D内容。

    进入项目之后会有个smaple project,我们可以尝试着运行:

    我们使用SceneKit绘制一个3D立方体。SceneKit有几个基本类,SCNScene是所有3D模型的容器。要向场景添加内容,你首先创建几何,几何可以是复杂的形状,或简单的像球体,多维数据集,平面等。然后,将几何模型放在在场景节点中,并将其添加到场景中。然后,SceneKit将遍历场景图并呈现内容。

    - (void)viewDidLoad {

    [super viewDidLoad];

    SCNScene *scene = [SCNScene new];

    SCNBox *boxGeometry = [SCNBox

    boxWithWidth:0.1

    height:0.1

    length:0.1

    chamferRadius:0.0];

    SCNNode *boxNode = [SCNNode nodeWithGeometry:boxGeometry];

    boxNode.position = SCNVector3Make(0, 0, -0.5);

    [scene.rootNode addChildNode: boxNode];

    self.sceneView.scene = scene;

    }

    ARKit和SceneKit的坐标系如下所示:

    当ARSession启动时,计算出的相机位置最初设置为X = 0,Y = 0,Z = 0。

    们可以看到立方体的两面,我们可以稍后添加一些更高级的照明,但现在我们可以在SCNScene实例上设置autoenablesDefaultLighting :

    self.sceneView.autoenablesDefaultLighting = YES;

    进阶:平面检测+可视化

    效果演示:

    在我们开始之前,将一些调试信息添加到程序中,即渲染ARKit检测到的功能点,我们可以打开我们的ARSCNView:

    self.sceneView.debugOptions =

    ARSCNDebugOptionShowWorldOrigin |

    ARSCNDebugOptionShowFeaturePoints;

    我们来检测平面几何,在ARKit中,可以通过设置planeDetection属性来检测水平平面。此值可以设置为ARPlaneDetectionHorizontal或ARPlaneDetectionNone。

    - (void)renderer:(id )renderer

    didAddNode:(SCNNode *)node

    forAnchor:(ARAnchor *)anchor {

    SCNNode实例是ARKit创建的一个SceneKit节点,它具有一些类似于方向和位置的属性,然后我们获得一个锚实例,这将告诉我们使用已找到的特定锚点的更多信息,如大小和中心位置的plane。锚实例实际上是一个ARPlaneAnchor类型,比如我们可以得到plane的范围和中心信息。

    我们进行渲染plane,可以在虚拟世界中绘制一个SceneKit 3D平面。为此,我们创建一个继承自SCNNode的Plane类。在构造方法中,我们创建平面并相应地调整它的大小:

    self.planeGeometry = [SCNPlane planeWithWidth:anchor.extent.x height:anchor.extent.z];

    SCNNode *planeNode = [SCNNode nodeWithGeometry:self.planeGeometry];

    planeNode.position = SCNVector3Make(anchor.center.x, 0, anchor.center.z);

    planeNode.transform = SCNMatrix4MakeRotation(-M_PI / 2.0, 1.0, 0.0, 0.0);

    [self addChildNode:planeNode];

    现在我们有我们的Plane类,回到ARSCNViewDelegate回调方法中,当ARKit找到一个新的锚点时,我们可以创建我们的新plane:

    if (![anchor isKindOfClass:[ARPlaneAnchor class]]) {

    return;

    Plane *plane = [[Plane alloc] initWithAnchor: (ARPlaneAnchor *)anchor];

    [node addChildNode:plane];

    更新Plane SceneKit,使得我们在移动时有更稳定的效果。

    didUpdateNode:(SCNNode *)node

    // See if this is a plane we are currently rendering

    Plane *plane = [self.planes objectForKey:anchor.identifier];

    if (plane == nil) {

    [plane update:(ARPlaneAnchor *)anchor];

    更新plane的宽度和高度。

    - (void)update:(ARPlaneAnchor *)anchor {

    self.planeGeometry.width = anchor.extent.x;

    self.planeGeometry.height = anchor.extent.z;

    self.position = SCNVector3Make(anchor.center.x, 0, anchor.center.z);

    运行,会发现如下一些效果。

    添加物理效果

    效果预览:

    在这个演示中,当用户在屏幕上单击时,我们执行一段代码,这个代码很简单,ARSCNView包含一个hitTest方法,可以通过获得的屏幕坐标点,从相机中心通过该点投射一条射线,并返回结果:

    - (void)handleTapFrom: (UITapGestureRecognizer *)recognizer {

    CGPoint tapPoint = [recognizer locationInView:self.sceneView];

    NSArray *result = [self.sceneView hitTest:tapPoint types:ARHitTestResultTypeExistingPlaneUsingExtent];

    if (result.count == 0) {

    ARHitTestResult * hitResult = [result firstObject];

    [self insertGeometry:hitResult];

    通过上述代码,我们可以得到射线与平面交叉点的世界坐标,并在该位置放置一些3D模型等等。

    - (void)insertGeometry:(ARHitTestResult *)hitResult {

    float dimension = 0.1;

    SCNBox *cube = [SCNBox boxWithWidth:dimension

    height:dimension

    length:dimension

    chamferRadius:0];

    SCNNode *node = [SCNNode nodeWithGeometry:cube];

    node.physicsBody = [SCNPhysicsBody

    bodyWithType:SCNPhysicsBodyTypeDynamic

    shape:nil];

    node.physicsBody.mass = 2.0;

    node.physicsBody.categoryBitMask = CollisionCategoryCube;

    float insertionYOffset = 0.5;

    node.position = SCNVector3Make(

    hitResult.worldTransform.columns[3].x,

    hitResult.worldTransform.columns[3].y + insertionYOffset,

    hitResult.worldTransform.columns[3].z

    );

    [self.sceneView.scene.rootNode addChildNode:node];

    [self.boxes addObject:node];

    我们给每个立方体一个physicsBody,它是SceneKit的物理引擎。

    接下来,我们实现停止平面检测的功能。用户用两个手指按住屏幕1秒钟,那么我们会隐藏所有的平面并关闭平面检测。

    ARWorldTrackingSessionConfiguration *configuration = (ARWorldTrackingSessionConfiguration *)self.sceneView.session.configuration;

    configuration.planeDetection = ARPlaneDetectionNone;

    [self.sceneView.session runWithConfiguration:configuration];

    相关文章

      网友评论

          本文标题:ARkit 实战教程(Xcode开发)

          本文链接:https://www.haomeiwen.com/subject/irljdxtx.html