ARkit 实战教程(Xcode开发)

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开发))