zoukankan      html  css  js  c++  java
  • ARKit__2_尺子项目

    一、ARkit尺子项目学到了什么?

    先看效果,如下图:

    • 1.SCNVector3本质就是一个三维坐标
    • 2.画线的步骤就是:拿到2个坐标 --> 选择“线”这个“几何” --> 渲染--> 最后生成节点。这个过程待会会详细的代码解释。
    • 3.坐标之间的转换,世界坐标、摄像头。这个和SLAM里面的很类似。
    • 4.SCNText,一个很特殊的“几何”,如图中的8.52cm就是用SCNText表示的,当然最后都会放到节点里面去。
    • 5.对节点的使用更加的清晰,每个点、每根线、以及描述的text都会被添加到节点,然后ARSCNView的scene.rootNode.addChildNode(node)

    二、下面开始具体的讲解整个实现的逻辑和流程。 

     先解释下:图中的 白色"+"是始终位于屏幕的正中间的,整个项目都是以这个点为瞄准点。

    开始第一步:

    extension ARSCNView {
        //拿到三维坐标
        func worldVector(for position:CGPoint) ->SCNVector3?{
            let results = self.hitTest(position, types: [.featurePoint])
            guard let result = results.first else {
                return nil
            }
            // 获取点的坐标,类型是matrix_float4x4 ,调这个方法就可以拿到相机的镜头
            return SCNVector3.positionTransform(result.worldTransform)
        }
    }
    //  拿到镜头的坐标
        static func positionTransform(_ transform: matrix_float4x4) -> SCNVector3{
    
            return SCNVector3Make(transform.columns.3.x, transform.columns.3.y, transform.columns.3.z)
    
        }
    
    •  1.点击手机屏幕,然后获取到一个CGPoint,
    •  2.通过 self.hitTest(position, types: [.featurePoint]).first 就拿到一个 为matrix_float4x4类型的坐标。
    •  3.通过positionTransform方法得到镜头的坐标。
    实话里面到底是如何实现的,我也很想知道。我通过之前对SLAM的学习,大概知道,里面的矩阵变换的过程。对于iOS开发者,知道需要转换即可,具体的深究留到自己对AR的掌握到了一定程度的时候会比较好。

    第二步:画线

    //画线的方法
        func drawLine( vector: SCNVector3, color:UIColor) -> SCNNode {
            let indices: [UInt32] = [0,1] // 指数    
    //0指:一维,表示点
    //1指:二维,表示线 //数据来源 let source = SCNGeometrySource(vertices: [self,vector]) //画什么样的几何---选择线 let element = SCNGeometryElement(indices: indices, primitiveType: .line) let geometry = SCNGeometry(sources: [source], elements: [element]) geometry.firstMaterial?.diffuse.contents = color let node = SCNNode(geometry: geometry) return node }
    •  1.数据源:两个坐标
    • 2.选择几何模型--线
    • 3.生成节点 

    第三步:什么时候绘制了?

    实在ARSCNViewDelegate中的渲染方法里面进行绘制。具体代码:

     {
        func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {     
            DispatchQueue.main.async {
                self.scanWorld()
            }
        }
     //扫描外部真实世界,开始测量
        func scanWorld() {
            //我们以中间点为开始点,也就是那个十字标图片指的点为开始的点。
            guard let worldPosition = sceneView.worldVector(for: view.center) else {
                return
            }
                 vectorStart = worldPosition
                  currentLine = Line.init(sceneView: self.sceneView, startVector: vectorStart, unit: self.unit)
                //设置结束的节点
                vectorEnd = worldPosition
                currentLine?.update(to: vectorEnd)
                infoLabel.text = currentLine?.distance(to: vectorEnd) ?? "是同一个点"    
            }
        }
    

    进行扫描真实的世界,在scanWorld()方法里面调用绘制的方法进行绘制。

    三、总结一下思路

    • 选择开始的点
    • 然后开始绘制并计算长度
    • 再次点击屏幕获取终点--结束。

    实现的难点:想到坐标的转换、然后绘制的时机、对节点的使用的掌握。

    项目代码,我后续会传到GitHub,后面在一起加。 

    但行好事,莫问前程。
  • 相关阅读:
    EasyUI基础searchbox&progressbar(搜索框,进度条)
    git 仓库
    “农民代码”讨论
    多线程和多进程之间的区别
    move_uploaded_file
    在form里面,放了四个UEditor,怎么在后台分别获取它们值
    ThinkPHP模板IF标签用法详解
    Tp框架查询分页显示与全部查询出来显示运行时间快慢有区别吗?
    百度UEditor基本使用
    织梦DedeCms获取当前页面URL地址的调用方法
  • 原文地址:https://www.cnblogs.com/yuhui-snail/p/8515335.html
Copyright © 2011-2022 走看看