• ARKit的使用示例


    #import "ViewController.h"
    #import <ARKit/ARKit.h>
    
    @interface ViewController ()
    <ARSCNViewDelegate,ARSessionDelegate>
    
    #define YDUseARConfiguration ARWorldTrackingConfiguration //ARBodyTrackingConfiguration
    
    @property (nonatomic, strong) ARSession *session;
    @property (nonatomic, strong) YDUseARConfiguration *configuration;
    @property (nonatomic, strong) ARSCNView *arView;
    @property (nonatomic, strong) SCNNode *fromNode;
    @property (nonatomic, strong) SCNNode *toNode;
    @property (nonatomic, strong) SCNNode *planeNode;
    @property (nonatomic, strong) SCNNode *zeroNode;
    @property (weak, nonatomic) IBOutlet UILabel *messageLabel;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        if ([YDUseARConfiguration supportsFrameSemantics:ARFrameSemanticPersonSegmentationWithDepth]) {
            NSLog(@"YDUseARConfiguration");
        }
        if ([ARFaceTrackingConfiguration supportsFrameSemantics:ARFrameSemanticPersonSegmentationWithDepth]) {
            NSLog(@"ARFaceTrackingConfiguration");
        }
        if ([ARBodyTrackingConfiguration supportsFrameSemantics:ARFrameSemanticPersonSegmentationWithDepth]) {
            NSLog(@"ARBodyTrackingConfiguration");
        }
        [self.view addSubview:self.arView];
        [self.view sendSubviewToBack:self.arView];
    }
    
    - (IBAction)resetPointFunc:(UIButton *)sender {
        [self.fromNode removeFromParentNode];
        [self.toNode removeFromParentNode];
        self.fromNode = nil;
        self.toNode = nil;
    }
    
    
    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        [self.session runWithConfiguration:self.configuration];
    }
    
    - (void)viewWillDisappear:(BOOL)animated {
        [self.session pause];
    }
    
    - (YDUseARConfiguration *)configuration {
        if (!_configuration) {
            _configuration = [YDUseARConfiguration new];
            _configuration.planeDetection = ARPlaneDetectionHorizontal;
        }
    
        return _configuration;
    }
    
    - (ARSCNView *)arView {
        if (!_arView) {
            _arView = [[ARSCNView alloc] initWithFrame:self.view.bounds];
            _arView.session = self.session;
            _arView.delegate = self;
            _arView.scene = [SCNScene new];
            _arView.debugOptions = ARSCNDebugOptionShowFeaturePoints;//debug模式,显示追踪到的点位
        }
        return _arView;
    }
    
    - (ARSession *)session {
        if (!_session) {
            _session = [ARSession new];
            _session.delegate = self;
        }
        return _session;
    }
    
    - (SCNMaterial *)materialNamed:(NSString *)name {
        // 创建一个模型贴图立方体
        static NSMutableDictionary *materials = nil;
        if (!materials) {
            materials = [NSMutableDictionary new];
        }
        SCNMaterial *mat = materials[name];
        if (mat) {
            return mat;
        }
        mat = [SCNMaterial new];
        mat.lightingModelName = SCNLightingModelPhysicallyBased;
        mat.diffuse.contents = [UIImage imageNamed:@"tron-albedo"];
        mat.roughness.contents = [UIImage imageNamed:@"tron-albedo"];
        mat.metalness.contents = [UIImage imageNamed:@"tron-albedo"];
        mat.normal.contents = [UIImage imageNamed:@"tron-albedo"];
        mat.diffuse.wrapS = SCNWrapModeRepeat;
        mat.diffuse.wrapT = SCNWrapModeRepeat;
        mat.roughness.wrapS = SCNWrapModeRepeat;
        mat.roughness.wrapT = SCNWrapModeRepeat;
        mat.metalness.wrapS = SCNWrapModeRepeat;
        mat.metalness.wrapT = SCNWrapModeRepeat;
        mat.normal.wrapS = SCNWrapModeRepeat;
        mat.normal.wrapT = SCNWrapModeRepeat;
        
        materials[name] = mat;
        return mat;
    }
    
    - (void)renderer:(id <SCNSceneRenderer>)renderer didAddNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {
        if ([anchor isKindOfClass:[ARPlaneAnchor class]]) {
    //        if (self.planeNode) {
    //            [self.planeNode removeFromParentNode];
    //        }
    //
    //        ARPlaneAnchor *planeAnchor = (ARPlaneAnchor *)anchor;
    //        SCNBox *plane = [SCNBox boxWithWidth:3.0 height:3.0 length:3.0 chamferRadius:0];
    //        SCNMaterial *transparentMaterial = [SCNMaterial new];
    //        transparentMaterial = [self materialNamed:@"tron"];
    //        plane.materials = @[transparentMaterial, transparentMaterial, transparentMaterial, transparentMaterial, transparentMaterial, transparentMaterial];
    //        SCNNode *planeNode = [SCNNode nodeWithGeometry:plane];
    //        planeNode.position = SCNVector3Make(
    //                                            node.position.x,
    //                                            node.position.y,
    //                                            node.position.z - 6.0
    //                                            );
    //        [node addChildNode:planeNode];
    //        self.planeNode = planeNode;
            // Y轴线
            SCNTube *tubey = [SCNTube tubeWithInnerRadius:0 outerRadius:0.001 height:50];
            tubey.firstMaterial.diffuse.contents = [UIColor greenColor];
            SCNNode *tubeNodey = [SCNNode nodeWithGeometry:tubey];
            tubeNodey.position = SCNVector3Make(0, 2.5, 0);
            [node addChildNode:tubeNodey];
            // X轴线
            SCNTube *tubex = [SCNTube tubeWithInnerRadius:0 outerRadius:0.001 height:50];
            tubex.firstMaterial.diffuse.contents = [UIColor redColor];
            SCNNode *tubeNodex = [SCNNode nodeWithGeometry:tubex];
            tubeNodex.position =  SCNVector3Make(0, 0, 0);
            tubeNodex.rotation = SCNVector4Make(1, 0, 0, M_PI/2);
            [node addChildNode:tubeNodex];
            
            // Z轴线
            SCNTube *tubez = [SCNTube tubeWithInnerRadius:0 outerRadius:0.001 height:50]; // 声明一个形体(此处为圆柱体)
            tubez.firstMaterial.diffuse.contents = [UIColor blueColor];
            SCNNode *tubeNodez = [SCNNode nodeWithGeometry:tubez]; // 通过上述形体创建一个物体
            tubeNodez.position =  SCNVector3Make(0, 0, 0);
            tubeNodez.rotation = SCNVector4Make(0, 0, 1, M_PI/2);
            [node addChildNode:tubeNodez];
            
            _zeroNode = node; // ARAnchor这个是AR世界的一个点对象 node是坐标原点
            
            // 设置下面两句不再寻找平面,后面计算参照现有平面
            self.configuration.planeDetection = ARPlaneDetectionNone;
            [self.arView.session runWithConfiguration:self.configuration];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                self.messageLabel.text = @"已经寻找到了一个平面";//[NSString stringWithFormat:@"planeAnchor.extent.x:%.4f", planeAnchor.extent.x];
            });
        }
    }
    
    - (void)renderer:(id<SCNSceneRenderer>)renderer didRemoveNode:(SCNNode *)node forAnchor:(ARAnchor *)anchor {
        if (self.planeNode == self.planeNode) {
            dispatch_async(dispatch_get_main_queue(), ^{
                self.messageLabel.text = @"请寻找一个平面";
                [self resetPointFunc:nil];
                if (self.planeNode) {
                    [self.planeNode removeFromParentNode];
                }
            });
        }
    }
    
    - (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame {
        ARBody2D *body = [frame detectedBody];
        if (body) {
        
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.zeroNode) {
    //            SCNVector3 zerolocation = [self.arView projectPoint:self.zeroNode.worldPosition];
    //            self.messageLabel.text = [NSString stringWithFormat:@"%.2f,%.2f",zerolocation.x,zerolocation.y];
            }
        });
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        CGPoint point = [touches.anyObject locationInView:self.arView];
    //    NSArray<ARHitTestResult *> *result = [self.arView hitTest:point types:ARHitTestResultTypeFeaturePoint];
    //    if (result.count != 0) {
    //        // If there are multiple hits, just pick the closest plane
    //        ARHitTestResult * hitResult = [result firstObject];
        if (!self.zeroNode) {
            return;
        }
        // 将三维点转为二位平面点坐标+深度(z值)
        SCNVector3 zeroLocation = [self.arView projectPoint:self.zeroNode.worldPosition];
        // 将屏幕点+深度转为AR世界中的点坐标
        SCNVector3 location = [self.arView unprojectPoint:SCNVector3Make(point.x, point.y, zeroLocation.z)];
            if (!self.fromNode) {
                SCNSphere *calculareTube = [SCNSphere sphereWithRadius:0.01];
                calculareTube.firstMaterial.diffuse.contents = [UIColor colorWithRed:255 green:255 blue:0 alpha:0.6];
                self.fromNode = [SCNNode nodeWithGeometry:calculareTube];
                //    设置节点的位置为捕捉到的平地的锚点的中心位置  SceneKit框架中节点的位置position是一个基于3D坐标系的矢量坐标SCNVector3Make
                self.fromNode.position = location;
    //            SCNVector3Make(
    //                                                      hitResult.worldTransform.columns[3].x,
    //                                                      hitResult.worldTransform.columns[3].y,
    //                                                      hitResult.worldTransform.columns[3].z
    //                                                      );
                [self.arView.scene.rootNode addChildNode:self.fromNode];
            } else {
                if (self.toNode) {
                    [self.toNode removeFromParentNode];
                }
                SCNSphere *calculareTube = [SCNSphere sphereWithRadius:0.01];
                calculareTube.firstMaterial.diffuse.contents = [UIColor colorWithRed:255 green:0 blue:255 alpha:0.6];
                self.toNode = [SCNNode nodeWithGeometry:calculareTube];
                //    设置节点的位置为捕捉到的平地的锚点的中心位置  SceneKit框架中节点的位置position是一个基于3D坐标系的矢量坐标SCNVector3Make
                self.toNode.position = location;
    //            SCNVector3Make(
    //                                                      hitResult.worldTransform.columns[3].x,
    //                                                      hitResult.worldTransform.columns[3].y,
    //                                                      hitResult.worldTransform.columns[3].z
    //                                                      );
                [self.arView.scene.rootNode addChildNode:self.toNode];
                
                SCNNode *previousNode = self.fromNode;
                SCNNode *currentNode = self.toNode;
    
                CGFloat distance = sqrt((previousNode.position.x-currentNode.position.x)*(previousNode.position.x-currentNode.position.x)+(previousNode.position.z-currentNode.position.z)*(previousNode.position.z-currentNode.position.z));
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    self.messageLabel.text = [NSString stringWithFormat:@"上两点距离:%f 米",distance];
                });
            }
            
    //    }
        
    }
    
    @end

     一个很好的demo地址  https://www.jianshu.com/p/46ded5b1fa00

    //画线(这里无法设定线条的宽度)
        func line(to vector:SCNVector3,color:UIColor) -> SCNNode {
            let indices : [UInt32] = [0,1]//指数
            let source = SCNGeometrySource(vertices: [self,vector]) // 创建一个几何容器
    
            let element = SCNGeometryElement(indices: indices, primitiveType: .line)//用线的方式来创造一个几何元素(线)
            let geomtry = SCNGeometry(sources: [source], elements: [element])//几何
            geomtry.firstMaterial?.diffuse.contents = color//渲染颜色
            let node = SCNNode(geometry: geomtry)//返回一个节点
            return node
            
        }
  • 相关阅读:
    如何在帮助页面添加测试工具
    如何给你的ASP.NET页面添加HelpPage
    各种序列化库的性能数据
    Quartz.NET配置
    T-SQL中只截取日期的日期部分和日期的时间部分
    sql 根据指定条件获取一个字段批量获取数据插入另外一张表字段中+MD5加密
    读取图片数据流转换成图片
    T-SQL Transact-SQL 编程
    Python 链接Mysql数据库
    c 生成随机不重复的整数序列
  • 原文地址:https://www.cnblogs.com/yuxiaoyiyou/p/14047510.html
Copyright © 2020-2023  润新知